写在前面:要不要DDD
网上关于领域驱动的相关文章数不胜数,但是就跟我一个同事说的,具体落地的到底有多少呢?我们说领域驱动最核心的就是领域模型,一个稳定的领域模型胜过千军万马,然而在当下依然是互联网的时代,业务告诉发展的时期,一切的产品设计和技术都是服务于业务,然而有多少业务是随心所欲闭门造车临时方案的情况,我想程序员们应该是深有体会。于是带来一个问题,业务层面如此的不固定,我们如何跟业务通过领域建模来统一语言,更别说稳定我们的领域模型了(一段时间范围内的相对稳定)。同时在那些不懂技术的老板眼里,他们只关注完成系统的开发通过时间点压榨,哪里管你因为使用了 DDD 而带来的开发周期和开发成本的增加,他们只会认为你技术不行,做这么简单的东西要那么久。好了,吐槽到此为止!
既然没有多少企业实际落地 DDD,那我们还需要 DDD 吗?
我的答案:需要,我们需要一个抓手,任何新系统的开发和老系统的重构乃至系统技术应用架构或者功能架构图,都需要一个抓手,一个切入点,一个可以撬动大家思路的武器,包括微服务的拆分,拆分的理论依据是什么? by experience ?出于慎重考虑我们需要一个抓手,因为 DDD 可能是一个。
然而虽说众多企业并没有实际落地 DDD ,或许因为其书籍和资料都过于高大上,但实际上我们平时的工作中都用到了 DDD 的部分理念和方法。例如聚合,在 DDD 建模种聚合是构建领域模型的基础。那我们在日常技术方案设计过程中多多少少都会涉及聚合,甚至我们在画 UML 类图的时候聚合就是六种关系的其中一种。
本篇文章属于软实力的修炼,而修炼内功是程序员的基本素养。
一、 模型
领域驱动最核心的莫过于领域模型,我们先聊一聊什么是模型?
百度百科解释有很多解释,我们一一理解理解。
模型是通过主观意识借助实体或者虚拟表现,构成客观阐述形态结构的一种表达目的的物件(物件并不等于物体,不局限于实体与虚拟、不限于平面与立体)
从这里的描述有几点有必要说明,首先模型并不一定是现实世界真是存在的一个东西,其次模型的建立渠道是我们的主管意识,也就是我们的大脑经过思考形成的,但不是瞎说瞎想,有依据和道理的。当然我们也可以把客观世界存在的事物直接定义成我们的模型,而在当今 MVC 的开发模式下,大部分公司大部分程序员都是如此做的也可能是如此想的。如果软件开发都是如此,那么我们确实是大家嘴里的“农民工”。
另外我们可以得到的一个信息,模型的范围很大很广,甚至不限形式不限地域和空间。
模型≠商品。任何物件定义为商品之前的研发过程中形态均为模型,当定义型号、规格并匹配相应价格的时候,模型将会以商品形式呈现出来。
这句话的描述我觉得至关重要,我们可以理解模型它其实是一种过程性的产物,不是结果的呈现,模型本身还比较靠近业务或者技术化,客户所关心的是完全商业化的呈现。
这就从另一个角度体现了建模的重要性,我们可以直接做拿来主义将一个事物直接映射成模型且一一对应,我们也需要做一些深入的思考和沉淀,好好打磨一下我们的模型。
从广义上讲:如果一件事物能随着另一件事物的改变而改变,那么此事物就是另一件事物的模型。模型的作用就是表达不同概念的性质,一个概念可以使很多模型发生不同程度的改变,但只要很少模型就能表达出一个概念的性质,所以一个概念可以通过参考不同的模型从而改变性质的表达形式。
广义的定义告诉我们模型是变化的,而且不是拘泥于一种形式或者某一个单一的模型,甚至有时候非常负责的模型才能让我们理解和明白某一个定义和概念,所以模型本身又是复杂的,而建模的过程又是非常有意思的。
当模型与事物发生联系时会产生一个具有性质的框架,此性质决定模型怎样随事物变化。
这里引出了框架,让我们从中闻到了一丝丝架构的气息,这再一次说明模型是多么的重要,并且当他和真实世界发生关联的时候,所产生的蝴蝶效应也将预示着事物发展的过程和结局。
总结:模型是用来表达现实世界的真实或者虚拟的事物,用来表达某种概念,让我们获得某种认识,并在在未来事物的发展和演变过程中,我们可以通过某种框架来控制和稳定事情的发展,以防止出现我们无法控制的局面出现。
最后模型属于数据领域,所以谁说我们小学、初中和高中学习的语数外没有用,其实作用和用途无处不在,只是说出这种话的人们不自知。
二、领域
我们看一看什么是领域。
其英文叫:domain
中文含义:
具体指一种特定的范围或区域.
我们画出重点范围二字,也就是领域模型其实是表示某种具有范围的概念、认识、事物。就如同我们作为技术 PM 上线某个项目一样,一定是在一个有限的时间内,完成某个工作清单里的一个一个的任务,项目管理最重要的事情就是项目范围。同样在我们领域建模最重要的也是确定模型涉及的范围。以下是其他的解释,不过大体意思相似:
一国主权所达之地。
一种专门活动或事业的范围、部类或部门。
学术思想或社会活动的范围。
三、领域模型
领域驱动有几个非常重要的概念:核心域、子域、通用域、限界上下文。
核心域:决定产品和公司核心竞争力的子域,是业务成功的主要因素和公司的核心竞争力。从这个定义中我们可以看到核心域其实就是我们当前业务最直接最忒且的内容,例如点餐的 APP ,那么其核心域就应该是跟点菜、菜品管理、发布菜品、菜品评价、菜品订单,那在这个 APP 里的其他功能比如用户、库存、配料、支付、用户的订单甚至账务这些要么通用域要么是支撑域。
通用域:顾名思义,具有通用性,在点餐的 APP 中,用户、库存、配料这些就属于通用域,被多个子域所引用。
支撑域:它是用来解决某一个业务问题,在点菜的 APP 中用户的支付订单、账务、支付就是支撑域,为了解决 APP 支付相关的某一个业务问题。
限界上下文的理解非常重要,它也将确定我们领域划分边界。我们在弄清楚哪些是核心域、通用域、支撑域后,我们需要对产生的聚合进行分组,通过业务的内聚性和关联度划分边界,结合上下文含义并给出上下文名称。限界上下文不是跟模型一一对应,可以是多个模型组成一个限界上下文,它的作用可以明确模型有解决的问题,并保持每个模型的清晰。我们讲领域的核心在于确定范围,而限界上下文就是领域模型的边界,也是我们对领域认知的边界。我们常说的高内聚低耦合意思就是在某一个限界上下文内,模型之间紧密关联,而其他模型应该在其他的领域限界上下文中。
那为什么说限界上下文跟模型不是一对一的,可以是一对多的?
模型不是万能的,模型存在的意义就是描述现实的真实或者虚拟事物,并一定要能够解决现实的问题。世界也是不停变化的,事物也是发展变化的,所以现实情况的种种问题也是复杂多样的,往往用一个或者两个模型也无法能够非常清晰的面面俱到的描述和解决所有问题,这个时候我们就需要把多个模型围起来,形成一个整体来解决问题,对这个整体进行建模。
子域:可以解决某个特定的问题。
四、如何领域建模
网上有各种领域模型的详解,也有很多领域建模的方法和例子,在这里把个人认为比较好理解,比较好实施落地的方法列举出来。其实对于如何领域建模的方法论也不是每次都按部步骤去实现,在某些领域划分不清或者分歧较大的时候,通过对业务流程的重塑也许就找到解决问题的钥匙。
所有的开发工作都离不开业务流程的梳理,然后将业务转化成产品语言,技术将产品设计落地实现。所以第一步就是画出所有的核心业务流程,任何业务也都存在一条稳定的业务流程,而业务流程中节点的产物就是我们的业务骨架。一般我们采用如下形式画出业务流程:
这里强调的是核心业务流程,核心业务流程可以觉得我们的核心业务域,同样也可以对我们的界限上下文的确定有一定的辅助作用。
挖成第一步后,接下来就是业务子流程的再分解,一般我们会形成如下形式的图:
简单的两部,可以大概确定我们的领域模型有哪些,可以支撑什么业务解决什么问题,但是哪些是核心域、支撑域、通用域,限界上下文如何执行还需要通过抽象和分析,结合各自的作用进行细致的划分。
有的同行甚至把领域建模的方法总结成了三字经方法:找名词、加属性、连关系。
五、就这么结束了
本文没有举真实的案例,并不是从来没有实践过 ,而是我亦在总结和找到个人认为比较能接手的方法论,用来知道以后遇到的一些情况,也是为了强化和修炼内功心法,作为程序员技术不可丢,但是只有上层剑法秘籍,没有深厚的内功方法论,如何合二为一具备持续的竞争力呢。在这个浮躁的社会,越是晦涩难懂的东西越需要静下心来好好总结,现在网络流程叫沉浸式!
在未来我还会总结一些其他方面更为晦涩难懂的理论,人们总是在找一种平衡点,理论过于深奥读不懂,过于白话那是别人总结的精华不是自己的,最后要问自己一句:核心竞争力在哪里!