苏眠月|DDD as Code:如何用代码诠释领域驱动设计?
阿导读: 相较于常规的MVC架构 , DDD更抽象、更难以理解 , 各个开发者对DDD的解释也不尽相同 。 那么哪种设计方式才更好?在学习时如何知道哪种DDD更正统 , 没有被别人带歪?本文尝试使用“DDD as Code”的概念 , 即 用DSL代码方式来描述DDD , 统一D DD的设计思想 , 通过案例详细介绍 如何基于ContextMapper来完成一个项目基于DDD DSL的表达, 并分享现实中DDD的设计流程和微服务的关系 。
网上有非常多关于DDD的文章 , 这当然是好事情 , 大家都想掌握好的设计方法来解决软件开发中的问题 。 但是这其中也存在一些问题 , 如果你随便打开网上的几篇DDD文章 , 虽然每一位作者都说自己是按照DDD思路进行架构设计的 , 但是细心的同学会发现每一个作者DDD文章中的结构描述、画的架构图都千差万别 , 你会非常奇怪 , 这些都是DDD设计吗?这里其实有一个问题 , 就是通过文字和图示描述一些抽象的概念时 , 本来就会有很大的差别 。 大家不要用盲人摸象的概念进行类比 , 这个不太合适 , 即便两个同学 , 对DDD都非常了解 , 而且都实践了好几年多个项目 , 他们写出来的东西还是不一样 。 我Java入行稍微早点 , 当然你说我年纪大保守也可以 , 记得当初没有那么多中间件 , 就是基于Struts 1.x这个MVC框架进行开发 , 不同的同学写出的设计文档也是千差万别 。 这么简单的MVC架构都能有不同的架构设计文档 , 而DDD相对更抽象、更难以理解 , 所以架构设计文档长的不太一样 , 这个也是可以理解的 。
【苏眠月|DDD as Code:如何用代码诠释领域驱动设计?】那么我们是不是要接受这个事实 , “各个作者对DDD的解释可以不必相同” , "DDD设计文档可以以不同种形式呈现"?如果是这样 , 那么想学习DDD的同学就有非常大的负担 , 哪种设计表现方式才是比较好的 , 才是比较容易理解的 , 同时我怎么知道我学的DDD是相对正统的 , 没有被别人带歪 。 我不是说发挥性思考不可以 , 但是从传道的角度来说 , 尊重理论事实还是需要的 。
我们都知道代码在表达一些业务或者逻辑时 , 非常能反应真实情况 , 即便是不同的开发者所编写 , 考虑到遵循Design Pattern、命名规范、开发语言约束等 , 代码大体上还是相同的 , 还是便于理解的 , 如果有单元测试和Code Review , 那就更好啦 。 这也是在一些文档不完善的时候 , 非常多同学选择阅读代码 , 更有同学说 , “直接看代码 , 不要看他们PPT和文档 , 会被误导的 , 不然怎么死的都不知道”。另外我们都知道 , 现在一个非常好的实践就是Everything as Code , 典型的如Infrastructure as Code的Terraform , Platform as code的Kubernetes YAML, Diagram as Code的PlantUML等等 ,那么我们能否使用DDD as Code这个概念 , 让我们的设计更统一些 , 更能方便表达设计思想 , 更容易被人理解 。
DDD DSL
用DSL也就是用代码方式来表达DDD , 这个很早就有了 , 但是更偏向DDD的战术设计(Tactic Design)和代码层面 , 如 Sculptor[1]和fuin.org DDD DSL[2], 大家普遍都认为 , 就是基于Xtext的DDD代码生成器 。 要费劲学习那么多 , 只为生成一些代码 , 而且只是Java代码 , 所以普遍关注度并没有多高 。
我们能否将DDD DSL除了代码生成这一部分 , 更偏向于战略设计(Strategic Design) , 突出设计的思想 , 那么DDD as Code就全面多了 。 接下来我们就介绍ContextMapper这个框架 。
名词解释一下:有不少同学对于DDD的战略设计(Strategic Design) 和战术(Tactic Design)之间区分有些疑惑 , DDD有专门的介绍 , 如下: