领域驱动设计(一)

381 阅读8分钟

领域驱动设计

前段时间跟着网上资料粗略的学习了一下领域驱动设计, 最近将之前的笔记整理好分享出来.

希望我们永远保持这份思考与热爱

内容:

  1. DDD和微服务的关系

    DDD比微服务出现对要早很多,但近今年随着微服务又才火起来的,这是为什么呢?为什么说它和微服务是天作之合呢?

  2. DDD和微服务编码实战

    从具体对编码讲起,理解如何在DDD和微服务对指导下开发应用程序

  3. DDD和微服务边界划分

    DDD对战略设计是如何指导微服务划分的呢?

  4. DDD和中台的关系

    在构建业务中台对过程中,通常把DDD作为重要对方法之一,到底DDD在中台建设中能起到什么作用呢?

一. DDD和微服务的关系

1. 初识DDD (Domain Driven Design)

  1. 领域

    ​ 领域是相对于系统而言的,系统是一种解决方案,领域就是系统要解决的现实问题所属的空间,即它是问题空间,这个空间主要由业务知识或活动组成。

  2. 设计

    ​ 设计是一种“有目的的创作行为。软件设计是根据需求分析阶段确定的功能来设计软件系统的整体结构、划分功能模块、确定每个模块的实现算法以及编写具体的代码,最后形成软件的具体设计方案。设计属于解决方案空间。

  3. 核心复杂性

    ​ 复杂性分为必然复杂性和偶然复杂性。那核心复杂性指的什么?通过领域“驱动”设计就能解决这个复杂性吗?如何“驱动”?

2. 为什么微服务需要DDD

微服务解决了哪些问题?解决不了哪些问题?

2.1 扩展和拆分

  1. 扩展/伸缩的三个维度

1_1.扩展立方体.png

X轴和Z轴扩展有效地提升了应用的吞吐量和可用性,

然而没有解决日益增长的开发问题和应用复杂性。

这需要使用Y轴扩展,即功能分解。

  1. 微服务架构

    模块化是功能分解的基础。微服务架构使用服务作为模块化的单元,它是模块化的一种形式

    • 小而专注,功能内聚,按业务边界来确定服务的边界.

    • 自治性,比如,避免把多个服务部署在一起、服务间通过网络调用通信、有自己独立的数据库等.

    所有形式的模块化都应该遵循这个原则:

    • 技术异构性 - 不同服务采用不同的技术
    • 弹性 - 处理服务不可用和功能降级
    • 扩展 - 按需在X/Z轴上进行扩展
    • 简化部署 - 更快地对特定部分的代码进行部署
    • 与组织结构相匹配 - 小的代码库可获得理想的团队大小和生产力
    • 可组合性 - 比如可以容易支持多端,PC/移动端/可穿戴设备等
    • 支持可替代性优化
  2. 小而专注,功能内聚

    解决日益增长对开发问题和应用复杂性的关键

1_2.散弹式修改.png

散弹式修改: 一处功能的修改影响的代码特别多特别散.

​ 微服务架构告诉我们应该按业务边界去确定服务的边界,但是没有告诉我们如何识别和定义业务边界。

关注微服务的本质,即服务的分解定义,而不是技术,如容器和其他工具。确保你的服务松耦合……不要搞成分布式单体,那将是巨大的灾难。

- Chris Richardson 《微服务架构设计模式》

​ 所以需要DDD来帮忙,DDD对所有对模块化都有帮助,不只是微服务。

  1. 功能的分和治

    正确定义业务边界,确定每个部分的职责和类型以及他们间的相互关系,可以:

    • 减少耦合

    • 不同类型的部分做不同投入,做到更好的投入产出

    • 有利于建立良好的团队沟通和合作

    DDD的战略设计部分可以解决这个问题

2.2 做正确的事儿和正确地做事儿

正确区分问题空间解决方案空间.

先探求正确的事儿, 然后再探求正确地做事儿.

  • 我们需要一匹跑的更快的马

    福特认为我们需要的是快速到达目的地 ,而不是马.

  • 普通的圆珠笔无法在外太空使用

    那为什么不用铅笔呢?

  • 我要赚够一千万,让前女友回心转意

  • 让订单系统打个特殊的标记,生产系统识别这个标记在拣货时做一下特殊处理

  1. 聚焦业务建立领域模型

    领域模型就是针对系统要解决的现实问题而建立的模型,它表达的是与系统相关的现实世界的不变事实,领域模型也是软件开发团队和业务专家都可以理解的模型,但它是技术无关的,它是为满足软件的功能性需求而做的抽象。

    DDD强调开发团队和业务专家一起协作探索, 围绕业务问题建立合理的领域模型

  2. 然后产出设计模型

    如果说分析是“做正确的事”,设计就是“正确地做事”。设计强调的是满足需求的概念上的解决方案。

    领域模型所体现的领域事实会在设计模型中得到延续,除了功能需求,设计模型更多的关注点会放在非功能需求(也称为质量属性,比如性能、可伸缩性、高可用性等)上,我们常说的架构设计就是设计模型里的主要内容。

1_3.rua4+1.png

  • 逻辑视图:当采用面向对象的设计方法时,逻辑视图即对象模型。

  • 开发视图:描述软件在开发环境下的静态组织。

  • 处理视图:描述系统的并发和同步方面的设计。

  • 物理视图:描述软件如何映射到硬件,反映系统在分布方面的设计。

可以看到,只有逻辑视图体现了之前领域模型的内容,其它视图关注的都是非功能性需求,从4+1视图模型里我们可以体会到设计模型里应该包含哪些内容。

也可以看一下arc42( arc42.org/overview/ ),这是一个架构设计文档模板,里面大部分内容也是关于设计模型的。

另一种流行的C4模型(c4model.com/)也是主要表达系统设计…

  1. 协作/迭代和闭环

1_4.协作迭代和闭环.png

技术专家和领域专家共同协作迭代式地探索模型, 将实现与核心业务概念模型紧密地联系在一起.

2.3 软件的复杂度

  1. 如何对复杂度进行管理

    复杂度的类型

    • 本质复杂度和待求解问题的本质有关,是无法避免的。

    • 偶然复杂度一般是因为选用求解问题的方法时所引入的,和问题本质无关,和选用求解的工具或方法有关。

    图灵奖得主佛瑞德 · 布鲁克斯《人月神话》谈到“没有银弹”时使用了这两个概念。

  2. 软件的腐化带来的熵增

    文档不可信,代码掺杂了技术和业务逻辑,随着演化越来越难以维护,难以加入新功能。

  3. 业务架构和系统架构绑定

    DDD强调业务架构和系统架构的绑定,以及和技术架构保持“低表示差异”,减少翻译的过程,系统架构随着业务架构的变化而变化,软件能最大程度地体现业务和设计决策

  4. 领域驱动设计

1_5.业务架构和系统架构绑定.png

“驱动”的含义

  • 把关注点放在核心域及核心域的领域逻辑上

  • 基于建模进行复杂设计

  • 通过技术专家和领域专家共同协作迭代式地探索模型,切入问题的核心概念

  • 将实现与核心业务概念模型紧密地联系在一起,让应用能清晰地体现业务和设计意图,让系统容易随着业务的变化容易演进

拥抱本质复杂度, 降低偶然复杂度.

领域模型应该是架构中立的。当然,在模型周围和模型之间则是存在架构的。……有时候我们过于强调架构而忽略了DDD建模的重要性。架构固然是好,但是,架构并非一成不变。此时我们必须正确地处理优先级,将重点放在领域模型上,因为领域模型将产生更多的业务价值,并且更具有持久性。

-- 《实现领域驱动设计》