数字市场法案|为什么用了 DDD 以后,代码更难懂了?( 二 )


公司的业务要怎么分派给不同的人 bu(部门)去完成 , 这个一般是公司 CTO 或者 GM 要做的事情 ,部门内的项目要怎么分 , 哪些组做哪些事情 。 这是战略设计的范畴。 DDD 声称战略设计也是要有方法的 。 这部分也是很多程序员认为最没用的一部分 , 我们后面来批判一下这些程序员 。
战术设计战术设计是纯技术范畴的东西 , 最让人头痛的就是里面的名词 。
贫血模式和充血模式:DDD 推荐你用充血模式写代码 , 也就是按照 OOP 的方式去做抽象 , 然后把行为挂在对象上 , 而不是以纯过程式 的方法去写代码 。 所谓的充血 , 就是对象本身有很多关联的行为 , 而不只是一个单纯的数据库的表的字段映射 。 DDD 声称的充血模式的优势是 , 大部分的行为被封装到了对象内部 , 这样我们在阅读流程代码的时候 , 是一目了然的 , 直接能看到 step 1 , step 2 , step 3 。 但实际上即使我们不用 OOP 来组织行为 , 一样可以把不同的业务 step 做好封装和复用 。 有些公司的服务粒度拆得特别细 , 比如只有 5000-10000 行代码 , 在 DDD 里声称的充血模式的优势没有那么明显 。
值对象和实体:这个也挺离谱的 , 值对象就是纯粹的数值、文本类型 , 比如:
type person struct {
 age int
 name string

就是指对象 , 如果我们给这个 person 加一个 id , 让它能表示 person 的唯一性了;
type person struct {
 id  int
 age int
 name string

那它就是实体了 。
这两个概念只是给我们日常用的对象们进行了一个简单的分类 , 没什么大用处 。
聚合根:DDD 所谓的聚合根是事务粒度的 entity , 也就是说 , 如果我们对 db 进行存取 , 那么我们就需要有一个聚合根 , 如果在一个事务里需要操作多张表 , 那么就需要给多张表关联一个单独的聚合根 。

聚合根本可以由一个 entity 组成 , 也可以由多个 entity 组成 , 就是你完成一个任务 db 事务的时候有多少关联的对象, 那可能就有多少在同一个聚合根下面的 entity 。
六边形架构:这个所谓的六边形架构 , 就是除了业务以外的所有外部变化都抽象成 adapter interface 做适配 。 如果你稍微理解一点点点依赖反转 , 那应该知道怎么样去做这种抽象 。 如果你一点都不了解 , 那我建议你去看看 go-micro 的代码 。 如果看不懂 , 建议还是尽早转行吧~

六边形架构这东西主要是名字实在起得太奇怪 , 在 《clean architecture》那本书里 , uncle bob 也给过一张图:

《evolutionary architecture》这本书出自造词大本营 thoughtworks 的员工之手 , 里面有一个 plugin architecture , 就是有些人特别喜欢说的插件化架构:

Repo Pattern:DDD 理论认为我们业务项目的存储这一层是可能经常变化的 , 所以就专门存储层的 interface 设计单独拿出来 , 称为 Repo Pattern , 这东西实在没啥可说的 , find , getlist , save , 你只要有一点点 orm 经验 , 里面有啥接口应该自己都可以默写出来 。
事实是在 2021 年 , 我们的存储系统基本是不太可能做切换的了 , 即使切换 , 那些新兴的社区存储系统也会支持 MySQL 协议 , 基础设施想要侵入代码 , 那简单是大逆不道啊 。
领域事件:其实就是做上下游解耦的 kafka message , 我们用 domain event 显得会更洋气一些 。
领域服务:Domain service , 顾名思义 , 你认为是自己部门或者组内的局部 api gateway 也是可以的 。
综上 , 如果你是在大公司一线工作了两三年的程序员 , 上面这些东西应该马上就能理解 , 没有啥值得说的 。 如果是为了去架构师大会上秀一秀 , 你总得包装一下让自己显得没那么土吧?