结论先行

在 DDD 中,通用语言是以限界上下文为边界的。如果一个产品或者项目有多个限界上下文,我们就需要为每个限界上下文定义通用语言。限界上下文提供了一个语义边界,来保持通用语言和领域概念的一一对应关系。这个约束解决了现实世界中同样的名词在不同场景、时机下对应不同的业务概念所带来的歧义问题,帮助团队在使用通用语言交流的时候可以无歧义沟通。

初尝“通用语言”

最初我对于如何构建通用语言的认识,来自于《领域驱动设计》第一章中的案例。这个案例生动的展示了开发人员如何在和领域专家的沟通过程中,建立了双方理解一致的通用语言,并且使用这个语言来进行双方的沟通。基于那个案例,我当时对构建通用语言的理解就是要:

  • 技术人员使用业务人员的用语作为开发词汇;
  • 划分好聚合,将这些词汇关联到聚合上;
  • 技术人员要将这些词汇映射到代码实现中;
  • 这些词汇会随着项目的发展一点点扩展;

带着这份理解,我在曾经负责过的小型项目上做了一些实践,效果都很不错。在很长一段时间,团队的开发人员体会到了在和业务人员交流时候心有灵犀、会心一笑的快感;也很少听到“这个东西不是我要的”这类批评了。

“通用语言”遇到同名词汇时就变得不清不楚了

然而,当我来到ThoughtWorks参与到一些几十号人的项目时,我发现根据这个原则构建起来的通用语言,在遇到同名多义的词汇时,就无法保证团队内部的沟通是无歧义的。而这种歧义又会导致团队成员说着同样的话想着不同的事情的情况出现,例如:

  • 同名的业务词汇与实际业务关系不清:“为什么不能给销售订单增加一个是否投诉的字段,界面上都是显示在销售订单上的”——销售订单到底是个什么东西,能干什么不能干什么是怎么确定的?
  • 同名的业务词汇与不同的业务词汇关联:“我在销售订单付款后改变了买家信息,为什么我看销售订单的预定里的买家也发生了改变”——这里说的买家信息有几个?
  • 同名的业务词汇之间的关系不清楚:“为什么我变更了profile 上的买家地址,销售订单上的买家地址就跟着改变了” ——这里说订单上的买家地址和profile 上的买家地址是一个什么关系?

通过添加约束消除歧义

下图是 DDD 概念的一个元模型图。从图的左下角,我们可以看到在构建通用语言时,还有两个额外的约束条件:子域和限界上下文。

在 DDD 中,软件的核心是其为客户解决领域相关的问题的能力

这里的领域,就是指软件系统要解决的实际问题相关的东西的集合。

例如:为一个电子商务公司开发一个电商系统,我们就需要围绕这个盈利模式的运营方式、业务规则,比如如何进货,如何促销,如何物流等等了解这个电子商务公司的盈利模式,所有和业务相关的东西都属于领域。

领域分为问题域和解决方案域两部分。

为了分解问题域的复杂度,问题域又会被拆解为多个子域,每个子域都要明确待解决的业务问题和业务流程,以及通过解决业务问题为企业带来了什么样的业务价值(这个是因,业务流程和要解决的业务问题是果)。

在清晰的定义子域后,我们就可以建立通用语言来提取该子域的领域知识,并基于通用语言为解决问题建立领域模型。

一个领域模型会存在于一个限界上下文中。限界上下文在 DDD 中用来定义模型的适用范围、模型的用途、以及在何处保持一致,限界上下文会让团队明确模型的职责边界是什么。同时,通用语言被限定在限界上下文中;限界上下文提供了一个语义边界,在每个限界上下文内通用语言的每个词汇必须和领域概念一一对应。

理想条件下,子域和限界上下文是一一对应。但是子域划分的粒度,遗留系统的现状,语言的歧义,团队结构等子域和限界上下文对应可能是1:N 或者 N:N 的。

通过限界上下文间的映射,上下文中的多个模型会协作以满足系统需求。我们也可以了解在不同上下文中的同名词汇是否存在关系,存在什么样的关系。

对通用语言而言,子域解释了通用语言和现实世界业务活动的关系;限界上下文提供了一个语义边界,来保持通用语言和领域概念的一一对应关系;上下文映射则提供了不同限界上下中的通用语言的转换关系。

来解决下前文的问题

前文所述的订单及订单的相关概念存在着歧义,我们来看下通过子域、限界上下文和上下文映射是怎么消除这些歧义的:

因为同名的业务词汇与实际业务关系不清导致的疑惑

“为什么不能在销售订单中增加一个是否投诉的字段,界面上都是显示在销售订单上的”

假设,这里所说的销售订单存在于销售子域下,那么这个订单应该解决的是销售过程中的问题。订单的生命周期以销售开始到销售终止。一般而言投诉属于售后环节,在销售订单上声明是否投诉字段,意味着销售订单的职能突破了销售子域。UI 上的销售订单展示了聚合的信息,和同名的领域模型不一定保持一致。

因为同名的业务词汇与不同的业务词汇关联导致的疑惑

“我在订单付款后改变了买家信息,为什么我看订单的预定里的买家也发生了改变”

在订单上有两种买家信息,可以通过在不同的上下文中隔离来区别这两个拥有相同含义但却是不同词汇的词汇。在销售子域中建立两个上下文,分别为预定有界上下文和购买上下文,把订单领域模型拆分到这两个上下文中。在不同的上下文中,订单都有自己的买家信息,就解决了“在订单付款后改变了买家信息,为什么我看订单的预定里的买家也发生了改变”这个问题。

因为同名的业务词汇之间的关系不清楚导致的疑惑

“为什么我变更了profile 上的买家地址,订单上的买家地址就跟着改变了”

订单存在于购买上下文,profile 存在于身份信息上下文中,购买上下文和身份信息上下文存在映射关系,在订单创建时候从身份信息上下文复制买家地址,在订单中单独保存。这样就解决了“为什么我变更了profile 上的买家地址,订单上的买家地址就跟着改变了” 的问题。

引用:

  1. 《领域驱动设计》
  2. 《实现领域驱动设计》
  3. 当Subdomain遇见Bounded Context
  4. DDD的终极大招——By Experience
  5. 《领域驱动设计学习:领域、子域、限界上下文》

文/ThoughtWorks王岩

更多精彩洞见,请关注微信公众号:ThoughtWorks洞见

转载于:https://juejin.im/post/5cb944c3f265da0374187693

重读领域驱动设计——如何说好一门通用语言相关推荐

  1. DDD(domain driven design)-领域驱动设计

    domain driven design-领域驱动设计 领域驱动设计概述 背景 软件架构模式的演进 概念 分层架构与六边形架构 分层分包 复杂是我们软件生涯的一生之敌. 分层架构 & 面向过程 ...

  2. 领域驱动设计,为何死灰复燃?

    作者简介 张逸,曾先后就职于中兴通讯.惠普 GDCC.中软国际.ThoughtWorks 等大型中外企业,任职角色为高级软件工程师.架构师.技术总监.首席咨询师. 一.领域驱动设计为何又死灰复燃焕发青 ...

  3. 如何系统学习领域驱动设计?

    一.领域驱动设计为何又焕发青春? 领域驱动设计(Domain Driven Design,DDD)确实已不再青春,从 Eric Evans 出版了划时代的著作<领域驱动设计>至今,已有将近 ...

  4. 领域驱动设计,为何又死灰复燃了?

    作者简介 张逸,曾先后就职于中兴通讯.惠普 GDCC.中软国际.ThoughtWorks 等大型中外企业,任职角色为高级软件工程师.架构师.技术总监.首席咨询师. 一.领域驱动设计为何又死灰复燃焕发青 ...

  5. 如何系统学习领域驱动设计(DDD)?

    作者简介 张逸,曾先后就职于中兴通讯.惠普 GDCC.中软国际.ThoughtWorks 等大型中外企业,任职角色为高级软件工程师.架构师.技术总监.首席咨询师. 精通包括 Java.Scala.Py ...

  6. 演进架构中的领域驱动设计

    原文链接:http://www.infoq.com/cn/articles/ddd-evolving-architecture 作者 Mat Wall and Nik Silver 译者 王丽娟 发布 ...

  7. 微服务架构与领域驱动设计应用实践

    本篇文章一共分为三个部分,分别是微服务架构的演进过程.具体实践微服务的应用技术和领域驱动设计的意识转变.微服务架构已经渗透到互联网应用的方方面面,而领域驱动设计也逐渐被业界所接收. 微服务架构几乎都是 ...

  8. 领域驱动设计(2)怎么使用沟通

    领域驱动设计(2)怎么使用沟通 废话 沟通的重要性:沟通很重要,不论在生活中,还是工作中沟通处理不好,我想为人处事这块肯定有问题.LZ接触社会比较早,做过焊工.销售.跑过业务...,一路走来在沟通上同 ...

  9. 万字长文助你上手软件领域驱动设计 DDD

    作者:faryrong,腾讯 CSIG 后台开发工程师 最近看了一本书<解构-领域驱动设计>,书中提出了领域驱动设计统一过程(DDDRUP),它指明了实践 DDD 的具体步骤,并很好地串联 ...

  10. Hacker News热文:请停止学习框架,学习领域驱动设计(DDD)(获500个点赞)

    在 Hacker News 上获得接近 500 个点赞的一篇名为<停止学习框架>的文章称: 我们是程序员,每天都在了解最新的技术,每天都在学习编程语言.框架和库,因为我们知道的现代编程工具 ...

最新文章

  1. 双边滤波--OpenCV实现
  2. cdecl、stdcall、fastcall函数调用约定区别
  3. Angular 不同种类 Module 的介绍
  4. fat32 linux 打包工具_11款最棒的Linux数据恢复工具发布啦!
  5. 《修改代码的艺术》读书笔记一
  6. python pandas使用pipe管道增强代码可读性
  7. python zip函数_Python zip()函数
  8. Unable to round-trip http request to upstream: EOF
  9. 【图像处理】基于matlab GUI美颜系统【含Matlab源码 809期】
  10. ATLAS.ti 9(质性研究分析软件)官方中文版V9.0.20.0 | 质性分析软件Atlas.ti下载 | atlas软件是什么软件
  11. 谈谈我对Spring Bean 生命周期的理解
  12. jquery-migrate.min.js兼容jQuery版本
  13. 架设NOD32升级服务器
  14. 目标检测从两阶段R-CNN系列到单阶段YOLO系列精炼
  15. Fault tolerant heap shim applied to current process. This is usually due to previous crashes
  16. 20210507新版友价框架制作江雀网店交易天猫淘宝京东拼多多唯品会网店转让送手机版系统
  17. 考研政治——马克思辩证法中的两大特征和五大范畴
  18. 欢迎扫码进群加入或关注ServiceComb社区
  19. cv2.erode函数
  20. 安装sql server走过的弯路,收集了一些安装sql遇到的问题

热门文章

  1. 常见 HTTP/FTP/WebSocket 错误代码大全 - 转
  2. Xcode CoreData 存储报错问题。
  3. mysql自增字段重排 或 归零
  4. POJ 1611 The Suspects(简单并查集)
  5. 特殊字符搜索网站 http://symbolhound.com/
  6. HDU 1358 (所有前缀中的周期串) Period
  7. 使用ASP.NET Membership
  8. SoundSource for Mac - 音频控制工具
  9. 发力多人在线游戏!PS5有望2020年E3展会亮相!
  10. 了解java虚拟机mdash;串行回收器(6)