什么是ddd?
领域驱动设计(简称 ddd)概念来源于2004年著名建模专家eric evans发表的他最具影响力的书籍:《domain-driven design –tackling complexity in the heart of software》(中文译名:领域驱动设计—软件核心复杂性应对之道)一书,书中提出了“领域驱动设计(简称 ddd)”的概念。
从现在的视角来看,这本书其实写的是有问题。前半本书描述了一些概念性的内容,后半本书则描述了建模战略方法。很多人前半本书还没看完就看不下去了,因此这本03年的书直到18年后才又重新流行起来。
因为十几年后人们遇到了一个现实的问题,比代码怎么维护更加棘手的问题,微服务怎么划分。既然微服务是克服复杂度的最佳实践,科学划分(起码有个能说服别人的理由)就应该是基础内容。
本文不仅写给技术人,产品和非技术管理也可以用这种方法梳理业务逻辑,找出逻辑bug。比起拿张纸画一下业务逻辑,有现成的工具和方法更好用,而且产出还可以直接作为架构设计的输入,变成产品。
ddd有战略战术两个方向,本文只讲战略方向的内容。
ddd的基础
基础概念:
实体:有id的对象
值对象:没有id的对象
聚合根:同个域下只有一个实“聚合”其他实体,因此有且只有一个实体是聚合根
领域:一个聚合就是一个领域domain
一张纸币,因为上面有编号,因此是一个实体。面额=100,这是一个属性。货币单位=人民币,这是另外一个属性,这个属性可能包含其他属性,是一个没有id的对象,也就是聚合根。
另外一个场景下,比如一个外汇系统,其中要列出所有的货币。上面说的货币对象就有了id,在这个领域中它变成了实体,而且是一个聚合根。
领域划分
先说一个事实,ddd是无用的。
ddd确实描述了领域和概念,但没有告诉你怎么划分领域。都是概念落不了地,这也是这么多年ddd被人诟病的原因。
古人有云:两程序员辩领域,一员曰购物车归属商品域️,一员曰购物车归属订单域。孔子不能决也。
如果有个工具能帮助ddd落地,只要用了这个工具就一定能够(或者最大程度上)让迅速把业务转化为领域、聚合、实体,ddd一下就可以发挥应有的作用。
这个工具是18年出现的event stroming,一个非常有效的工具可以用来把业务转化为领域模型。
如果有同学看过别人做event storming,一定对一墙的贴纸记忆犹新。这里我们用一种极简的方式进行,不那么细致,但是快速且准确,非常适合产品验证,也非常适合小团队小项目。
事件风暴
用实际的需求体验一下这个过程。
假设有如下需求:一个外卖系统,用户可以登录、搜索、浏览、加购、下单、支付,商家可以接单,骑手可以接单、送单,用户可以确认收货。
不考虑用户评价、商家骑手分润、商家后台等。
按照流程体验一下分析过程:
列出所有事件:
用户已登录
用户已点菜
用户已支付
商户已接单
骑手已接单
骑手已送货
用户已收货
列出所有“命令”(增删改逻辑):
用户加购
用户支付
商户准备
骑手准备
骑手送货
列出所有读模型(只读内容):
列出所有餐馆
列出所有菜品
列出所有订单
列出所有角色
用户
商户
骑手
列出所有对象(有id的对象,除了角色)
订单
菜品
列出所有外部系统
支付系统(支付宝、微信)
短信
集成上下文
8. 微服务和子领域划分(这是纯技术内容)
从这个过程可以看出,1-6步都是在从需求中拆分对象,7步用表格组合起来就可以了,整个过程没有那么复杂。
当然这个精简版的过程实际并没有那么严谨,比如商家和骑手登陆都没有。在大型系统中要考虑的点比列出的这些多多了,理应用一墙的贴纸来完成。
在实际使用中,可以用这种方式快速识别业务逻辑,找到可能的业务bug。正所谓不追求每次都是100分,只追求可复制的80分。
有了领域划分能力之后,ddd一下就发挥了巨大的优势。
使用ddd进行产研融合
小团队虽然小,产研经验可能都不丰富,最大的问题就是产品逻辑怎么准确反馈到开发。
关键词是准确。需求虽小,谁能保证没有逻辑bug?谁能保证产品脑海中的100到了研发心里还能剩下哪怕60?测试理解的又是另外一个故事,拿这个故事来测试研发的60分内容,会是什么结果?
正所谓“项目不是在结束时失败,是在开始时失败”
因为大家更不专业,小团队更容易因为沟通问题一锅粥,ddd是解决这个问题的良药。
如果产品输出的不仅是原型和prd,同时还输出了领域、对象甚至微服务划分参考。在更多层面指导了研发“代码怎么写”。
比如对象属性就可以直接建立出相关表的多数字段;事件和命令更是对应了cqrs中的command和query;外部系统可以安排适配器模式进行抽象;读模型不涉及事务,可以优先开发。
更多精彩内容预告:
技术人如何做管理:小团队怎么做中台?
技术人如何做管理:小技术团队的hrbp