一、背景
最近有微信朋友在公司内部分享的时候有人问领域划分的规则是什么?
意思就是你怎么知道一个领域需要划分哪些子领域?有没有依据,是凭直觉吗?本文将重点讨论下这个比较现实的问题。同时根据网友的试读建议本文进行了思维导图的总结,可以保存收藏。
本文先找人进行了试读,有大佬提出了一些建议,为了让本文更容易让人理解
,这里我们不再具体讨论领域模型、子领域、限界上下文和聚合的概念,而是聚焦于对一个宽泛意义上的领域来划分,另外当你真正深入领域划分过程的时候,其实这些词在某些情况下是等同的,比如上下文,领域,子领域这三个词。所以对于划分出来的划分方案可能就是一份文档,一个对于应用架构落地的指导性方案。那么这时候,领域可能是一个部门负责的,可能是一个平台系统,可能是一个单独的微服务,也可能是更细致上的模块。
最终,当你觉得概念很难理解的时候不妨先放一下,去真正体验一下
领域驱动设计中的统一语言在现实情况下的应用场景。
二、领域划分的依据
现在我们先直观的回答这个问题,我这边从以下个方面来阐述一下领域划分的
依据,可能不够全面,如果有其他依据欢迎交流讨论。
2.0 领域划分依据的思维导图
2.1 基于领域模型的对象关系
在进行领域建模的时候我们会完整的构建一张对象关系图谱,有些对象很明显的属
于某一个范围,这个范围相当于对这些对象的一层抽象或者总结,比如SkuBO,
SpuBO,SkuSnapShotBO等。这些虽然没有表达商品的概念也没有显示的定义
ItemBO 但是我们可以很容易的通过关联关系来把他们画成一类。你可能会觉得
这样的划分不就是主观意义上的吗?或者这本身就是凭直觉去做的。那我们再看
一下每个对象的业务操作和其本身的一些行为是否会影响其他对象,是不是强关
联的。很多业务对象事实上都有关联关系,但是在业务流程和交互上有先有后,
有时候做一件事情可以延迟做另外一件事情然后去修改或者调整数据关联关系,
这样就形成了一定的上下游关系或者依赖关系,这是一种依据。
在对象的关联关系中如果存在一对多的情况或者存在多级关联关系的那种
比如省市县或者系统-菜单-按钮的这种情况,或者是一个主单子对多个单据
详情列表,这种我们可以自然的去把这些对象单独放一起,如果存在别的
对象要引用一对多的多方就要考虑是否要通过一方去进行引用遍历,或者
说别的对象也可以把多方的这个对象划分到对应领域里,类似于都有关系的
那种,那么在操作上一对多的情况下肯定是希望在一次操作就可以完成的。如果这个对象也参与在这个操作中就可能存在这个对象跟一对多的这俩对象
是一种聚合关系或者可以划分为领域内对象。当然有些对象是关联对象被显示的
表达出来了,比如UserRoleRelationBo这种的,这样的关联关系本身也算领域内
的对象,可以附庸在UserBO或者RoleBO的领域上下文中。
2.2 基于数据模型的对象关系
从数据模型上不是特别能看出来领域划分的依据,但是我们可以从中找到一些
线索,比如一些表之间跟另外一些表之间本身有些数据的流动关系,或者依赖
关系。或者我们通过几个被依赖的表去发现被依赖的表本身就代表着这个表可
能就是一个核心表,那么核心表对外而言就只需要通过其ID或者业务标示字段
进行关联,内部的表都可以通过这个表的ID来遍历找到。一个特殊的案例就是
我们会因为性能等方面的原因来打破数据库范式的约束,比如做冗余,但是这
个冗余的字段却很明显的不能当作表间关系的依据。一个超过10张表的e-r图
从布局上就可以看出这些表之间的亲缘关系。
2.3 基于业务流程的交互关系
尝试划分领域的一个最好的实践就是去了解业务流程,通过时序图,通过流程
图我们可以从不同的节点事件来表达这些节点事件的关联关系,比如外卖,对
于用户来说他做的就是浏览菜单下单支付然后拿外卖,在用户操作的这个领域
来说他就只有几个节点,这些节点还包括商家接单,商家把单子告诉厨房,厨
房准备菜品,做好了外卖员要么在取餐的路上要么在等餐的路上,或者在送餐
的路上。那这个例子就告诉我们一个业务流程如果我们不分割为多个领域的话
我们几乎无法完成一整套的操作。
这期间其实也涉及到了一个上下文或者数据流的变化,比如从订单上看用户订
单到商家订单,再到外卖送餐订单。这个订单如果是一个的话其实是需要多个
角色一起完成的。比如骑手准备送餐了,那么系统可能会告诉骑手走哪条路最
快,这个骑手按照路线走的过程其实放大了看就相当于一个问题领域,就是最
佳路线选择的问题。
从全局看的话,外卖都追求快效率高,所以对于平台方而言各个领域内部的处
理流程就成了预测建模和提效的依据了。所以可以得到一个结论领域的划分依
据是可以通过业务流程中的不同的节点的关系度和业务数据流去分。
2.4 基于抽象复用的要求
在java中万物皆对象,包括女朋友。所以很多时候有些领域是经过实践探索的
,那么对于后来者来说领域的划分就简单很多了,不是凭感觉,而是我就是这
么抄过来的。那么对于划分领域的这个人是否真正的从业务出发去划分谁也不
知道,就是说这个领域在当前业务中是肯定存在的,比如下单优惠,支付优惠
,营销策略等等。
重点在于营销和优惠是不是在业务流程中存在多次,如果说业务刚起来有优惠
的场景。那么此时就去识别优惠领域,构建一个营销优惠平台可能就不太合适
。那么,再看一下,假设某公司有多个业务线,业务上都做了营销优惠相关的
逻辑,但是业务成交量却上不去,业务线之间的关联关系却不紧密。那么这个
领域还是否需要独立出来做单独的领域建模呢?注意我这里举的例子是把领域
看作看作系统应用服务级别的而不是模块上下文级别的。
那么终究有一些其他存在感比较强的横向应用场景,比如权限,审批这种的。如果一个大型系统没有权限和审批的话那系统可能就千疮百孔了。另外一方面企业相关的IT系统基本都比较大,同时微服务和分布式也催生了很多相对小粒度的系统,但是这并不意味着每个系统都要背负一套权限模型或者审批流,所以绕来绕去还是需要建设一个相对统一和通用的支撑系统来解决每个系统的共性的业务的依赖功能。
其他的例子也有不少比如工具,中间件等,但是都是基于抽象复用和解耦的目
的去考量和划分领域的。
2.5 基于角色和职责的定位
前面说的场景也遗憾了这个依据,在这一小节中我们可以看到因为分工和职能
的问题导致的领域划分变得时而简单时而复杂。因为角色和职责在某些情况下
会分的特别详细比如线上出现了一个bug,不大不小的。要问责,领导要背多
少个百分比,开发,测试,产品要分多少。但是有时候就会发现很多人会做一
些“分内之事”,怎么说呢,就是说职责上和角色上并不属于自己去做或者去推
动的事情而去做了,那么此时领域的划分就变得模糊了,说白了可能从别的视
角或者在别人看来是狗拿耗子了。
在具体事项上因为角色或者职责等的因素导致划分不清晰其实也很多,说白了
就是可能因为妥协或者坚持才发现结果的对错。在这一方面上看,因为某些问
题导致的划分不清晰可能是没有统一的标准或者规范,就是说没有个标尺来说
明谁做这个事好。比如说当前是因为某原因在B领域系统里帮A做了A领域系统
里的部分功能,从当前看是复合当前利益的,但是从长远看并不合理,那么就
可能会出现一些情况,B依然承担了这个职责,系统正常运行。A变得非常复杂
让B很难受。B去掉了这个职责,让A自己做。或者B在升级的过程中因为这部分
职责让B自己很难受。
所以在多个领域之间其角色和职责会代表着这个领域的范围,有时候帮助我们
在划分领域的时候寻找有角色和职责相关的因素去找最好的划分方案。
根据大佬的意见是在这个维度上可以通过企业架构(EA)来划分,说白了领域划
分可能会受到利益相关者的干扰,即使你觉得非常合理非常适合演进的领域划
分方案其实可能并不是最合适的,起码对于处在各个业务架构下的带头老大也
通常不会认可这种方案。
2.6 基于团队协作的方式
现在我们从团队或者合作方的角度来谈领域划分相关的话题,因为团队协作其
实也不仅仅包括公司内部的团队和部门,毕竟关起门来好商量,在2.5的描述
上看上下游都是兄弟嘛。那么如果部门变得比较大是兄弟公司级别的或者业务
线级别的可能就是堂兄弟了。那现在我们看一下一个更广泛的团队协作方式,就是跨企业的合作,比如互联网中小型公司对接支付宝,微信或者银行,毕竟人家是大佬,跟你不存在太多好商量的余地,只能按人家的标准和规范来。那么为了做业务所以只能在自己的业务领域中找一个可以做适配的领域来帮忙对接。又或者是我本身没有这个领域的能力,但是我有钱,我可以买服务,买系统来实现这个业务依赖的功能。此时可能已经不需要你去费尽心思去分了,老板已经搞定了。
但是这不意味着领域划分就结束了,而是说这个领域相关的模型和业务接口实
现什么都起码有一套了,自己要做的就是弄个适配模块来代表这个领域的能力
,比如第三方系统的对接,下游对接的防腐层等等。
现在总结一下就是因为团队和客户供应商的关系会让相关领域的划分变得简单
,在eric的书中很多战略上的模式也说明了一些领域划分的依据,只是不是
特别明显。
三、领域划分的规则或者原则
上面从各个方面来阐述来一些领域划分的依据,那现在我们总结一下相关的规则或者原则,领域划分的规则其实跟聚合或者上下文划分的规则很类似,基本上大同小异,小异的地方等有时间再分享下。因此我也重点看了张逸老师的《解构领域驱动设计》的书,把其中关于上下文和聚合相关的原则拿过来简单说明一下。
3.0 领域划分的规则或者原则思维导图
3.1 单一抽象层次原则
这个原则其实要求做领域划分的时候不可以抽象出多个相似的领域,比如营销
和优惠,这两个可能就是相似的领域,或者说优惠是在营销领域下的一个层次
的抽象,那这样的话我们可以用这个原则来检查一下划分的领域有没有可能存
在相似和重复。当然另外一方面也可以保障我们可以识别大多数的重要领域。
3.2 奥卡姆剃刀原理
这个在书里说的意思是在划分上下文的时候不要做的太细,太细的话就存在多
个层次的内容反而无法更好的切分上下文,那么在领域层也类似,说白了,通
过这个原理可以让主观的划分更有能动性,也更能给出划分的理由。即使是拍
脑袋划分的,能从中取出核心的领域名称并给出具有说服力的理由也算一种划
分方案。
3.3 最小惊讶原则
这个原则说的是在真正懂行的专家里或者有经验的大佬面前如果你的划分挺合
理的话那么他们不会感到惊讶,可能会会心一笑。反之就会觉得有需要改进的
地方,或者再讨论讨论。所以在领域和上下文的划分上来看,如果划分的比较
合理那么就没有太多争论的必要了。
3.4 正交原则
这个正交原则其实可能有点不太理解或者不容易应用,在领域划分方案出来之
后可以通过一些业务流程来看一下领域内的聚合实体服务等是否跟别的领域内
做的事情相似或者一样,如果存在的话说明还可以继续优化。直到每个领域做
的事情都足够唯一或者职责单一,到合适的正交维度即可。如果过度的追求正
交和职责单一可能会出现3.1的情况。
3.5 多数派原则
这个原则是我在群里面聊的内容的一个总结,简单解释一下,就是可以从统一
语言或者领域名称中找一些线索,比如我们有很多业务流程,有很多用例或者
用户故事,那么这些文档和业务中哪些出现的名词或者动名词最多这个就可以
作为一个领域。
目前看这是一种最简单的领域划分原则了,也就是说你可以从脑海中过一遍所
有业务流程,接口流程,调用时序,从统一语言上去统计哪些词语是最常出现
的,这些词语代表了哪个维度的领域,是核心领域还是通用领域,还是依赖领
域等等。那么可以把这些词语单独摘出来去划分,当然也可能有最多的排序,
比如出现词语最多的有20个,但是里面可能有重复的,不够正交也不够单一抽
象,那么可以用排除法一一去舍掉看是否是最好的领域划分方案,类似于手动
寻找最优解。
四、领域划分的方法
从现在看领域的划分可能比聚合和上下文的划分更有难度,领域本身涉及的维
度其实是多维的,所以在正交上只是选择某一维度去划分,说白了就是在边界
上其实领域是更模糊的,有时候上下文就可以代表领域,但是领域其实可能不
能跟上下文去划等号。所以领域划分的话其实是对时空间的划分,比如生态系
统,12306购票系统,这些系统其实是跨空间在时间上并行的。业务流程是源
源不断的通过各个领域。所以通过上面的一些依据,规则或者原则能帮我们区
分领域的问题空间和解空间,以及将这些业务流程从时间维度上来验证划分的
结果是否合理。
五、总结
这个话题其实也让很多学DDD的人又多了一个问号,但是如果这个话题讨论清
楚了那么我们对于DDD和领域相关的知识理解又深了一些,本文也仅通过自己
的所思所想表达一下这个话题相关的内容,如果有补充的或者哪里不对欢迎讨
论。
小编后记:作者总结了这么多,佩服。但类似2.1,2.2似乎有些面向数据
设计,再反向找领域对象。
欢迎读者交流!