为什么要使用领域驱动模型
- 传统设计模式特点
a. 以数据库为中心
b. 贫血模型
c. 业务逻辑散落在大量的方法中
d. 当系统越来越复杂时,开发时间指数增长,维护成本很高
传统的代码设计没有模型的概念,一上来就开始建表写代码,代码写的非常冗余,完全是过程是的思考方式,最后导致系统非常难以维护。更糟糕的是,前期的领域模型设计的不好,不够抽象,如果你的系统会长期需要维护和适应业务变化,那后面你一定会遇到各种问题维护上的困难,比如数据结构设计不合理,代码到处冗余,改BUG到处引入新的BUG,新人对这种代码上手困难等。这时如果你再想重构模型,那要付出的代价会比一开始重新开发还要大,因为你还要考虑兼容历史的数据,数据迁移,如何平滑发布等各种头疼的问题。
传统开发四层架构:表现层、Service层、Dao层、Model层。业务逻辑都是写在Service中的,Model层只是个数据载体,没有任何行为,是一种贫血模型。简单的业务系统采用这种贫血模型和过程化设计是没有问题的,但在业务逻辑复杂了,业务逻辑、状态会散落到在大量方法中,原本的代码意图会渐渐不明确,我们将这种情况称为由贫血症引起的失忆症。

领域模型的设计思想
到底什么是领域模型呢?作为一个软件开发者,我们很难在对一个领域不了解的情况下着手开发,所以我们首先需要和领域专家沟通,建立领域知识。
以飞机航行为例子:现要为航空公司开发一款能够为飞机提供导航,保证无路线冲突监控软件。那我们应该从哪里开始下手呢?根据DDD的思路,我们第一步是建立领域知识:作为平时管理和维护机场飞行秩序的工作人员来说,他们自然就是这个领域的专家,我们第一个目标就是与他们沟通,也许我们并不能从中获取所有想要的知识,但至少可以筛选出主要的内容和元素。你可能会听到诸如起飞,着陆,飞行冲突,延误等领域名词。
这个过程,是我们不断建立领域知识的过程,其中的重点就是寻找领域专家频繁沟通,从中提炼必要领域元素。
领域模型的分层
- DDD把模型分成四层
展现层:负责界面展示,一般对应http的controller层和dubbo的facade层。
应用层(Application Layer):负责业务流程。
领域层(Domain Layer):负责领域逻辑。
基建层(Infrastructure Layer):负责提供基建。
分类的依据是:越往上,预期变动越频察;越往下,预期变动越少。对于程序员来说,展现层和基建层应该很容易分清,一个只管展示,一个只管提供持续储存、网络传输等等基础设施,都没有“业务”的参与。
应用层和领域层是比较容易混淆的。模型属于哪一层,有个粗略的判断方式。如果是一个实体(entity)和针对实体的增删改查,就属于领域层;如果是一个场景,比如出现在UI菜单上的选项,就属于应用层。比如:账单,用户,编辑商品,编辑库存,这些是领域层;“购买商品”,则是应用层。前者是针对实体的操作。每一个实体都只有增删改查这样的操作。与之相反的是,要完整实现“购买商品”这个场景,也许需要检查库存、创建订单、创建交易等多个操作。
如何设计领域模型
领域驱动设计的核心是领域模型,这一方法论可以通俗的理解为先找到业务中的领域模型,以领域模型为中心驱动项目的开发。而领域模型的设计精髓在于面向对象分析,在于对事物的抽象能力,一个领域驱动架构师必然是一个面向对象分析的大师。
在面向对象编程中讲究封装,讲究设计低耦合,高内聚的类。而对于一个软件工程来讲,仅仅只靠类的设计是不够的,我们需要把紧密联系在一起的业务设计为一个领域模型,让领域模型内部隐藏一些细节,这样一来领域模型和领域模型之间的关系就会变得简单。这一思想有效的降低了复杂的业务之间千丝万缕的耦合关系。
- 设计方法论
领域模型”阶段我们要做什么、该怎么做,分为四个步骤:
a. 找出用例模型中的名词,
b. 然后识别这些名词本身的相关信息,
c. 以及名词之间的相互关联关系,
d. 用UML画出领域模型。
我们以设计一个pos机程序为例子来讲解。
第一步:找出用例模型中的名词
1)顾客携带商品到收银台;
2)收银员扫描商品条形码;
3)系统根据条形码获取并显示商品信息;
4)收银员重复2~3步,直到所有商品扫描完毕;
5)系统计算商品总额;
6)系统打出商品清单,完成交易。
这个用例中的名词有“顾客”、“商品”、“收银台”、“收银员”、“商品条形码”、“系统”、“商品信息”、“商品总额”、“商品清单”、“交易”。稍加整理:
1)“顾客”、“收银员”是系统的外部对象,不需要我们进行设计,但这些对象要和系统进行交互;
2)“商品”、“商品条形码”、“商品信息”、“商品总额”、“商品清单”、“交易”是领域对象,但“商品条形码”、“商品信息”可以算作“商品”的属性、“商品总额”可以算作“交易”的属性,最后从用例总结出来的领域对象有“商品”、“商品清单”、“交易”三个。
第二步:识别这些名词本身的相关信息
一个对象的属性可能分布在多个用例中,因此可以通过迭代不断的完善一个对象的属性,大家可以看到,我们在第一步中的样例就已经分析了一部分了:“商品条形码”、“商品信息”可以算作“商品”的属性。
对象除了属性外,还有一些约束或者限制,这些在用例中可能有,也可能没有,这就需要分析人员来发现了。比如说交易金额必须大于0.1元小于99999元这种约束,用例中不一定会体现,可能需要分析人员向客户咨询。
第三步:识别对象间的关系
面向对象设计就是依靠对象间的互相协作来配合完成相应的功能,因此识别出对象和对象本身的属性外,还要识别对象间的关系,例如1对多、1对1、依赖等,详细的各种关系可以参考UML的标准定义。
我们以第一步识别的三个对象为例:“商品清单”包含多个“商品”、一次“交易”对应一个“商品清单”、一个“商品”只能属于一个“交易”等。
第四步:画出领域模型UML图
UML这里就不啰嗦了,我们结合前三步的分析,画出这个样例的UML领域模型图
网友评论