DDD战略战术

《DDD开篇总结》的前三篇已经阐述了几个内容

  1. DDD是什么
  2. 复杂系统的特征
  3. DDD如何应对复杂系统
  4. 模型概念
  5. 软件开发流程

但一般DDD资料中都会分为两部分讲述:战略和战术,所以按这两种分类,重新归纳整合一下

在讨论战略和战术前,先表述一下“道”

DDD是一种软件开发的方法论,任何方法论,都必须落实到“减少代码复杂度”

那么“道”是什么呢?

一直认为DDD的战略就是道,结果搞错了

软件开发的终极“道”就是“高内聚、低耦合”,它是任何有价值思想和方法的具象

如何才能达到这个终极道呢?

    1. DRY
    1. 分离关注点
      • 2.1. 业务和技术分离
      • 2.2. 业务和部署分离
      • 2.3. 变与不变分离
    1. 缩小依赖范围
    1. 向稳定方向依赖

战略

DDD战略主要包含统一语言和限界上下文

统一语言

在以往OO开发过程中,会经过OOA,再到OOD,复杂系统中,没有人能全方位了解系统并实现系统,术业有专工,专业人士干伟业事,这是正确的

但分工后,团队合作时沟通至关重要,,在整个系统开发过程中,是有一根主线的,那就是业务知识,业务知识在系统落地前经过层层传递,走样变形是常有的事,从开发人员经过多少次的返工情况就很清楚

如果解决这个问题呢?DDD引入了统一语言,把业务名词含义事先确定好,减少不必要的翻译过程,车同轨,书同文,行同伦

这也消除了业务与技术之间的重复,共同使用业务原语对话

代码就是文档,代码就是领域知识

1
2
userService.love(Jack, Rose) => Jack.love(Rose)
companyService.hire(company,employee) => Company.hire(employee)

界限上下文

界限上下文囊括了实现道的方方面面,如分离关注点,每个上下文围绕一个关注点,通过整洁架构让各层向稳定方向依赖,合理的划分界限,使各个上下文之间减小依赖

说白了界限上下文就是把一个大系统分而治之

界限上下文算是DDD中的核心知识点,但常被技术人员忽视,对于实用主义的程序员来讲,战术常常更吸引人,其实大到微服务,小到实体类,背后都渗透着上下文的概念

引入限界上下文的目的,不在于如何划分边界,而在于如何控制边界

Alberto Brandolini认为bounded context are a mean of safety(限界上下文意味着安全),safety的意思是being in control and no surprise,对限界上下文是可控制的,就意味着你的系统架构与组织结构都是可控的

显然,限界上下文并不是像大多数程序员理解的那样,是模块、服务、组件或子系统,而是你对领域模型、团队合作以及技术风险的控制

限界上下文是“分而治之”架构原则的体现,我们引入它的目的其实为了控制(应对)软件的复杂度,它并非某种固定的设计单元,我们不能说它就是模块、服务或组件,而是通过它来帮助我们做出高内聚低耦合的设计。只要遵循了这个设计,则限界上下文就可能成为模块、服务或组件。所以,文章《Bounded Contexts as a Strategic Pattern Beyond DDD》才会写到:“限界上下文体现的是高层的抽象机制,它并非编程语言或框架的产出工件,而是体现了人们对领域思考的本质。”

战术

对于开发人员而,战术是最实用的,比如聚合、实体、值对象、工厂、仓储、领域事件等等,
使用这些战术组件建模工具,DDD满足了软件真正的技术需求。这些战术设计工具使开发人员能够按照领域专家的思维开发软件

战略部分讲了,界限上下文的思想是核心,在战术组件中都有体现,比如实体,实体就是一个最小上下文,聚合就是相对实体大一点的上下文

但残酷的现实是,花费了大量的精力来学习这些DDD战术组件,却在实现项目中却用不上,为什么呢?因为事务脚本思维太深,分层也大多是从技术角度出发,没有抽象出领域模型,也就是没有OO抽象,没有一个完整的对象,实体都没有,像工厂,值对象也就成了水中花

这也是我们虽然常重构代码,也不过是大类变小类,大函数拆分成小函数,符合一下代码规范,但对整个项目而言,其实没有实质性改进

如何能有实质性改进,对于复杂系统如何运用上这些战术组件呢?

此时,结构性思维发挥作用了

第一步:过程分解,把一个复杂的系统按流程拆解成各个阶段和步骤,这也是事务脚本的强项

第二步:对象建模,过程性拆解虽然可以降低了开发难度,但领域知识被割裂,代码的业务语义也不明确,在这方面OO是强项,提升代码复用性和内聚性

结合这两步,自上而下的结构化分解+自下而上的面向对象建模,过程化分析更好地清理了模型之间的关系,而对象模型提升代码复用性和业务语义表达能力

总结

DDD是一套很好的方法论,有时我们常在理论纯洁性与实战性之间徘徊。这也许是初级阶段常有的纠结点

DDD有适用场景,事务脚本有存在的优势

不能因为现在人们开口闭口都是DDD,就硬要开展DDD

DDD难以落地除了本身带来了很多概念,还需要团队整体素质

软件开发没有银弹,不能偏执于一种理论,实际开发是场硬仗,像混合格斗一样,不在于一招一式是哪门哪派,制敌才是终极目标,所以需要根据自身情况进行裁剪,灵活运用

公众号:码农戏码
欢迎关注微信公众号『码农戏码』