1、前言
DDD(领域驱动设计)的一些介绍网上资料不少,这里就不继续描述了。本身使用领域驱动设计摸滚打爬也有2年多的时间,出于对知识的总结和分享,也是对自我理解的一个公开检验,介于博客园这个平台也算是对DDD的推广尽了一份绵薄之力。一开始接触这个东西是在2014年,真的以为像是发现了一片新大陆通常,对我整个程序开发视野有了新的理解,可是像[Vaughn Vernon]《实现领域驱动设计》里写的那样,景色虽好,但是本身很长一段时间内很混乱,理不清眼前的陌生世界,由于它与传统的观念彻底不一样。我相信大部分同窗刚接触DDD的时候也会有同样的感受。
此次开始写这系列,也但愿有愈来愈多的人可以加入到DDD的队列中,在我以前,园子里的netfocus、dax.net、田园里的蟋蟀等园友都已经对推广DDD作了不少事情,再此感谢下各位,这些分享在我学习DDD的道路上给予了不少帮助。
本次系列中多处引用[Vaughn Vernon]《实现领域驱动设计》一书里的语句,我认为此书能够做为各位进入DDD的敲门砖,但愿你们可以去拜读一下此书。
2、名词解释
首先我以为有必要先把DDD中的经常使用名词作一个解释。
界限上下文:表明一个系统、一个应用程序或者一种业务服务。限界上下文所包含的领域模型概念应该恰如其分,很少也很多。
通用语言:做用于某个“限界上下文”,在一个特定的限界上下文中只使用一套通用语言,而且保证它的清晰性(避免一个概念在同一个界限上下文中的二义性)和简洁性。举个例子:像京东和天猫这样的B2C系统中会用到系统的人有2种,买家和卖家,对于系统来讲均可以称为用户,可是这样破坏了清晰性的特色。若是使用一个相似Type的枚举来区分,破坏了简洁性。因此对于这种场景,就应该直接设计2个对象:买家和卖家。
领域:从大了看,领域表明整个公司的运做一切。从小了看,是每一个组织运做中的一切。因此领域的概念必然与公司的组织架构所承担的职责有必定的关系。
子域:一个领域内能够包含1个或者多个子域。理论上一个子域对应一个限界上下文是最优也是最理想的状况,可是有时又要考虑到业务关联度须要作出权衡。子域又分核心域、支撑子域、通用子域。
核心域:它是整个业务领域的一部分,也是业务成功的主要促成因素。从战略层面上讲,企业应该在核心域上胜人一筹。咱们应该给予核心域最高的优先级、最资深的领域专家和最优秀的开发团队。在实施DDD的过程当中将主要关注核心域。
支撑子域:对应着业务的某些重要方面,但却不是核心,那么它即是一个支撑子域。
通用子域:某个支撑子域的运用范围是整个系统,那么这个子域即是通用子域。
上下文映射图:由多个界限上下文和子域组成的表示当前单个领域或者多个领域之间的集成关系图。
3、实施DDD的关键
我认为实施DDD最最最关键的东西有2样。
一是“通用语言”,没有基于通用语言创建的所谓的聚合,实体,值对象,只能算是DDDLite,只是技术层面的一种设计方式。
二是“建模”,建模又分为战略建模和战术建模,这2者相辅相成,来构建合理的上下文映射图。
①战略建模:战略建模是以一种最宏观的角度去审视整个项目对它进行拆分,来划分“界限上下文”,最终造成一个具备俯瞰视角的“上下文映射图”。
②战术建模:在咱们战略建模划出的“界限上下文”中进行“聚合”、“实体”、“值对象”的建模,而且按模块分组。
4、如何构建一个领域的上下文映射图
对于如何构建一个上下文映射图,分为思想和操做2个层面。
首先思想层面须要引入2个空间的概念:问题空间和解决方案空间。
在问题空间中,咱们思考的是业务所面临的挑战,而在解决方案空间中,咱们思考如何实现软件以解决这些业务挑战。
评估问题空间和解决方案空间的问题:
①这个战略核心域的名字是什么,它的目标是什么?
②这个战略核心域中包含哪些概念?
③这个核心域的支撑子域和通用子域是什么?
其次操做层面就是[Vaughn Vernon]《实现领域驱动设计》里提到的9种组织模式和集成模式。
①合做关系(Partnership):若是2个限界上下文的团队要么一块儿成功,要么一块儿失败,此时就是这种关系。应该为相互关联的软件功能制定好计划表,这样能够确保这些功能在同一个发布中完成。
②共享内核(Shared Kernel):对模型和代码的共享将产生一种紧密的依赖性,对于设计来讲,这种依赖性可好可坏。咱们须要为共享的部分模型指定一个显式边界,并保持共享内核的小型化。共享内核具备特殊的状态,在没有与另外一个团队协商的状况下,这种状态是不能改变的。咱们应该引入一种持续集成过程来保证共享内核与通用语言的一致性。【简单的说就是数据库共享】
③客户方——供应方(Customer-Supplier Development):当2个团队处于一种上游——下游关系时,上游团队可能独立于下游团队完成开发,此时下游团队的开发可能会受到很大的影响。所以,在上游团队的计划中,咱们应该顾及到下游团队的需求。
④遵奉者(Conformist):在存在上游——下游关系的2个团队中,若是上游团队已经没有动力提供下游团队之需,下游团队便孤军无助了。处于利他主义,上游团队可能向下游团队作出种种承诺,可是有很大的多是:这些承诺是没法实现的。下游团队只能盲目地使用上游团队模型。
⑤防腐层(Anticorruption Layer):在集成2个设计良好的限界上下文时,翻译层可能很简单,甚至能够很优雅的实现。可是,当共享内核,合做关系或客户方——供应方关系没法顺利实现时,此时的翻译将变得复杂。对于下游客户来讲,你须要根据本身的领域模型建立一个单独的层,该层做为上游系统的委派向你的系统提供功能。防腐层经过已有的接口与其余系统交互,而其余系统只须要作很小的修改,甚至无需修改。在防腐层内部,它在你本身的模型和他方模型之间进行翻译转换。【为每一个防腐层定义相应的领域服务】
⑥开放主机服务(Open Host Service):定义一种协议,让你的子系统经过该协议来访问你的服务。而且须要将协议公开。
⑦发布语言(Published Language):在2个限界上下文之间翻译模型须要一种公用的语言。此时你应该使用一种发布出来的共享语言来完成集成交流。发布语言一般与开放主机服务一块儿使用。
⑧另谋他路(SeparateWay):在肯定需求时,咱们应该作到坚持完全。若是2套功能没有显著的关系,那么它们是能够被彻底解耦的。集成老是昂贵的,有时带给你的好处也不大。声明2个限界上下文之间不存在任何关系,这样使得开发者去另外寻找简单的、专门的方法来解决问题。
⑨大泥球(Big Ball of Mud):当咱们检查已有系统时,常常会发现系统中存在混杂在一块儿的模型,它们之间的边界是很是模糊的。此时你应该为整个系统绘制一个边界,而后将其概括在大泥球范围之列。在这个边界内,不要试图使用复杂的建模手段来化解问题。同时,这样的系统有可能会向其余系统蔓延,应该对此保持警觉。
5、构建咱们的上下文映射图
本次的系列的主题是电商网站,那么如今开始构建一个电商网站的上下文映射图。
①这个战略核心域的名字是什么,它的目标是什么?
销售核心域,目标是卖更多的商品,获取更多的利润。这点是整个组织的共同目标,因此应该很容易界定,而且应该是在整个组织中能最终够达成一致的某个观点。如图1。
【图1,点击图片查看大图】
②这个战略核心域中包含哪些概念?
我通常会使用“划分”,“组合”,“梳理”的3步走方式去作。先根据咱们对这个领域的理解进行划分出各个上下文,而后从新审视每一个上下文在销售这个领域中的定位来“圈地(划分子域)”,最后再思考是否可以彻底体现出每一个子域的功能和职责。个人思路是这样的,先根据我本身的经验得出了图2。
【图2,点击图片查看大图】
我思考了一下,整个销售过程当中,订单只是一个结果,一旦到达这个环节,其实销售的工做已经结束了,那么订单的相关业务其实不该该属于销售的子域内,因此把它拿出去,变为图3这个样子。
【图3,点击图片查看大图】
而后看了一下全图,销售上下文的概念太泛,没法得知其中应该干什么,怎么去销售,有哪些影响销售概念,我又作了拆分。以下图4。
【图4,点击图片查看大图】
到这里几个核心域内包含的概念已经出来了:价格体系(促销、会员价)、销售方式(打包、捆绑赠品)、内容管理、购买。这其中最核心的又是购买。
③这个核心域的支撑子域和通用子域是什么?
这里开始咱们须要对咱们整理出的各个上下文和子域结合起来,而且根据9种组织模式和集成模式表达出各上下文之间的关系。以下图5。
【图5,点击图片查看大图】
这里的U和D分别表明UpStream和DownStream,表达出上下游关系,而且图的位置也须要看出这点。另外OHS+PL = Open Host Service+Published Language,ACL = Anticorruption Layer。
发现这里的5个子域中,订单和物流子域分别承担着2个子域的下游支撑做用,那么成为了通用子域。
最终这个问题的结果为商品子域[支撑]、会员子域[支撑]、支付子域[支撑]、订单子域[通用]、物流子域[通用]。
最后再考虑到一些非必须的辅助性概念,数据分析系统和预测系统,造成咱们的最终上下文映射图。
【图6,点击图片查看大图】
6、结语
以上的每一个环节都应该尽量有领域专家参与,这样才能得出最符合实际的上下文映射图。DDD之路很差走,而且从短时间的表面来看,须要花费的时间和精力会比咱们常规的数据驱动开发方式看上去多的多。可是从沟通的便捷性、理解的错误率、代码的可维护性来看,DDD可以让对项目的把控更上一个层级。而且为了应对互联网行业的快速变化,咱们获得的远比咱们付出的多的多。
做者:Zachary
出处:https://zacharyfan.com/archives/95.html
▶关于做者:张帆(Zachary,我的微信号:Zachary-ZF)。坚持用心打磨每一篇高质量原创。欢迎扫描右侧的二维码~。
按期发表原创内容:架构设计丨分布式系统丨产品丨运营丨一些思考。
若是你是初级程序员,想提高但不知道如何下手。又或者作程序员多年,陷入了一些瓶颈想拓宽一下视野。欢迎关注个人公众号「跨界架构师」,回复「技术」,送你一份我长期收集和整理的思惟导图。
若是你是运营,面对不断变化的市场一筹莫展。又或者想了解主流的运营策略,以丰富本身的“仓库”。欢迎关注个人公众号「跨界架构师」,回复「运营」,送你一份我长期收集和整理的思惟导图。