前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DDD -- 领域驱动设计 -- 6步成诗法

DDD -- 领域驱动设计 -- 6步成诗法

作者头像
lyb-geek
发布2022-03-09 20:18:06
4660
发布2022-03-09 20:18:06
举报
文章被收录于专栏:Linyb极客之路Linyb极客之路

记得很多年以前读Evans的《领域驱动设计 – 软件复杂性核心应对之道》,那个时候DDD还很少人知道,更不用说实践了,这本书呢也在我的书柜里沉睡了很多年。而最近发现,不光传统重业务的软件公司,就连很多互联网公司也在推DDD。

然后呢,在不同地方听了一些DDD的分享,也看了一些DDD的博客,但整体下来,总有“新瓶装旧酒”之嫌。

究其原因:软件的方法论,到今天为止,前辈大师们已经给我们总结了太多太多:面向对象、SOLID原则、分层架构、SOA、微服务、业务建模、分析模式、设计模式、UML、4色建模、RUP 4+1、敏捷开发、CAP理论。。。

而DDD呢,其实是一个吸取百家之所长的方法论。在DDD的书里,你会看到业务分析、技术架构、设计模式等不同层次的东西。所以对于DDD的理解,需要深厚的理论和实践功底做基础,由此,你才可能把各式各样的方法论“糅杂”在一起,形成一个完整的体系。

而本文,则试图经由DDD把过去软件开发的一序列方法论串起来,最终让大家对DDD有一个系统化的认识,而不是纠结于DDD的各种细节概念。

到底什么样的软件适合用“领域驱动”

说到软件开发,下面是一些常见的套路: (1)小作坊式:纯粹需求驱动,或者说功能驱动,来一个功能做一个,不断累代码,系统越来越臃肿,到了一定程度实在受不了了,重构一把,然后继续,如此反复。。。 (2)大型流水线工厂:严格的软件过程,需求分析、业务建模、架构设计、详细设计、项目管理、测试用例编写。。人多、环节多、文档多。。 (3)技术控:做偏底层的,中间件、分布式存储、RPC框架等,主要关注点都是在技术层面,多线程、操作系统、数据结构、算法。。 (4)“大牛”驱动:有某位“大牛”在公司内部搞了一个框架,或者借助某个开源的框架,然后其他人接到需求,不断往里面填业务代码。。 (5)数据驱动:所有数据在一个DB或者中央存储里面, 所有工作以对数据的“增删改查”为中心。。

上面的分类方法呢,并不是完全的“正交分解“,很多时候做开发,是同时糅和了好几个套路。

那么DDD到底适合哪种呢?或者说,对于你当前的开发方法,是否应该考虑去学习吸收DDD呢?

在《领域驱动设计》的前言里面,明确说明了,要用DDD,有一个前提就是:“你的焦点是在领域和领域逻辑”。

“领域”是你最重要的部分

换句话说,如果你做的软件,领域不是最重要的部分。比如做底层系统,你的最重要的部分或者是存储,或者是解决分布式一致性,或者解决高并发问题。那可能你就不需要搞DDD。

但不要陷入一个误区:“重技术”的系统就不需要DDD。一个“重技术”的系统,可能同时也是一个业务非常重的系统,这样的系统,DDD也能发挥巨大价值。

“领域”要够复杂

如果你的领域比较简单,就数据库的CRUD就搞定了,那也不需要用DDD。但实际情况是,简单和复杂的分界线并没有那么清晰。可能一个软件你刚接手时,发现蛮简单的,但越做发现坑越多,越做发现越复杂。

另外,即使对同一个领域,不同人的看法也是不一样的,有的人会认为蛮简单的,有的人会认为很复杂,这也是一个很凭经验判断的事情。

关于这个呢,《实现领域驱动设计》里面开篇专门搞了一个打分卡,让你来衡量你的领域逻辑是否足够复杂到要用DDD。个人觉得这个打分卡是一个很不错的参照,让你对“什么是复杂”有一个直观的认识。

DDD核心要点之1: 统一语言,分析与设计不再2张皮

在传统的软件开发方法中,“分析”与“设计”往往是分开的。“分析”呢,不管技术如何实现,专注于业务分析,业务建模,建模人员呢,通常都不是程序员,而是领域专家; “设计”呢,根据业务建模结果,做架构设计,详细设计,然后进行编码实施。

这种办法经常遇到的一个问题是:领域专家、架构师、程序员不是在同一个“东西”上沟通。领域专家搞的业务模型,到了设计那,觉得这种业务模型很难实现,就会抛弃业务模型中的某些东西,等架构设计、详细设计搞完之后,这个业务模型可能就“束之高阁”了。

为此,DDD发明了一个词:Ubiquitous Language,让领域专家、架构师、程序员都用这同1种语言沟通,避免“牛头不对马嘴”的问题。那么这个UL语言,包含了哪些单词呢?

限界上下文/子领域; 实体/值对象/领域服务/领域事件; 聚合根/工厂/仓库;

DDD核心要点之2:吸百家之所长,为业务之所用

前面说了,DDD是一个很需要功底才能看明白的方法论,因为它糅合了软件方法论的各个层次的东西。要明白DDD,先的把下面列举的这些东西消化吸收。

架构模式

分层、六边形、SOA、CQRS、Event Sourcing

分析模式

详见Martin Flower的《分析模式》一书,里面总结了一些常见的业务模型的分析方法

设计模式

比如“工厂”,以前讲“工厂模式”,主要从技术角度去讲。而在DDD中,它把”工厂“的思想,应用到了业务分析上面。 当然,他在书中也说了,不是所有的”设计模式“都可以应用到业务层面,哪些能用,哪些不能用,没有一个标准答案。但这种”把技术模式应用到业务层面“的思想,非常值得借鉴。

DDD核心要点之3:DDD不关注什么东西?

DDD主要关注”领域“,但在实际软件开发中,除了”领域“,还有一些东西,对我们可能也很重要。

比如《软件架构设计》这本书中,提到的架构的5视图中,物理架构/运行架构在开发大型分布式系统中,也是至关重要。

在使用DDD做好业务分析的同时,我们也需要从技术角度去考虑这些问题。

如何实现DDD – 6步成诗法

在从宏观层面对DDD有了一个把握之后,接下来进入实施环节,讲解如何一步步实施DDD。

当然,下面的方法只是个人观点,每个人都可以根据自己的实践去形成自己的一个套路。

第1步:消化知识,梳理领域概念/流程

需求分析结束之后,我们知道了系统要做哪些功能。接下来就是进入DDD的第1个环节:梳理领域里面的所有”专业名词“,”业务流程“。

这个环节,考验的不是“技术”,而是你的业务sense,你的深入思考能力,说的再大一定,包括你的“情商”,你的沟通能力、表达能力。

在这个环节,你可能需要跟很多人沟通,产品经理、运营人员、领域专家、客户等等。对同一个“名词”,不同人可能会给你不同的答案,你需要去提炼每个“名词”背后的本质。

除了“专业术语”,对于核心的业务流程,你也需要梳理的很清楚。每个流程,参与者都有哪几方,分为几步,每步都有哪些业务规则。

第2步:划分子域

第1步做的差不多了,就进入第2步。这里要说明的是,并不需要第1步想到100%清楚之后,再进入第2步,这里会有个反复迭代的过程。

所谓划分子域,就是你并不需要为整个系统建一个统一的“大模型”,把所有概念都涵盖里面,这对脑容量的挑战会非常大。你可以按照高内聚、低耦合的原则,把领域划分成几个子域,每个子域有自己清晰的界限,分而治之。

在划分好之后,你可以再回去优化第1步,进一步在每个子域里面,提炼概念。

第3步:每个子域里面找“聚合根”

子域有了,现在每个子域里面有一堆 “概念”,平铺开,平等对待每个“概念“,太琐碎。 接下来,在这一堆”概念“里面,找几个”老大“出来,也就是聚合根。每个老大带几个小弟。

第4步:聚合根之间引入“领域服务”

每个子域里面,有了几个老大。老大与老大之间,如何互相协作呢?

比如现在有一个业务流程,需要多个老大,每个老大带的团队都要做一部分事情。你可以让某个老大负责协调,也可以在搞一个”协调者“,由它统一协调多个老大。

这个“协调者”,就是领域服务。

第5步:“领域服务”之间/ “子域”之间引入“领域事件”

有了“领域服务“,“领域服务”和“领域服务”之间就可以引入“领域事件”,一个流程做完了,发一个事件出去,另一个接收到事件之后,开始下一个流程;

同样,每一个“子域”,在实现层面,就对应一个SOA服务。它们之间也可用“领域事件”串起来。

第6步:架构重设计

在前面5步做完之后,我们基本在实现层面,确立了多少个SOA服务?每个服务内部多少个聚合根?多少个领域服务? 服务之家多少个“领域事件”?

但这种设计,过于偏重“业务”,还没有考虑要解决的一些“技术难题”,比如拆了多个服务/多个DB之后,查询的效率问题? 比如发事件,如何保证事件的不丢不重?

这就是接下来要说的CQRS和分布式事务:

CQRS

CQRS全称是Command Query Responsibility Separation,也就是读写分离。

拆了之后,不是查询的慢吗,那可以实现读写分离,比如把所有的写的DB数据,全部进入到搜索引擎里面,所有的查询都在搜索引擎里面解决,领域模型只负责写入问 题。

不用搜索引擎,用DB也是一样的思路。另外搞一个DB或者表,把查询的数据,提前在这join好,查的时候就不用再把分散的数据拼装在一起了,这也就是“重写轻读”的思路。之前我在另1篇博客 “分布式架构–思想与理论–基本思想汇总里面”已经谈了这个问题。

分布式事务

消息的不丢不重是解决分布式事务的一个关键,关于分布式事务的问题,我在另一篇博客 “分布式消息队列RocketMQ–事务消息–解决分布式事务的最佳实践”里面有详细探讨,此处不再详述。

下面以图的形式来形象的展示一下上面6步最终形成的结果:实体/值对象由聚合根管理;聚合根之间串成领域服务;领域服务之间用领域事件通信;领域服务组成子域;子域之间用领域事件通信。

最后

本篇没有详细的去讲DDD的各种细节,而是想让大家对DDD有一个宏观认识,知道如何去看待DDD?DDD可以干什么,不能干什么? 知道DDD和传统的各种软件方法论,有一个什么样的源渊?

关于DDD里面的各种术语,各种细节,后面有机会一一讲述。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Linyb极客之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 到底什么样的软件适合用“领域驱动”
    • “领域”是你最重要的部分
      • “领域”要够复杂
      • DDD核心要点之1: 统一语言,分析与设计不再2张皮
      • DDD核心要点之2:吸百家之所长,为业务之所用
        • 架构模式
          • 分析模式
            • 设计模式
            • DDD核心要点之3:DDD不关注什么东西?
            • 如何实现DDD – 6步成诗法
              • 第1步:消化知识,梳理领域概念/流程
                • 第2步:划分子域
                  • 第3步:每个子域里面找“聚合根”
                    • 第4步:聚合根之间引入“领域服务”
                      • 第5步:“领域服务”之间/ “子域”之间引入“领域事件”
                        • 第6步:架构重设计
                          • CQRS
                          • 分布式事务
                      • 最后
                      相关产品与服务
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档