DDD(Domain Driven Design) 领域驱动设计从理论到实践 五

… 接上

四. 领域驱动设计基本概念介绍

​     在介绍领域驱动涉及的基本概念之前,我们先来看一下传统的思路容易形成什么问题。

​     无论是单体应用或者是服务化架构,开发人员在基本了解需求后,很容易从设计数据库模式开始。也就是说,开发人员会从业务需求上先构思实体关系图(ER-Graph),然后再以CRUD的思路来设计业务服务和代码。这种方式在简单业务逻辑上可以工作得很好,但是随着业务逻辑日趋复杂且需求频繁改动和增加,整个系统就会变得越来越难以维护和迭代。

​     开发人员会设计很多只有getter和setter的类,而这些类完全不能反映业务语义,同时业务规则代码散乱在服务层,随着需求变化,服务层代码会越来越厚。这种方式建立起来的模型我们称之为贫血模型。由于业务规则被映射成为了直接对数据库操作的增删改查,所以所有性能压力被导向数据库层。由于数据库只有一个,也没办法根据业务对象相关性进行拆分或者对读写操作分别优化,这就产生了所谓高手才具备的技能:分库分表,读写分离等。想想也挺可笑的!最后的结果就是产品质量下降,运维成本越来越高。当然贫血模型的产生还与市面上的一些主流开发框架有关,例如Hibernate等。

​     进一步讲,贫血领域对象存在对象-关系失配问题,你花了很大代价开发领域对象,却从中受益很少。开发者需要把很多时间花在对象与数据存储之间的映射上。这种对象只是把关系数据库中的数据模型映射到了对象上而已,更像是活动记录;而这样做花的代价很大,收益很小。

​     上述这种开发思路我们称为数据驱动开发,所形成的包含各种业务规则的代码称为事务脚本(Transaction scripts)。如前所述,这种开发思路在业务逻辑简单的情况下是没有问题的,甚至是比较好的选择;而在业务逻辑非常复杂的情况下是很难维系的。

​     DDD提供了应对复杂业务逻辑的一个有效的思路,它完全是从业务视角出发来审视全局的贯穿整个研发过程的思想方法,它既不是架构方法也不是设计模式。笔者理解其基本理念是:技术是服务于业务的,所以必须以业务目的来指导开发过程;没有任何理由依赖于技术栈或者数据模型,这些只是实现业务功能的技术手段而已。

DDD开发流程

​     我们先来看一下DDD的开发过程:
在这里插入图片描述
​     上图清晰地展示了领域驱动设计的基本工作流程和迭代过程。这里的问题域+业务期望实际上指的就是业务领域,领域可进一步划分为子域。从DDD的概念上子域可以分为三类:核心域通用域支撑域

领域的划分:核心域、支撑域、通用语

​     核心域代表着整个领域模型中最为重要和关键的子域,一般来说是指对于此领域而言最重要、最核心的业务逻辑。在整个研发过程中,我们应该更关注核心域。支撑域通用域对于整个领域模型而言也是必要的,只是支撑域主要是针对业务的某个重要方面,并不聚集核心的业务知识;通用域则可能被用于整个业务系统。请看下图中的例子,图中展示了一个ERP系统的领域模型。该模型可以为采购人员提供决策工具,从多年人工处理过程中积累起来的算法实现自动化,这里的最优获取核心域能够大大提高企业的竞争优势。
在这里插入图片描述
​     如果是第一次接触领域驱动设计的概念很容易被这张图搞晕了。让我们来解释一下:

​     图中虚线分割了子域;每个子域有其对应的上下文,例如购买子域中的购买上下文。到这里,我们引出了领域驱动设计中比较难理解的一个概念,界限上下文(Bounded Context)。各个上下文的实线连接表示它们是有引用或者调用关系,而所有上下文和它们之间的关系称为上下文映射图(Context Mapper)

界限上下文

​     我们尝试进一步理解一下什么是界限上下文(Bounded Context)。在本系列文章第一节中,我们解释了软件系统可以理解为从问题空间到解决方案空间的映射。领域的概念可以理解为问题空间,统一语言可以认为是对问题空间的精确定义和描述,而界限上下文则代表了解决方案空间。

解决方案空间
问题空间
界限上下文1
界限上下文2
...
界限上下文n
领域
核心子域1
支撑子域2
...
通用子域n

​     界限,指存在显式边界;上下文,指应用的场景和环境,业务术语或者陈述在这个场景下的含义是有精确定义的。领域模型就包含在这些界限上下文之中,模型中的每一个概念,包括其属性和方法,在边界之内都具有特殊的含义。

​     这么说还是比较抽象,让我们看几个例子:

​     例如账户(Account)这个领域概念,它在银行上下文(Bank Context)中表示的是一个客户的存款状态和每次交易记录,可能有支票账户和储蓄账户等等;但在文学上下文(Literary Context),它表示的可能是某一篇文学作品在一段时间内所发生的一系列事件。同样是账户,在不同的上下文环境中,其含义是不同的。

​     又比如一篇科技论文从撰写到上线,会经历制作、编辑、审核、加工等各个阶段。在每个阶段都被称为论文,但其含义是不同的。制作阶段是指作者的撰写过程,主要注重内容;编辑过程注重对文章的修正和一些编辑规则;审核阶段注重该论文的审核状态;而加工阶段则注重改论文的分类和标签等。

​     再如在金融领域,证券交易委员会限制证券只能和股票一起使用。但是很多金融公司把期货也分类成证券,从文化上来讲也是合理的。所以如何正确地表示期货(Futures)取决于其所在的环境和领域。

上下文映射图

​     我们再来看一下上下文映射图(Context Mapper)

​     从实现业务功能需求来看,只有界限上下文是不够的。这些界限上下文一定需要共同协作来提供业务处理能力,说明界限上下文之间存在协作集成关系。一个简单的抽象图例如下:
在这里插入图片描述
​     图中,U(Upstream)和D(Upstream)代表上下游关系。这种定义的逻辑是上游会影响下游,而下游不会影响上游。笔者认为可以简单用河流的上下游来理解,假如一条河的上游有了污染肯定会扩散到其下游,而下游有了污染是不会传导到上游的。

​     在DDD中定义了多个界限上下文的集成关系,让我们简单梳理一下:

  • 合作关系(Partnership)

    如果两个上下文需要建立起一种合作关系,也就是说要么一起成功,要么一起失败。他们需要协同开发和集成管理。

  • 共享内核(Shared Kernel)

    对模型和代码的共享产生一种紧密的依赖性。换句话说,就是说两个上下文共享一组模型和代码。

  • 客户方-供应方(Customer-Supplier)

    供应方作为上游,而客户方作为下游。在上游的开发过程中应该顾及下游的需求。

  • 遵奉者(Conformist)

    下游团队完全遵循上游团队的方案,盲目使用上游团队的模型。

  • 防腐层(Anti-corruption Layer)

    主要为其他上下位提供的模型进行翻译转换为自己所需的模型。

  • 开发主机服务(Open Host Service)

    公开一种协议,让其他系统通过该协议来访问你的服务。

  • 发布语言(Published Language)

    通常和开放主机服务一起使用,提供模型使用的公用语言。

    请看下面的图例:关于敏捷项目管理软件的领域模型中的一部分
在这里插入图片描述
    另外还有另谋他路(Separate Way)和大泥球(Big Ball of Mud)。前者是在两个上下文确实不存在直接关系时,研发人员寻找其他更简单的方案解决问题;后者在已有系统中经常存在,就是在系统中会发现混杂在一起的模型,已经很难拆解,而这通常是由于非良构设计导致。

​     到这里,我们简单介绍了DDD中关于其战略设计的相关概念。用一句话概括的话就是:DDD的战略设计就是得到通用语言和上下文映射图。如果是初接触DDD的读者很可能依然对上面所述的这些概念感到困惑。请大家别着急,在实践部分我们结合实践再来审视这些概念和设计思维,相信会对大家有帮助。

未完,待续…
DDD(Domain Driven Design) 领域驱动设计从理论到实践 一
DDD(Domain Driven Design) 领域驱动设计从理论到实践 二
DDD(Domain Driven Design) 领域驱动设计从理论到实践 三
DDD(Domain Driven Design) 领域驱动设计从理论到实践 四
DDD(Domain Driven Design) 领域驱动设计从理论到实践 五
DDD(Domain Driven Design) 领域驱动设计从理论到实践 六
DDD(Domain Driven Design) 领域驱动设计从理论到实践 七
DDD(Domain Driven Design) 领域驱动设计从理论到实践 八
DDD(Domain Driven Design) 领域驱动设计从理论到实践 九

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值