写点什么

10.4 领域驱动设计 DDD

用户头像
张荣召
关注
发布于: 2020 年 11 月 28 日

微服务核心:服务本身的设计。重点把握业务。框架只是技术手段。

1.为什么需要DDD

很多项目的实际情况:

  • 用户或者产品经理的需求零零散散,不断变更。

  • 工程师在各处代码中寻找可以实现这些需求变更的代码,修修补补

  • 软件只有需求分析,并没有真正的设计,系统没有一个统一的领域模型维持其内在的逻辑一致性。

  • 功能特性并不是按照领域模型内在的逻辑设计,而是按照各色人等自己的主观想象设计。

项目时间一长,各种困难重重,需求不断延期,线上BUG不断,管理者考虑是不是要推倒重来,而程序员则考虑是不是要跑路。

2.事务脚本

Service层:由于需求变化,导致代码无限膨胀。Service层承担了复杂的业务逻辑,需求变更,Service代码需要调整。使用大量的if else,switch case处理各种业务逻辑。需求变更,调整代码,很容易引入bug。

解决方法:设计核心领域模型。使用领域模型统一业务逻辑。

3.领域模型

4.贫血模型 VS 领域模型

由于事务脚本模式中,Service,Dao这些对象只有方法,没有数值成员变量,而方法调用时传递的数值对象,比如Contract,没有方法(或者只有一些getter,setter方法),因此事务脚本又被称作贫血模型。



领域模型对象则包含了对象的数据和计算逻辑,比如合同对象,即包含合同数据,也包含合同相关的计算。因此从面向对象的角度看,

领域模型才是真正的面向对象。收入确认是和合同强相关的,是合同对象的一个职责,那么合同对象就应该提供一个calculateRecognition方法计算收入。



领域模型是合并了行为和数据的领域的对象模型,通过领域模型对象的交互完成业务逻辑的实现,也就是说,设计好了领域模型对象,也就设计好了业务逻辑实现。和事务脚本被称作贫血模型相对应的,领域模型也被成为充血模型。



DDD是充血模型的补充。使充血模型实现起来更简单。

5.DDD战略设计

领域是一个组织所有的事情以及其包含的一切,通俗的说,就是组织的业务范围和做事方式,也是软件开发的目标范围。



领域驱动设计就是从领域出发,分析领域内模型及其关系,进而设计软件系统的方法。

5.1 子域(sub-domain)

领域:一个组织所做的事情及其包含的一切。这个范围太大了,不知道该如何下手。所以通常的做法是把整个领域拆分成多个子域,比如:商品,购物车,订单,支付,库存,物流,发票等。

如何划分子域?

卖家提现功能属于用户子域?订单子域?财务子域?还是直接设计一个提现子域?

5.2 限界上下文

在一个子域中,会创建一个概念上的领域边界,在这个边界中,任何领域对象都只表示特定于该边界内部的确切含义。这样边界便称为限界上下文。

限界上下文和子域具有一对一的关系,用来限定子域的边界,保证子域内的概念统一性。



子域:概念逻辑领域。(业务上更小的领域)

限界上下文:物理限定子域(逻辑领域)边界。



通常限界上下文对应一个组件或者一个模块,或者一个微服务,一个子系统。

5.3 上下文映射图

不同的限界上下文,也就是不同的子系统或者模块之间会有各种的交互操作。DDD使用上下文映射图来设计这种关联和交互。





6.战术设计

6.1实体

领域模型对象也被称为实体,每个实体都是唯一的,具有一个唯一标识。

一个订单对象是一个实体,一个产品对象也是一个实体,订单ID或者产品ID是他们唯一的标识。

实体可能会发生变化,比如订单状态会发生变化,但是他们的唯一标识不会变化。



实体设计是DDD的核心所在,首先通过业务分析,识别出实体对象,然后通过相关的业务逻辑设计实体的属性和方法。

这里最重要的,是要把握住实体的特征是什么,实体应该承担什么职责,不应该承担什么职责,

分析的时候要放在业务场景和限界上下文中,而不是想当然的认为这样的实体就应该承担这样的角色。

6.2值对象

并不是领域内的对象都应该被设计为实体,DDD推荐尽可能将对象设计为值对象。比如:住址,是一个典型的值对象。

也许建在住址上的房子可以被当做一个实体,但是住址仅仅是对房子的一个描述,向这样仅仅用来做度量或描述的对象应该被设计为值对象。



值对象的一个特点是不变性,一个值对象创建后就不能再改变了。如果地址改变了,那就是一个新地址。

而一个订单实体则可能会经历创建,待支付,已支付,待发货,已发货,待签收,已签收,待评价等各种变化。

6.3聚合

聚合是一个关联对象的集合,我们将其作为一个单元来处理数据更改。每一个集合都有一个根和一个边界。边界定义了聚合内部的内容。

根是聚合中包含的单个特定实体。

聚合根:将多个实体和值对象聚合在一起的实体。

7.分层架构

 领域实体的组合调用和事务控制在应用层。

应用层:比较薄,不处理业务,业务预处理,准备参数等。应用层可以包装多个业务。

领域层:核心业务处理。聚合根关联的多个业务可在应用层包装。

8.六边形架构

领域模型通过应用程序封装成一个相对比较独立的模块,而不同的外部系统则通过不同的适配器和领域模型交互。

比如:可以通过HTTP接口访问领域模型,也可以通过WebService或者消息队列访问领域模型,只需要为这些不同的访问接口提供不同的适配器就可以了。



9.战略设计 与 战术设计

 战略设计: 领域,子域,限界上下文,上下文映射图

 战术设计: 实体,值对象,聚合,CQRS,事件溯源

 通过战略设计,划分模块和服务的边界及依赖关系,对微服务的架构设计至关重要。



用户头像

张荣召

关注

还未添加个人签名 2018.05.02 加入

还未添加个人简介

评论

发布
暂无评论
10.4领域驱动设计DDD