总览:本章主要介绍为对象范式提供的常见构造块。从如何设计和简化关联开始,然后着重区别三种模型元素,Entity、Value Object、Service。
对象关系的确认是很有技巧的,如果无差别保持所有关系,那么存储会变得极其复杂,因此开始会引入简化关联的技术。
事实上,看上去定义领域对象是很容易的,因为对象本身是一个很直观的概念。但是彻底搞清楚不同对象的特点是有点难度的。为此需要划分三种模型元素。
简单来说,Entity值具有连续性和标识(唯一性)的事务。而ValueObject则通常表示只关心属性而不关心唯一性的情况。Service则表示无状态的动作和操作。
高内聚和低耦合的概念在概念建模的过程中依然有用,因此就得到了Model/Package的概念。
关联简化 和 Model/Package 为处理复杂建模提供了指导性方向。
建模范式:面向对象建模
在了解模型元素之前,先了解一下DDD的建模范式,也就是面向对象建模,这是主流的建模方式。对象建模在简单性和复杂的表达能力之间实现了很好的平衡。
面向对象流行的原因在于:
1:大部分人都比较容易理解面向对象的基本知识,即便是非技术人员
2:功能丰富,表达能力强
3:发展成熟并得到广泛支持,有成熟的工具和框架支持,有良好的行业标准集成方案,大部分其他技术都能很好协同
4:开发者社区和设计文化成熟,熟练的开发人员也很多
对象世界的非对象
然而,即便对象建模的技术已经是我们的主要选择,有时候还是无法避免采用其他范式。常见的有这么几种:
- 数学问题就很难通过对象来建模。
- 规则引擎,特别是针对系统的全局规则,很难通过对象来表达。
- 关系型数据存储,很常见的存储方式
领域或者技术实现必须包含上述的情况时,我们就必须考虑将对象范式和其他范式结合起来服务于同一个模型,而不是将模型割裂开用不同范式表达不同部分。
在必须要这做的情况下,坚持使用健壮的通用语言,在不同范式实现的部分使用统一的名称,坚持用通用语言来讨论将有助于消除不同建模方式带来的问题。
但是在使用不同范式建模之前,请确保面向对象范式真的不能用了,尽管有些对象不能显著的表示为对象,但是不见得真的不能用对象建模,第九章会讨论一些非常规类型的概念建模。
关联
模型中每个关联,都应该在实现过程中有对应的属性指向。这个指向可以是简单直接的对象引用,或者是数据库层面的关联设计。也可能是在持久层表现出关联,而在内存中表现成引用。
例如一个一对多关联,可以是一个集合类型的成员变量来表示,也可以是数据库外键关联而通过一个特定的方法直接能访问到。这两种方式反应的是同样的模型,只是实现不同。
现实中存在大量的多对多关联,而且很多关联是双向的(A可以指向B,B也可以指向A)。这两种情况都会导致模型复杂化。但是,很少会出现一定需要这种关系的情况,通过简化可以很好的表达关系同时去除多对多或者双向关联。
具体的方法就是:规定关联方向,添加限定条件减少多对多关联,消除当前需求中不需要的关联。
好例子:一个国家有很多总统,而且一个人理论上说可以当几个国家的总统。这是一个多对多双向关联。假设有两个类,Person和President。
但是通过常识我们知道,一个方向的关联比另一个方向重要,我们不需要在Person中横加一个属性 president,因为这个属性使用概率极低,我们的Person类定义的时候完全可以不考虑。这样就消除了双向关联,而只规定了 President 对象中包含 Person。
另外