DDD建模案例
燃气抄表计费场景每月末,燃气公司制定抄表计划并批量生成抄表任务,抄表任务通过工单的形式下发到抄表人员到客户现场抄表,抄表完成之后给客户应收账单,客户可以现场缴费或者延后通过在线自助缴费。下面以此案例描述建模步骤。
1 描述业务场景
用5W2H进行分析:用户(WHO)在什么环境(WHERE)下遇到什么时机(WHEN)因为什么(WHY)产生什么目标(WHAT),继而通过什么方法(HOW)去达成目标。大部分场景不需要考虑HOW MUCH。
通过本案例的分析,可以得到以下需求场景清单:
2 梳理业务流程
在得到场景清单后,我们把各个场景串联起来用业务流程的方式表达出来:
3 寻找时标性对象
时标性对象对应到时刻-时段原型,是我们关心的可追溯的业务事件。通过将业务流程分解到业务过程的最小粒度来寻找,然后绘制以下格式的表格:
接着将这些时标性对象(用红色标记)的关系描述出来,就得到了领域模型的骨干:
4 寻找时标对象周围的“人、地、物”
在“时标”对象周围的用绿色所表示的“人、地、物”概念,如下图所示:
5 抽象“角色”
在上图中插入用黄色所表示的“角色”概念,如下图所示:
6 补充“描述”信息
在上图中插入用蓝色所表示的“描述”概念,描述对象包括“人、地、物”和时标对象,如下图所示:
7 划分限界上下文
在本案例中,抄表缴费属于核心业务,将业务过程中的时标对象都划分到核心子域,但核心子域解决的问题有所不同,比如抄表计划和抄表任务指派属于抄表前期规划阶段,参与人员同其他阶段都不同,因此将其划分到计划上下文。同样,抄表记录属于抄表的实施阶段,划分到抄表上下文,缴费属于抄表后期阶段,划分到缴费上下文,如下图:
8 确定聚合及聚合根
在每个上下文中,对时标对象中的概念按照相近原则划分为不同的组,形成新的聚合,然后选出聚合根作为与外界交互的代表。比如抄表时标对象产出的核心数据是待缴费的应收账单,关联对象涉及到抄表员、客户和表具,而其他暂时无法分组的概念或属性独立为值对象,待需求需要的时候进一步处理。浅绿色代表聚合根,下图所示:
同理,继续寻找其他上下文中的聚合和聚合根,如缴费和支付:
注意上图中支付和缴费、抄表都涉及到账单聚合根,但是因为账单关注的点有所区别,比如抄表关心的是应收账单,缴费关心的是实收账单,支付账单关心的是无业务含义的交易流水和交易账号,不同关注点通过限界上下文隔离。
9 优化调整子域划分
通过聚合的过程我们发现,客户和表具在多个上下文中公用,是可以将其独立出来,作为共享上下文,划分到通用子域中。另外,在缴费环节,因为支付通常作为基础功能,支撑着缴费等支付相关业务,因此也划分到独立的支撑子域,调整后的子域限界上下文如图,其中虚线椭圆标识的客户、表具属于共享子域:
参考资料
《Java Modeling in Color with UML》
《实现领域驱动设计》
《领域驱动设计精粹》
《复杂软件设计之道:领域驱动设计》
《领域驱动设计》(Thoughtworks洞见)
《Object Design: Roles, Responsibilities, and Collaborations》
https://www.artima.com/articles/the-dci-architecture-a-new-vision-of-object-oriented-programming
https://insights.thoughtworks.cn/port-and-adapter-architecture/
https://culttt.com/2014/12/10/modules-domain-driven-design/
https://insights.thoughtworks.cn/paper-pen-modeling/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本