简单来说,本文会讲清楚我是如何使用DDD方法来进行供应链服务拆分的。

前言

本文尝试归纳整理作者前几个月负责的供应链项目中使用到的DDD战略设计方法,大概包含了以下部分:

  1. 理解问题
    1. 明确业务价值
    2. 分析业务需求
    3. 建立业务概念模型
  2. 识别限界上下文
    1. 业务边界
    2. 应用边界
  3. 领域建模
    1. 领域分析建模
    2. 领域设计建模
  4. 模型实现
    1. 微服务架构
    2. 应用集成、交互

其中架构层面,主要做了微服务拆分。

开始前简单对齐一下领域驱动设计的基本信息。

领域驱动设计简述

领域驱动设计,即DDD(Domain Driven Design)是一种软件设计方法,适用于复杂的业务建模场景。

简单概括DDD:通过领域建模的方式来落地软件设计过程以及结果。

那么如何进行领域建模?

我们可以拆解为两部分:

  1. 战略设计
    • 划分限界上下文:根据业务功能和职责,将整个业务系统划分为不同的限界上下文,明确每个限界上下文的边界和职责。
    • 确定上下文映射关系:分析不同限界上下文之间的关系,如共享内核、客户 - 供应商、遵奉者等关系,定义它们之间的交互方式和协作机制。
  2. 战术设计
    • 识别领域对象:从业务需求和流程中识别出实体、值对象、聚合等领域对象,并确定它们的属性和行为。
    • 设计领域模型:根据领域对象之间的关系,构建领域模型,包括实体之间的关联、聚合的组成、领域服务的定义等。
    • 实现领域逻辑:通过编写代码来实现领域模型中的业务逻辑,包括实体的状态变化、领域服务的具体操作等,同时使用仓储来处理数据的持久化和查询。

本文我们聚焦于理解问题、识别限界上下文这两步。

工具、方法论只是辅助工程师去解决问题、输出方案,核心、本质还是要理解业务。所以我们先看看业务背景。

业务背景

我们团队核心能力:

  1. 为上层业务提供智能设备实物;
  2. 设备管理能力(B端以及C端使用设备的能力);
  3. 售后交付服务;

24年之前,设备直接从供应商采购、交付,业务最简闭环流程:

24年开始,公司决定自研自营设备,业务最简闭环流程:

从图中可以看到,初期使用供应商现成的服务,生产制造、仓储对于平台是透明的。

业务开始自营后,供应链的预算、合同、采购、交付、仓储这些环节都需要自己负责,任何环节纯人工,成本巨大且低效。

同时,初期平台针对业务方侧已经建设了完善的销售、售后能力,24年亟需补充大后方的供应链能力。

从采买供应商服务到自营设备,团队职责与视角发生了巨大改变。

视角转变

职责上:增加了供应链的预算计划、生产采购、交付发货、仓储,每个环节都有巨大的效率提升空间。 视角上:自营供应链,需要自负盈亏、关注经营效率、品质。

业务上职责、视角变了,对应到系统上,关注的重点自然也就变了,规划与动作自然也得变。

职责变化

经过上面的梳理、分析,我们看看供应链ERP系统核心职责:

  1. 进(贝壳平台从供应商侧进货)
  2. 销(贝壳平台向上层业务方售卖设备、服务)
  3. 存(贝壳平台管理自研自营设备库存)(库存管理、供应链)

ERP业务核心是为贝壳IoT自研自营智能锁服务,将整个生产、进货、销售、售后、仓储流程数字化。 在之前采买供应商设备与服务的模式下,这些环节都是不需要我们负责的。

核心目标

经过上面的步步分析,我们明确一下供应链ERP的核心目标:

  1. 经营提效;
    1. 用更少的人、成本向上层提供服务
  2. 财务数字化:
    1. 快速算清账
    2. 系统化预算
    3. 系统化操盘
  3. 数字化沉淀业务规则;
    1. 流程运转
    2. 风控

ERP系统,核心是经营。领域名词都可以增加一个「经营」作为定语。 由于ERP业务处于客户视角的大后方,因此也可以增加「供应链」作为定语。

至此,我相信读者对业务背景心中有数了。

上面花了大量篇幅来说明业务背景,侧面说明业务背景其实是非常重要的。

磨刀不误砍柴工。

落地领域驱动战略设计

DDD的概念、学习成本、心智负担可以很大,也可以简化。我尝试简化了一版,对于战略设计,其实只需要三步:

  1. 建立统一语言;
  2. 分解问题域;
  3. 关联业务与系统;

落地的完整全景:

如何上手?我们继续逐步拆解。

理解业务问题

想要输出方案,首先第一步需要理解需求、问题。

我一般通过沟通的方式,从业务侧获取业务知识、信息。 沟通的时候,抓住几个关键要素即可:

  1. 资产

背后的本质就是:搞清楚谁负责什么事,什么是业务的核心指标

这一步,可以使用用户故事、用例分析、四色建模等方式操作,也可以使用一些通用的战略分析的工具,比如5W1H、PEST、SWOT、价值链分析。

使用什么工具、方法我认为都是次要的,核心是要找对人找对信息的口子。

这点可以参考:迅速熟悉一摊子事:顺藤摸瓜

用例分析

经过与业务同学的沟通,我根据获得的信息,梳理了供应链运作的核心流程,如下:

梳理核心概念模型

根据上述的核心用例流程,其实已经可以梳理出核心的概念模型、领域实体:

划分上下文

有了概念模型,我们就可以划分领域、梳理领域间的协作关系,进一步产出限界上下文,同时根据语义相关性、功能相关性将关联性较强的归到同一个上下文。

统一语言

关于这里的核心域、支持域,我个人认为不是绝对的,比如下方的客户域、供应商域,在不同阶段不同角色来看,重要性是会变化的。

因此这种划分为核心域是合理的(没有这块业务无法运转),划分为支撑域也是合理的(相比交易结算来说,对业务的成败影响没那么大)。

根据子域初步划分限界上下文

核心的上下文就这几个:

梳理上下文协作关系

同样使用用例分析的方法,可以梳理评估一下上下文间的协作关系,进而产出中间层的上下文。

上下文本质表达的是业务的范围边界,同时也能作为技术上工程服务划分的重要依据。当中间层的职责变大、业务变重之后,就可以考虑将中间层上下文独立出去。

目前我们的供应链处于起步阶段,中间层业务并不复杂庞大,因此可以将中间层的业务维护在主上下文中。

明确核心领域模型

经过上面的逐步分析,终于可以把核心的领域模型给敲定了:

确定工程架构

经过上面的一系列过程,我们明确了核心的领域模型,并且划分了限界上下文。

到此,我们可以根据领域模型、上下文创建对应的代码工程了,结构如下:

这里部署只申请了两个工程资源,原因是目前还不清楚后续业务体量、复杂度会变得多大,因此暂时使用两个工程+子模块的方式进行代码工程架构拆分。同工程内的子模块间使用RPC子模块进行防腐交互,也为后续拆分预留了口子。

总结

本文主要使用文字+图例的方式介绍了我24年投入较多精力的供应链项目,包含了整体设计以及使用DDD 划分服务边界拆分服务的部分。

文中尽量屏蔽DDD 的复杂性,尽量让读者专注于业务的理解、整体的建模、拆分思路。

最后小结一下,使用DDD 方法论建模、拆分服务,我们经历了以下核心过程:

  1. 理解业务问题
  2. 划分上下文
  3. 明确核心领域模型
  4. 最后基于模型与上下文定义工程架构

其中最为重要的,我个人认为是要对业务背景理解透彻,要抓住一切能用的方式接收足够的业务信息。 其次才是使用工具、方法去解决问题。

以上,欢迎讨论。