作者简介
小白龙,携程资深后端开发工程师,关注架构落地、研发效能领域。
随着历史业务不断迭代和业务场景越来越复杂,携程用车、租车(简称两车)面临历史技术债和系统复杂度越来越高带来的理解、维护、迭代困难等问题,我们开始寻求如何更有效的降低复杂度和提升效率的方法。
本文描述了两车如何利用DDD(Domain-driven Design,领域驱动设计)方法论降低系统复杂度以及在重构历史系统中的取舍和思考。对于复杂业务场景下的领域驱动设计具有借鉴意义。
一、案例介绍
携程用车订单相关业务包括接送机、包车、打车这些产线,订单相关的功能包括订单状态管理、支付状态管理、供应商订单状态管理、履约状态管理,其中履约状态中包含司机相关状态,完成订单需要将额外费用结清。
携程租车订单相关功能包括订单状态管理、支付状态管理、押金扣款记录、供应商订单状态管理、履约状态管理,其中履约状态主要是取车和还车相关状态。
订单和相关实体如下图所示:
二、问题分析
由于两车业务存在一些差异,为了读者更容易理解,因此将抽取共性问题来说明。
2.1 沟通困难
关于沟通困难,我们发现整个开发过程中,沟通实际上是一个非常消耗时间的事情,需求方需要和产品沟通,产品要和研发人员沟通,研发开发过程中发现一些忽略的细节需要产品确认,来回之间耗费了大量时间。如果是跨团队沟通,这样的问题会更加复杂,以下总结了一些常见的场景:
产品不关心研发的实现,但是觉得需求很简单或者很复杂。
研发开发过程中发现一些忽略的细节需要产品确认,产品要找需求方确认。
历史逻辑没人知道,需求评审的时候无法发现问题,做到最后发现有问题。
跨团队之间不了解对方的业务,需要反复沟通确认。
遇到同一个名词不同的理解导致无效沟通。
一个需求到底该哪个域来实现是我们在实践中经常反复探讨的问题。
...
例如订单和供应商订单在不同的团队内都叫订单,在沟通中针对“订单”的讨论就会产生歧义。
2.2 业务边界不清晰
设计之初,订单被各调用方当作了对外输出的数据源头,数据需求方只要调订单详情即可获取全量数据,这为以后订单的迭代带来了相当大的隐患。订单在自己的业务模型中加入大量不涉及自身业务的冗余字段,在系统的演进过程中,由于无脑插入他方业务字段使得订单自己也要维护相关的逻辑(解释和修改),导致各方对订单的耦合日益加深,导致订单服务的发布变成高风险行为,甚至一个无关订单业务的相关字段修改也可能导致系统故障。
例如订单上关于供应商的相关数据,用户订单有一份,采购订单也有一份,当采购要修改供应商的相关逻辑时要用户订单也一起修改,而用户订单必须排查和推动相关使用到这个字段的业务方切换替代方案。