但是软件开发还有一类知识是没法通过分工解决了,上图箭头表示的就是领域知识必须随岗位传递,需求分析师把业务转换成需求文档,然后这个需求文档里面的业务知识必须传递给开发,开发必须理解清楚了才能干活,现实中确实出现了很多这样的情况,开发需求都没理解透,就开始设计编码,最后做出的东西跟实际业务需求不一样,返工,开发和产品经理矛盾重重。如何让业务知识快速传递,是迫切需要解决的问题。
这里得到第二个结论:
软件开发过程中的业务知识需要消除知识壁垒才能提升效率
从两个结论看好像有冲突,从第一个结论看,分工是有意义的,从第二结论看,不分工反而是好的。随着各个岗位专业度的提高,分工是必然的,那么怎么解决业务知识传递问题, DDD的一个核心模式是统一语言,用于解决解决业务知识传递的问题。
统一语言有两个含义。
1、统一交流语言。
我们把业务名词的含义事先确定好,在业务和技术的各个岗位都统一认知,这样在交流时,由于对业务名词的理解已经同频了,会节省很多沟通成本。
这里举个没统一语言的例子,我们公司有个有个渠道的概念,每次讨论这个渠道就容易出现每个人理解不一样,有的把电商平台一个店铺当渠道,有的把电商平台当渠道,还有人理解成其他含义。这是因为每个公司都有些历史遗留原因对名词的定义变味道了。
2、统一领域模型和代码模型。
我们知道一个系统最重要的知识沉淀就是代码和文档了,当然很多公司都没文档,程序员嘛,都一个尿性,恨别人不写文档,恨自己写文档。想一想当一个新人来接手一个项目,这个项目有一份设计文档和代码,设计文档里面描述的业务模型跟代码模型不一样时,我想这个新人是蒙圈的,到底哪个是对的,心里绝对会骂娘。当业务模型和代码模型一样,会大大降低我们系统的认知复杂度。
二、复杂系统设计
为了降低业务系统复杂性,一般是通过分而治之的方式,现在流行的微服务就是基于业务维度进行拆分,那么到底怎么拆分。
如下图,每个点代表一个领域对象,当很多个对象混合在一起时,设计者或者开发者需要了解所有领域对象,无疑增加了复杂度。如果能找到一种方式合理划分边界,让联系紧密的对象聚合在一起(比如下图中形成ABC三个聚合),聚合之间通过接口交互,那么接口数量会是最少的。有点类似K聚类算法,总能找到一种最优的划分方法,当然很多情况下依赖架构设计者的经验。DDD的限界上下文提供了一种指导思路,限界上下文划分好后,一个限界上下文可以对应一个微服务。
这里同样运用了建立知识壁垒可以提升效率这个理论,开发A服务的人实际上不需要了解B服务的内部实行,只需要了解B提供的接口即可,A服务的领域对象数量已经大大下降了,无疑降低了复杂度。
拿一个大学里面的一个学生管理系统来说,涉及到如下领域对象:学生,教师,角色,权限,菜单,课程,课程排班,签到等。
现在来划分限界上下文,因为学生和教师都需要登录和权限,我们一种上下文分解的方法是鉴权上下文<角色,权限,菜单,学生,教师>, 授课上下文<课程,课程排班,签到>。
从关联度来看,这两个上下文需要4个接口来做交互。
由于DDD里面规定限界上下文一个领域对象有确定的含义,学生和教师这个两个在鉴权上下文里面是系统的一个用户,放到授课上下文里面代表了两种不同的身份,也就是当我们说到学生时,到底是需要登录的一个用户还是授课里面的学生,含义是不确定的,所以这里缺了一个领域对象用户。
增加用户这个领域对象后,限界上下文重新划分,只需要2个接口做交互。