如何在DDD中建立领域模型( 三 )


运营人员修改活动 。应用服务利用Repository获取需要修改的活动,再根据运营人员提供的参数修改活动,最后利用Repository保存活动对象 。
用户参与活动 。应用服务:

  1. 使用活动通用规则判断用户是否可以参加 。由于活动通用规则需要用到活动参与记录,因此应用服务会使用Repository获取活动参与记录;
  2. 如果可以参加,则执行活动的参与活动方法获得结果 。这需要利用Repository获取用户参与的活动,并构造用户对象(可能需要调用用户服务获取用户信息,但是领域层并不关心这些逻辑);
  3. 如果结果是获得权益,则创建活动参与记录,并利用Repository保存 。
考虑到并发情况,应用服务可以在第1步前加锁,并在第3步后释放锁 。
再次思考(1) 配置和参与活动可否是两个模型?
在实现运营人员配置活动的用例过程中,我们会发现可能找到了一个隐藏的领域概念,将输入的参数转换成领域模型的逻辑有些枯燥和复杂,同样将领域模型和数据库的数据模型之间转换也如此 。输入参数和数据模型都是只是扁平的数据数据,没有继承结构 。如果使用另外一种面向数据的模型,也许这些用例实现起来会简单得多 。
每个模型都是为了解决某个问题 。这里运营人员配置和用户参与活动是不同的问题,如果用一个模型来解决这两个问题,可能会有些吃力 。那么干脆设计成两个模型,使用限界上下文的概念将这两个模型限定在各自的上下文中,也许更加合理 。两个模型可以共享同一份数据库数据,并加上一段(非领域层的)逻辑用于模型之间的转换 。
这实际上是一种配置-使用模式 。在配置阶段,注重配置类型和参数、审批等;在使用阶段,注重逻辑计算和性能 。
(2) 活动参与记录是否可以建模成领域事件?
活动参与记录实际上是不可变的,可以将其设计为领域事件 。
(3) 用户参与活动的用例里,逻辑复杂,有泄漏领域概念的嫌疑?
如果发现应用服务里逻辑变得复杂,可能意味着我们找到了一个隐藏的领域概念 。我们可以定义一个「用户参与活动逻辑」的概念:如果用户通过了活动通用规则的判断,则可以参与活动 。将其加入模型和通用语言中,在沟通中验证此概念是否合理 。
总结很多项目虽然也使用了以领域模型为中心的架构,但是设计者仍然是数据模型/贫血领域模型的思考方式,把大量领域逻辑放置在了万能的Service中,让领域概念隐藏在了冗长的过程代码中,无法享受到DDD带来的收益 。
最后总结下本文想要强调的要点:
  • 领域模型和领域概念一一对应
  • 领域模型和实现关联,也和通用语言关联 。刻意使用通用语言沟通以验证模型是否合理
  • 演示了一种设计领域模型的步骤
  • 构造块类型不是最重要的,领域模型本身更加重要
  • 更多的使用可以表达业务含义的值对象和临时值对象
  • 聚合是一种设计,需要方法权衡
  • 使用Repository、Factory获取和创建领域模型是应用层的职责,领域层应该关注在表达领域概念




推荐阅读