适用项目:线上商品的销售与运营平台
复习状态:未复习
领域驱动设计 DDD 是一种以业务领域为核心的软件设计方法,它强调将复杂的业务规则封装在领域模型中,通过清晰的层次划分、聚合设计和事件驱动协作,让代码结构更贴近业务逻辑。与传统的贫血模型不同,DDD 把业务逻辑从 Service 层搬回到领域模型中,使系统在面对频繁变化的促销规则、订单流程和会员权益时,能够以较小的改动范围完成需求迭代。线上商品的销售与运营平台涉及商品上下架、库存扣减、订单交易、优惠券核销、支付回调和积分累计等多个业务场景,各场景的规则差异大且互相影响。因此,在本项目中,我采用领域驱动设计方法,围绕分层架构、聚合设计和领域事件三个方面重构核心交易链路。
首先,我从 DDD 分层架构入手,明确了各层的职责和依赖关系。标准的 DDD 分层架构包括接口层、应用层、领域层和基础设施层,领域层是核心,不依赖任何外部框架。在本项目中,我在接口层通过 Controller 接收用户请求和参数校验,不包含任何业务逻辑;在应用层通过 ApplicationService 编排业务用例,例如下单服务依次调用商品校验、库存锁定、订单创建和优惠券核销,但不处理具体业务规则;在领域层将订单状态流转、金额计算、库存扣减和优惠券核销规则封装在各自的聚合和领域服务中;在基础设施层通过 Repository 接口的实现类完成 MySQL、Redis 和消息队列等外部资源的访问。依赖方向严格为上层依赖下层,领域层不直接引用 MyBatis 或 Redis 客户端。通过分层架构,业务逻辑和技术实现完全解耦,当支付渠道从直连改为第三方网关时,只需修改基础设施层的支付适配器,领域层和应用层代码无需变动,支付模块切换用时由预估的 4 天缩短到 1.5 天。
其次,我从聚合设计入手,保证核心业务规则的内聚和一致性。聚合是 DDD 中最核心的战术模式,它将一组关联对象封装在一起,由聚合根统一控制访问入口和业务不变条件,保证聚合内部数据在任何时候都不会违反业务规则。在本项目中,我将订单设计为聚合根,内部包含订单明细实体和收货地址值对象,所有对订单明细的修改都必须经过订单聚合根,从而保证订单实付金额与明细自动同步、订单取消时所有明细同时取消。库存记录设计为聚合根,锁定库存和释放库存的操作通过库存聚合根完成,确保可售库存与锁定库存之和等于总库存这一不变条件。优惠券设计为聚合根,优惠券的领取、使用和核销三个操作均由优惠券聚合根控制,防止同一张优惠券被重复核销或被过期使用。通过聚合设计,核心交易域识别出 16 个聚合,订单金额计算错误和库存超卖问题在开发阶段就减少了约 70%,订单聚合内部修改只影响自身,不再波及库存和营销模块。
最后,我从领域事件入手,实现不同聚合之间的解耦协作。领域事件是聚合内发生的有业务含义的事实,通过发布和订阅领域事件,各聚合可以异步响应彼此的变化,而不需要直接调用。在本项目中,我在订单聚合中定义了订单已支付、订单已取消和订单已退款三个关键领域事件。当订单已支付事件发布后,库存聚合订阅该事件完成从锁定库存到已售库存的真实转换,营销聚合订阅后完成优惠券的最终核销并更新优惠券使用记录,会员聚合订阅后累计用户消费积分,数据分析聚合订阅后记录交易明细供后续报表使用。当订单超时取消时,订单已取消事件触发库存聚合自动释放锁定库存、营销聚合恢复优惠券为可用状态。领域事件通过消息队列异步投递,各订阅方独立处理,互不阻塞。通过领域事件机制,订单与下游模块的耦合从同步 RPC 调用转为异步订阅,核心交易链路中新增一个下游消费方只需增加事件订阅者而不改动订单代码,跨模块功能扩展的联调时间减少了 50% 以上。