文章目录

  • 说明
  • 领域模型实践心得
  • 领域模型与传统业务分层区别
  • 应用场景
  • 实践心得(简要)
  • 领域模型缺点
  • 《领域驱动设计》笔记
  • 分层
  • 领域模型内常用元素
  • 领域模型内关联问题
  • 领域模型安全问题
  • 好例子
  • 代码重用


说明

业务模型的设计无定式,领域模型设计也不是适应任何业务,对于复杂业务逻辑可考虑使用。

领域模型实践心得

领域模型与传统业务分层区别

使用Spring框架的项目,业务模型通常是:
Bean-Service-Dao 其中Bean只有数据(其实什么也没有),Service只有行为,Dao持久化。项目经过长久的发展最终Bean几乎什么也没有,Dao还是持久化,而Service则急剧膨胀,几乎不可维护。Service经常沦为过程式编码。
领域业务模型:
Domain-dao 其中Domain包含数据(Bean)与行为(Service)。一般是真正的面向对象编程。

应用场景

当业务模型符合以下特征时,领域模型更合适:

  1. service方法(数据行为)具有清晰的范围,可以归于某一对象的行为。
  2. 调用service方法时传递的参数非常多
  3. 经常多次调用service方法
  4. 业务逻辑复杂

逐一解释:

  1. 通常在创建领域模型对象的时候,传入能够表征该对象的数据(id),如果不能归于某一对象,那么领域模型就不适合了。
  2. 如果数据同属于一个对象,通过id查询出数据,就不需要传递很多的外部参数。
  3. 这是指对该数据某一次处理时,会有多个数据行为。如果是使用MVC贫血模型,那么就会有多次的参数传递.
  4. 当业务逻辑复杂时,更应当划分清楚领域,否则业务修改起来难度很大。这一条是根本原因。简单业务逻辑不需要领域模型,否则得不偿失。

实践心得(简要)

领域模型的代码风格类似于JavaApi类。例如Calendar类。
只要尝试把数据(bean)同数据行为(service)结合到一起,领域自然就形成了,它迫使你在写代码时优先考虑bean中已有的数据。因为Bean没有数据的只能依赖于外部参数传递,这相当于显式地分割了本领域数据与其他数据。
领域模型在创建时通常有两步:

  1. init(id)create(id)。创建该领域模型对象,必须传入该领域数据或者数据id
  2. config() 配置项。配置项与id不同之处在于,配置项是可选的。例如操作用户账户的对象,对于该用户是不是黑名单用户,是不是会员等都可以通过设置来进行。因为如果不涉及这些行为,是不必设置的。

领域模型缺点

领域模型的缺点:

  1. 领域对象是有状态的.例如Canlendar类,在多线程中使用同一个Canlendar对象将是一场灾难。
  2. 业务逻辑散落在整个领域对象内,初看不易阅读。

《领域驱动设计》笔记

不知是翻译还是我水平有限,这本书很难懂。摘几处能看明白又有益处的。

分层
  • 用户界面(表示层)
  • 应用层:定义软件要完成的任务,指挥领域模型完成任务,但几乎不包含领域细节知识。
  • 领域层:领域模型层
  • 基础设施层:基础服务层,如持久化,发送电子邮件,获取外部资源等。
领域模型内常用元素

三种元素:Entity,ValueObject,Service.
Entity是带有标示的ValueObject,如用户存款100元。100元是Value,这次交易是Entity。
Service数据操作数据行为。
通常在业务开发完以后,将valueObject转变为Entity非常困难,然后就是有很多这样的需求。

领域模型内关联问题

对于领域模型内部元素之间的“关联”问题,不要使用"多对多"模式,不要使用逆向的一对多(要规定业务模型的“方向”)。例如用户的地址信息,可以设计为专门的地址表,存放的是某一个地址id,多个用户都可以对应到这个地址id上。这就是典型的逆向1对多,因为查询方向是从userid开始到地址id。现在要删除某个用户的信息,地址id就无法删除了。

领域模型安全问题

由于模型含有状态,状态的安全就是一个值得注意的问题,也是jdk源码当中经常出现不可变对象/对象副本的原因。如一个领域内含有某用户所有的订单列表,当外部需要返回这个订单列表的时候,需要注意 直接返回这个列表对象的 安全问题,如果存在安全问题,那么应当返回这个列表的一个副本。几乎很少有人会注意到这点。 直接将对象抛给外部是脱离了领域控制的对象,是十分危险的。
如果要使用共享的ValueObject,就要保证ValueObject是不可变对象。例如String类就是一个不可变对象。

好例子

此处以细胞为例,恰到好处地说明了领域驱动设计。再延伸一点,人体就是一个超大型系统,可供参考的系统设计。血管:service,器官:领域,细胞:最底层。
以手指为例:指纹是entity,手指甲只是valueobject。
以手机app下单为例:眼睛只负责看,手指只负责操作,大脑负责决策。这三个动作发生在不同的位置,传输的都是神经电信号(?)。这四个领域模型的功能非常强大,智能程度超过了任何计算机。

代码重用

这里有一个代码重用的不同观点。代码级别的重用是低级的,模型重用才是更高级的重用。例如持久化代码重用是非常不利于修改的,等于将两个领域不同的模型建立了关联,为了一个业务领域修改该持久化代码时,通常另一个业务模型也需要一定的修改。