各位好,我是一名普通的软件开发者。现在我将在这里分享我对领域驱动设计的一些理解,我预计会花费几章内容,给出我是如何落地领域驱动设计的,并会贴出一些关键的代码。第一章我将结合一个大家熟悉的业务,来帮助大家理解DDD是什么、战略层面建模会涉及到哪些基本概念
DDD到底是什么?DDD是一种方法论,它可以指导我们从最开始的需求分析,到整体项目落地者一整个过程。早在20世纪90年代初,DDD就已经有落地的实践了。采用DDD落地的项目有一下两个明显的特点:
- 战略层面上,清晰的业务边界,良好的领域模型,这有助于我们产品的横向扩展
- 战术层面上,面向对象编程,代码具有良好的可读性,甚至我们的非编码人员都能读懂我们的代码逻辑
既然DDD是一个方法论,那么它肯定有一些自己的概念,我这里不直接上来就说概念,大家肯定都看烦了,我这里直接结合一个具体的业务需求,来帮助我们理解到底这些概念是什么。
以电商系统为例
假设现在我们是电商系统的整体负责人,我们需要写出一些文档,来指导我们的开发人员写代码。那么电商,就是我们的领域,更细致一点来说就是一个问题空间。注意,领域和问题空间的概念就出来了哈,领域是一个组织为了解决一个市场问题而所作出的一切。比如说,某新东方是做线下教育平台的,那么线下教育就是这个新东方集团的领域;还比如,某阿里是做线上电子商务的,那么电子商务就是阿里集团的领域。以阿里为例,为了解决市场上电子商务的需求,阿里会去招聘一批人、开发一批软件项目、做出一些服务。他们所做出的一切,就是电商领域。
那么问题空间是什么呢?问题空间就是我们要解决什么样的问题,电商项目就是要解决市场上对电子商务的需求;线下教育是为了解决市场上那些有自我驱动学习能力的人的学习诉求。此外,我还认为,问题空间是我们最核心的部分,如果我们连问题空间都搞不清楚,那么后面谈论的建模也就完全错乱了。
一般来说,领域这个概念所包含的内容太多了,它只能告知我们到底我们要干啥,但是不能指导我们具体去做某些细致的事情。所以我们会把领域拆分开来,形成子域。子域主要就是用来告诉我们,到底我要做哪些细致的事情,子域分为以下三种:
-
核心子域:代表了我们的产品、我们的项目的核心竞争力,也就是最主要的那一部分。以电商为例,商品上架、购买、发货,就是电子商务的核心。所以商品的一系列生命周期管控就是电商的核心子域。这里我多说一句,如果让我来分析什么是新东方的核心域,我觉得那些授课老师就是新东方的核心子域。所以我认为,核心子域并不是一个抽象的概念,而是具体的事物甚至是人。
-
支撑子域:在我们的产品中,可能有那么一些概念,不是我们产品的核心,但是又不得不要,因为它们会支撑我们的产品核心。比如在电商系统中,发票、物流、分析算法等,都是支撑子域。试想一下,如果我们的电商系统中,没有发票,没有良好的商品推送算法,没有用户行为的分析算法,那么我们的商品还是能卖出去的,这个系统还是能盈利的,但是没有这些,我们可能无法成为行业第一,因为有些用户他可能需要发票。
-
通用子域:顾名思义,就是产品当中,那些其他产品也可以复用的部分,比如电商系统当中的用户、权限、审批等等,这些部分不光电商用户下单的时候会用到,商家上新的时候也会用到,甚至产品运维分析的时候也会用到,所以,他们都是一个通用子域。在这里我多说一句哈,子域的划分其实和前面几年中台的划分和相似,比如阿里的通用中台。说具体点就是,可以用支付宝账号登录淘宝和阿里云,所以我们可以猜测,用户中台,就是一个通用子域,支付宝和阿里云这两个核心域都会用到用户子域
那么子域划分有什么用呢?它可以明确指导我们到底什么是我们的产品核心竞争力,如果我们是电商系统的负责人,结果我们把发票、物流当作核心子域,那么我们可能就在项目落地的过程中,我们可能会成为一个OA系统,或者成为物流系统。另外,子域的划分,还可以帮助我们划分和投入我们企业当中有限的资源。显然,核心子域应该投入更多的企业资源。
好了,到目前为止,我们以电商系统出发,知道什么是问题空间、领域、子域的基本意义。但是还不能指导我们具体怎么划分微服务,怎么写代码。但是别急,一定要认真建模,慢慢梳理,这也是DDD的特点,需要我们事前投入大量的时间和精力,显然这是值得的。我认为,作为一名开发人员,一定要成为领域专家,这样才能清晰的知道,我们在做什么,怎么做才能做的更好。接下来,我将给出一个方法,来从电商领域拆分出我们具体有哪些子域。后面的文字可能有点口水话哈,请谅解
现在,老板发话了,我们要做一个电商项目。所以,问题空间有了,接下来,我们邀请公司的产品经理、架构师、开发人员、领域专家甚至是测试人员,一起到一个办公室开会。开什么会呢?就让大家用一句话说,到底什么是电商?具体的话术模板就是:谁谁谁,用什么东西,干了什么事情,产生什么结果,可能会对后面哪些人,哪些部件产生什么样的影响。
- 开发人员A:买家使用我们的系统购买商品
- 开发人员B:买家能够在我们的系统上完成对商品的浏览、下单、支付、收货、并评价等功能。
- 领域专家A:买家使用我们的电商系统浏览、下单,支付、查看物流、收获、评价商品;并且能够实现支付功能,通知商家扣库存、发货、对账、开具发票;此外系统还能够做到精准推广、数据分析、商品推广等等功能
显然,领域专家A的描述是比较准确的,但是这一句话也太长了,长到好像只有好肺活量的人才能参与这个会议一样。但是放心,当子域拆分出来了之后,就不会再有这么长的描述了。现在,我们就用这句话,来拆分,到底有哪些子域。
-
买家和商家,我们把他们看做是用户,显然,这是一个通用子域,因为一个用户他可能是一个买家,也可能是一个快递员,也就是说一个用户可能存在商品这个系统中,还有可能存在物流这个系统中。所以,我们第一个通用子域就划分出来了,以后凡是跟用户有关的业务需求,全部在用户子域这个里面去实现。
-
商品,用户主要的操作都是围绕这商品来的,商品也是我们电商项目的主要概念,因为商品的展示,上架,购买等,都是核心逻辑。所以它显然是一个核心子域。
-
支付,我们把支付看作一个支撑子域,因为我们的电商必须依赖支付这个功能,但是我们不是做支付的,我们是做电商的,所以支付是一个支撑子域,由于有这样的划分,我们这个支付可以随时替换实现方案。这里朋友们也许会有个疑问,说,为啥你支付要单独拆分出呢?支付明明是用户的一个行为啊,应该划分在用户这个子域里面才对,这个问题很好,我认为,用户子域只是单纯承载那些用户的基本能力,因为这个用户不光是商品子域会用到,可能物流子域也会用到,那么物流子域中的用户会有支付功能吗?显然,如果把支付划分到用户子域里面去,这是不合理的,而且当企业方案变化了之后,可能我们会使用某微信支付,如果用户和支付服务在一起,那么这个更改将导致用户子域的更新,这明显不符合单一职责原则
-
按照上面的逻辑,我们将库存子域、物流子域、发票子域、数据分析子域全部划分成为支撑子域。整体如图:
总结:到此,我们清晰的从一个问题空间出发,得到了一个领域,三种子域,以及具体到底有哪子域。当然这只是一个示例,电商明显还有更复杂的业务逻辑,但是这不妨碍我们的思路和流程。最后我给出一个流程图,总结我么这一章建模的过程,以及他们的输入输出是什么。下一章我们将讨论,我们拿到了三种子域之后,接下来会怎么办
作者介绍:一名普通的开发者,想与大家一起讨论学习
有什么问题,请大家在评论区讨论哦