如何将DDD实践反思转化为?

摘要:某大型互联网公司于2019年开始在XX中台财务域进行DDD实践。事后回顾,整体并没有达到预期的效果,个人也做了很多的反思和总结,形成此文。 1. 背景 为什么当时要实践DDD?其中的缘由比较复杂,可以从外部和内部两个视角来看。 首先,从外部
某大型互联网公司于2019年开始在XX中台财务域进行DDD实践。事后回顾,整体并没有达到预期的效果,个人也做了很多的反思和总结,形成此文。 1. 背景 为什么当时要实践DDD?其中的缘由比较复杂,可以从外部和内部两个视角来看。 首先,从外部也即整个BU的视角来看,最先开始实践DDD的是A域,并在该域诞生了一套在公司现有RPC框架之上的业务SPI框架(以下简称为【N框架】)。相较于dubbo这样纯技术的服务框架,它有以下特点: 标榜serverless,自身提供了代码托管和运行容器,可以直接进行服务的开发、部署及运维,也可以将现有docker应用的服务以SPI的形式注册到这个框架上并发布,实现“服务市场”的效果 可以进行服务的热插拔,不停机升级回滚不同版本的服务 业务SPI管控,可以将SPI按照业务域划分到不同的路径下,方便管理和业务发现、服务编排 在BU内部推行N框架时,对于现有的应用,需要将核心服务用SPI的方式注册上去;对于新接入的业务,则推荐使用serverless形式的bundle提供服务。对于哪些是“核心服务”,这些“核心服务”是否足够标准化,亟待一轮梳理甚至重构。 其次,从本域来看,在组织架构调整后,线上同时运行的多套系统已经日渐成为瓶颈。由于历史原因,XX中台财务域对接多个业务域时,往往会新搭一套系统,造成了当时一共有五套财务系统运行在线上,系统间相互依赖,系统内又有大量的if...else硬编码来处理定制化的需求。在这种情况下,无论对于新业务、新需求的支持,还是对于现有业务的运维,都需要付出巨大的人力成本,并且存在着很多隐患,多版本归一化迫在眉睫。 因为供应商发票在整个财务域的最下游,相对比较独立,并且对于现有的系统业务方也有开票流程线上化的诉求(原先的流程存在大量的人工步骤:是将对账单导出为excel,导入到开票系统,然后再将开票结果数据导回系统),所以选定了供应商发票这个子域作为第一个试点,目标是新建一套销项发票系统,发布可扩展的SPI,并将已有的业务线流量逐步切过来,降低运维成本,提高研发效率。 2. 实践 2.1 布道 对于DDD,其中有很多的概念和方法,需要所有开发认知达成一致,这里就不重复那些经典的概念了。 这里想稍微聊一下”六边形架构“。为什么是六边形,不是正方形、五边形、八边形?我思考了很久,得出的结论是:六边形比较好看,而且也好画。具体这六个边除了表示边界,并没有什么实际的含义,比如六大金刚什么的。使用”六边形架构“,一是为了和传统的分层结构进行区分,二是为了表示这个系统不是孤立的,而是在一个大网格中的一个节点。 对于实体,最初我的理解是现实中存在的对象,在DDD里则被定义为”有标识符来区分的对象“。从哲学的角度,则是”是客观存在并可相互区别的事物“。这样理解思路就开阔多了, ”订单“是实体,”抽奖活动“也可以抽象为实体[1]。 需要注意的是,一定要遵守现有的或形成一套统一的命名规范。比如DO,一般指的是DataObject,但是DomainObject也能缩写成DO,是不是很神奇? 2.2 建模 首先使用用例分析法,分析现有系统+短期未来中需求的用例。“发票”这一实体在现实世界中相对固定,所以建模相对比较简单——实际上并不完全正确,并且这种思维定式为后续的建模和开发带来了隐患。在子域划分中可以看到,不仅仅只有一个发票实体。 但是仅通过用例分析,又显得比较单薄——甚至很多业务场景都能套进这个模板中,因此需要在后续的环节(分析流程中缺失的实体)中丰富一些细节进来。 至于当时为什么没有考虑四色分析法和事件风暴法,事后回想这个问题,可能原因是:老系统的代码和场景比较复杂,新系统可以按业务线维度做进行迁移的时候再进行扩展,第一版不需要考虑大而全的所有场景,因此只需要梳理好SOP即可。而四色分析法,事件风暴法对于老系统的分析成本过高,即使将所有开发集中到一起也难以将所有事件罗列出来。 建模的结果简单表示如下: 各域职责如下: 费用域:对接上游不同形式的单据,统一转化成可以用来开票的账款单 开票申请域:抽象开票的过程信息,包括发票待填充字段和单据拆分规则 开票执行域:对接不同的开票ISV,提供统一的开票能力。 把发票域再划分成更细的子域,是出于以下考虑: 限界上下文更清晰,一个聚合根就是一个子域 将高内聚低耦合、单一职责原则极致化,外部应用可以自由选择调用哪个子域的服务,从而决定自己的应用边界 后续团队的扩张,更加专人专职,在需求迭代时降低并发度,避免十几个人同时修改一个系统的局面 2.3 编码 按照应用边界划分以后,按子域分别建立应用、申请主机实例、DB资源等。
阅读全文