- 首先,在领域建模过程中不应将概念与实现割裂开来
- 反对'先建设,后实现',应该随时间进行
迭代升级
(开发人员和领域人员以及专业人员共同协助完成) - DDD和敏捷开发互相增强
- 重点2,3,9,14章
运用领域模型
- 有效建模的要素
- 模型和实现的绑定(正因为要实现,建模不只是领域专家的事情,还需要开发人员参与)
- 建立了一种基于模型的语言(领域专家和开发人员可以持续基于模型语言进行讨论和展开)
- 开发一个具有丰富知识的模型库(业务活动和规则都是领域的核心)
- 不停提炼模型(模型不是不变的,需要不停迭代和更新)
- 头脑风暴和实验(不断改造和创新)
-
模型获取的知识远远不只是“发现名词”,业务活动和规则如同涉及到的实体一样,都是领域的核心。
知识丰富的设计-策略.png - ubiquitous language(通用语言)
开发人员之间的对话、领域专家之间的讨论以及代码本身所表达的内容都基于同一种语言,都来自于一个共享的领域模型。 - 图
- 简单、非正式的UML图能够维系整个讨论。
- 图是一种沟通和解释手段,它们可以促进头脑风暴。简洁的小图能够很好地实现这些目标,而涵盖整个对象模型的综合性大图反而失去了沟通或解释能力,因为它们将读者淹没在大量细节之中,加之这些图也缺乏目的性。
- 通常的用法是以图为主,辅以文本注释;而我更愿意以文本为主,用精心挑选的简化图作为说明。
- 文档
- 文档应作为代码和口头交流的补充
- 文档应当鲜活并保持最新
绑定模型和实现
- Model-Driven Design
从模型中获取用于程序设计和基本职责分配的术语。让程序代码成为模型的表达,代码的改变可能会是模型的改变。而其影响势必要波及接下来相应的项目活动。
- 模型没有派上用场的主要两个原因
- 模型的一些意图在传递过程中丢失了,模型的整体效果受细节的影响很大(在第二部分-模型驱动的设计块,第三部分-通过重构来加深理解会有具体的讨论)。
- 模型与程序实现及技术互相影响。
- 大型项目仍然需要技术负责人来协调高层次的设计和建模,并帮助做出最困难或最关键的决策(本书的第四部分描述的就是这种决策)
模型驱动的设计块
软件中所表示的模型
- 模型的关系
至少有3中方法使得关联容易控制
- 规定一个遍历方向(很多多对多的可以从重要性方面抽离成一对多的关系)
- 添加一个限定符,减少多重关联(一对多添加限定条件之后可以抽离成一对一的关系)
- 消除不必要的关联(清除那些对当前工作或模型对象的基本含义来说不重要的关联)
- Entity(实体-reference object-引用对象)
最基本的职责是确保连续性,以便使其行为更清楚且可预测(需要合理设计标识-id)。应该摆脱这些细枝末节,抓住ENTITY对象定义的最基本特征,尤其是那些用于识别、查找或匹配对象的特征。只添加那些对概念至关重要的行为和这些行为所必需的属性。此外,应该将行为和属性转移到与核心实体关联的其他对象中。
- Value Object
用于描述领域的某个方面而本身没有概念标识的对象称为VALUE OBJECT(值对象)。VALUE OBJECT被实例化之后用来表示一些设计元素,对于这些设计元素,我们只关心它们是什么,而不关心它们是谁。应该尽量消除Value Object的双向关联。
- Service
Service分为应用层service和领域层service。应用层和Entity,ValueObject紧密关联,负责对领域对象的行为进行协调。
优秀的领域service具有下面三个特征:
- 与领域概念相关的操作
不是
ENTITY或VALUE OBJECT的一个自然组成部分。 - 接口是根据领域模型的其他元素定义的。
-
操作是无状态的(幂等)。
service分层.png
领域对象的生命周期
- 聚合(AGGREGATE)
我 们 应 该 将 ENTITY 和 VALUE OBJECT 分 门 别 类 地 聚 集 到AGGREGATE中,并定义每个AGGREGATE的边界。在每个AGGREGATE中,选择一个ENTITY作为根,并通过根来控制对边界内其他对象的所有访问。只允许外部对象保持对根的引用。对内部成员的临时引用可以被传递出去,但仅在一次操作中有效。由于根控制访问,因此不能绕过它来修改内部对象。
- 工厂(FACTORY)
应该将创建复杂对象的实例和AGGREGATE的职责转移给单独的对象,这个对象本身可能没有承担领域模型中的职责,但它仍是领域设计的一部分。提供一个封装所有复杂装配操作的接口,而且这个接口不需要客户引用要被实例化的对象的具体类。在创建AGGREGATE时要把它作为一个整体,并确保它满足固定规则。
好的工厂有以下两个特征:
- 每个创建方法都是原子的,而且要保证被创建对象或AGGREGATE的所有固定规则。FACTORY生成的对象要处于一致的状态。
- FACTORY应该被抽象为所需的类型,而不是所要创建的具体类。
- 存储库(REPOSITORY)
这里相当于mybatis里面的mapper,也就是dao层。只为那些确实需要直接访问的AGGREGATE根提供REPOSITORY。让客户始终聚焦于模型,而将所有对象的存储和访问操作交给REPOSITORY来完成。
-
一个货运跟踪示意图
在一些关联上对遍历方向进行了约束.png
通过重构来加深理解
- 如何为那些不太明显的概念建模
-
显示的约束
为显式表达超订策略而重构的模型.png - 将过程建模为领域规则
首先要说明的是,我们都不希望过程变成模型的主要部分。在这里,我们讨论的是存在于领域中的过程,我们必须在模型中把这些过程表示出来。否则当这些过程显露出来时,往往会使对象设计变得笨拙。
-
模式-SPECIFICATION(类似java里的predicate)
SPECIFICATION.png