刚开始学习「DDD - 领域驱动设计」的时候,在网上看文章和看电子书,看到里面各种新概念:领域、领域驱动、子域、聚合、聚合根、值对象…..我原以为我会很开心地 “享用” 这些新知识带给我的营养。
7896890-a7db610ac865f917.gif
可事实是我自己动手实践时,有点不知道从哪里入手,翻遍了 Google 和 百度 前排的所有文章,可似乎都不太近人意,一方面这些「新概念」我对它的困惑太多了,另一方面真正「落地」并实践起来的经验有很少是可以直接借鉴的,再结合一些实际的场景(没有人解答),我感到更加困惑。
7896890-951d48e4bd0c1804.png

DDD领域驱动设计

先整段百科解释:DDD的全称是「Domain Driven Design」,即「领域驱动设计」。是一种通过将实现连接到持续进化的模型来满足复杂需求的软件开发方法
20170213996893_UnZAsp.gif
个人理解:DDD是一种将需求转化为模型来驱动软件开发方法,即找出需求中的「领域」、「限界上下文」、「实体」、「值对象」、「聚合根」及它们之间依赖关系建立对应模型,在根据建立的模型创建工程实现(有哪位大佬感觉描述不对不专业,欢迎下方留言)。
006i487Uly1fhtvkgdrfdj30hs0hs3zt.jpg

领域模型

领域模型定义了领域内的关键的概念以及这些概念之间的关系
领域模型是概念模型
领域模型描述的是现实世界的事物和他们之间的关系
领域模型和软件无关,反映的是问题空间的本质理解

实体( Entities )

我们会使用唯一的标识符跟踪那些具有重要业务意义的对象
这些对象通常会随着业务进展产生状态和属性的变更,但是们代表的业务对象不变

值对象( Value Objects )

值对象仅仅用来描述特征,所以我们只关心值对象的属性,不关心它有没有唯一标志符
区分实体对象和值对象有助于减少系统的复杂性。

领域服务(Domain Services )

一些业务逻辑并不是和领域对象相关,它本身代表了一种商业策略或业务处理过程
服务自身是无状态的

领域事件( Domain Event )

领域事件表达了“系统中发生了什么”
领域事件是“ 领域专家关心的事件”。它们源自于业务活动的结果
领域事件还可增强系统的可回溯性,解耦业务间的复杂关系
领域事件是一-种特殊的‘值对象’

聚合( Aggregates )

将实体和值对象划分为聚合并围绕着聚合定义边界
作为一个整体来定义聚合的属性和不变量,并把其执行责任赋予聚合根或指定的框架机制
选择一个实体作为每个聚合的根,并仅允许外部对象持有对聚合根的引用
聚合提升了对象系统的粒度,保证了业务逻辑的完整性,减少了错误产生的概率

聚合的划分的生命周期一致性原则

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

聚合的划分的小聚合原则

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

工厂( Factories )

在设计模式中,工厂的概念是分离构造和使用
在DDD上下文中,聚合需要保证业务一致性,我们应用工厂模式,来保证聚合的构造

资源库(Repositories)

资源库是聚合的仓储机制,外部世界通过资源库,而且只能通过资源库来完成对聚合的访问
资源库以聚合的整体管理对象。一个聚合只能有一个资源库对象,那就是以聚合根命名的资源库。除此之外的其他对象,都不应该提供资源库对象
资源库模式不等价于持久化,更不是数据库访问层

=========== ================网络参考=======================================

领域(Domain)

指软件使用场景范围,即问题域和解决问题系统。比如论坛是一个领域,只要你想做一个论坛,那这个论坛的核心业务是确定的,比如都有用户发帖、回帖等核心基本功能。比如电商平台、普通电商系统,这种都属于网上电商领域,只要是这个领域的系统,那都有挑选商品、商品管理、付款交易等核心环节。所以,同一个领域的系统都具有相同的核心业务,因为他们要解决的问题的本质是类似的。因此,我们可以推断出,一个领域本质上可以理解为就是一个问题域,只要是同一个领域,那问题域就相同。所以,只要我们确定了系统所属的领域,那这个系统的核心业务,即要解决的关键问题、问题的范围边界就基本确定了。通常我们说,要成为一个领域的专家,必须要在这个领域深入研究很多年才行。因为只有你研究了很多年,你才会遇到非常多的该领域的问题,同时你解决这个领域中的问题的经验也非常丰富。很多时候,领域专家比技术专家更加吃香,比如金融领域的专家。
006oOWahly1fqix4n7tfhj30bo09gq33.jpg

模型

描述领域内不同功能模块解决的问题的系统化抽象。如将电商领域划分成挑选商品、商品管理、付款交易等模块。

限界上下文(Bounded Context)

描述模型的边界范围,想与一个限界上下文沟通,则需要通过显示边界进行通信。系统通过确定的限界上下文来进行解耦,而每一个上下文内部紧密组织,职责明确,具有较高的内聚性。任何大型项目领域都有多个模型。 然而,当基于不同模型的代码相结合,软件变得越来越多,不可靠,并且难以理解。 团队成员之间的交流变得越来越难。 模型的使用情境变得越来越不清晰。因此:需要明确定义模型适用的上下文,并且根据团队组织,应用程序特定部分的使用情况以及代码库和数据库模式等物理表现明确设置边界。 保持模型在这些范围内严格一致,并且不被外部的问题影响。一个很形象的隐喻:细胞质所以能够存在,是因为细胞膜限定了什么在细胞内,什么在细胞外,并且确定了什么物质可以通过细胞膜。
9150e4e5ly1frve1g5zv4j20hs0b574r.jpg

实体(Entity)

一个不由自身属性定义而是由标识定义的对象。当两个对象的标识不同时,即使两个对象的其他属性全都相同,我们也认为他们是两个完全不同的实体。例如:大多数航空公司航班上都有独特的区分每个座位的唯一座位号。每个座位在这种情况下都是一个实体。

值对象(Value Object)

只包含元素属性没有唯一标识的不可变对象。例如:当人们交换名片时,他们一般不会区分每张独特的名片;他们只关心印在卡片上的信息,如果所有信息相同就认为是同一张名片。在这种情况下,名片是 Value Object。

聚合根(Aggregate,Aggregate Root)

由值对象和实体 绑定在一起的对象的集合,也称为聚合根。聚合根通过禁止外部对象保持对其成员的引用来保证在聚合内进行的更改的一致性。例如:驾驶汽车时,不必担心向前移动车轮,使发动机燃烧火花和燃料等。你只是在开车。在这种情况下,汽车是其他几个对象的集合,并作为所有其他系统的聚合根。

领域服务(Domain Service)

强调与其他对象的关系,只定义了可以为客户做什么,不应该替代 Entity 和 Value Object 的所有行为。例如:用户下单,需要调用付款服务和商品管理服务(减库存),下单就属于领域服务,负责来协调这些领域对象完成操作。

领域事件(Domain Event)

领域对象内定义了的事件。

设计领域模型一般步骤

  1. 根据需求划分出初步的领域和限界上下文,以及上下文之间的关系;
  2. 进一步分析每个上下文内部,识别出哪些是实体,哪些是值对象;
  3. 对实体、值对象进行关联和聚合,划分出聚合的范畴和聚合根;
  4. 为聚合根设计仓储,并思考实体或值对象的创建方式;
  5. 在工程中实践领域模型,并在实践中检验模型的合理性,倒推模型中不足的地方并重构。