DDD-第三课

第三课 从问题空间到方案空间:用领域模型指导软件实现

image-20200726130357011

本讲大纲:

1.从问题空间到实现空间——领域模型和设计质量;

2.从模型到代码——DDD的4个构造块模式;

3.在领域层保证业务完整性——DDD的3个生命周期模式;

4.在产品代码中增加领域层——聚焦核心业务逻辑。

image-20200726130637678

image-20200726130803957

正确的OO:

image-20200726130954289

什么样的设计是好的设计?

Any fool cat write code that a computer can understand. Good programmers write code that humans can understand. ——Martin Fowler, Recactoring

image-20200726131410105

“设计的好坏”和上下文相关

普适性原则:

1.易于理解;

2.易于演进;

3.低开发成本。

image-20200726132002198

问题1:在上图中,有没有哪些对象,它看起来比别的对象重要?再观察地更细一点,这几个对象有什么共同特点。

实体(Entities)

我们会使用唯一地标识符跟踪那些具有重要业务意义地对象。

这些对象通常会随着业务进展产生状态和属性地变更,但是它们代表地业务对象不变。

问题2:在上图中,有没有哪些对象,它的主要作用是描述?

image-20200726132716630

描述类对象地特点是,一旦它发生变化,它就不再是它自己。

值对象(Value Objects)

1.值对象仅仅用来描述特征,所以我们只关心值对象的属性,不关心它有没有唯一标识符;

2.区分实体对象和值对象有助于减少系统的复杂性。

问题3:在右图中,有没有哪些对象,它自身不持有数据,而是表达了某种业务计算逻辑或者业务策略?

image-20200726133237630

服务(Services)

1.一些业务逻辑并不是和领域对象相关,它本身代表了一种商业策略或业务处理过程;

2.服务自身是无状态的。

问题4:有没有哪些对象,它代表了重要的业务事件?

image-20200726133544858

领域事件(Domain Event)

1.领域事件表达了“系统中发生了什么”;

2.领域事件是“领域专家关心的事件”,它们源自于业务活动的结果;

3.领域事件还可增强系统的可回溯性,解耦业务间的复杂关系;

4.领域事件是一种特殊的“值对象”。

image-20200726134142831

问题5:辨析-上车信息中存在“上车点”。图中还有一个“预定义上车点”,这两个对象是什么关系?

1.尽量使用值对象;

2.对于生命周期不一致的数据,慎用关联;

3.转化数据库视角为对象视角;

4.慎用数据库外键。

image-20200726134549751

问题6:发布人、乘车人这些对象,究竟是实体还是值?

应该是值对象。

1.尽量使用值对象;

2.大多数时候不需要完整的实体信息;

3.这类值对象需要保存一个ID;

4.ID来支持必要时获取更多信息或者信息同步。

代码怎么写?

image-20200726140434106

问题域和方案域之间的低表示差距,易于理解,易于演进。

完整复刻,也可能有细微精化。

问题7:图中的对象有很多,请观察它们(实体对象和值对象)是否存在一些“中心“对象?

image-20200726140843234

将实体和值对象划分为聚合并围绕着聚合定义边界。

image-20200726140934530

image-20200726141130378

image-20200726141210817

作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制。

还有其他的问题:

image-20200726141507589

选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。

领域层获得了知识丰富的行为:

image-20200726141734161

聚合(Aggregates)

1.将实体和值对象划分为聚合并围绕着聚合定义边界;

2.作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制;

3.选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用。

聚合提升了对象系统的粒度,保证了业务逻辑的完整性,减少了错误产生的概率。

问题8:如果共乘是一个聚合根,共乘应该持有出行计划和支付单吗?

image-20200726142254916

聚合的划分的生命周期一致性原则:生命周期一致性是指聚合边界内的对象,和聚合根之间存在”人身依附“关系。即:如果聚合根消失,聚合内的其他元素都应该同时消失。

聚合的划分的小聚合原则:在不破坏业务逻辑完整性的基础上,小聚合带来更大的灵活性。

工厂(Factories)

1.在设计模式中,工厂的概念是分离构造和使用;

2.在DDD上下文中,聚合需要保证业务一致性,我们应用工厂模式来保证聚合的构造。

image-20200726143337670

资源库(Repositories)

1.资源库是聚合的仓储机制,外部世界通过资源库,而且只能通过资源库来完成对聚合的访问;

2.资源库以聚合的整体管理对象。一个聚合只能有一个资源库对象,那就是以聚合根明明的资源库。除此之外的其他对象,都不应该提供资源库对象;

3.资源库模式不等价于持久化,更不是数据库访问层。

image-20200726144026192

image-20200726144042200

业务完整性

image-20200726144257986

软件开发的本质挑战是复杂性:

1.接口层协议、接口层数据校验、必要的数据补全;

2.应用层的易变的业务逻辑;

3.领域层逻辑及不变形约束;

4.数据持久化、外部数据访问、消息收发。

分成四层:

1.接口层;

2.应用层;

3.领域层;

4.基础设施层。

image-20200726144559418

image-20200726144805336

依赖倒置+分层模型

image-20200726144855683

image-20200726145013816

image-20200726145102395