写点什么

DDD 实战 (3):从需求到代码实现生鲜电商系统

作者:深清秋
  • 2022 年 3 月 06 日
  • 本文字数:12700 字

    阅读完需:约 42 分钟

DDD实战(3):从需求到代码实现生鲜电商系统

从今天开始,我就要进入“群买菜”系统真正的 DDD 设计和实现过程了。这里面会涉及到一些 DDD 相关的概念和理论,但更多的是设计和代码实践。


正如第一篇“缘起”中提到的,本专题将尽可能的将理论知识进行浓缩和简化、糅合到实际的设计文档和代码实现中去表达。


DDD 本质上是个“软件设计”方法论,它指导的是“怎么做软件设计”。故在正式开始“群买菜”的软件设计之前,我们先对 DDD 整体方法论(这里主要是张逸老师的 DDDUP)做一个简单的、从我个人角度理解的介绍。


本篇在对 DDD 整体工作框架做了个简要的介绍后,我会在本篇中完成 DDD 工作框架中的第一步——“群买菜”系统的全局分析。


DDD 整体工作框架


在我个人的理解中,DDD 工作框架其实就只有两个部分:对“问题空间”的分析和描述、以及通过一系列方法实现的“解空间”的映射。 “问题空间”其实就是在目标软件系统上线前、当下的现实业务世界,“解空间”就是目标软件系统的设计方案和代码实现。

“问题空间”分析:全局分析


对“问题空间”进行分析和描述,就是“问题空间”的所有工作内容。它指的是要搞明白我们的软件“到底要解决什么问题、以及满足什么业务需求”——说得更直白一点,就是传统上大家理解的“业务需求分析”。不过,我们在 DDDUP 方法体系里,不叫“需求分析”而叫“全局分析”。


首先,我们需要了解 DDD 中反复提到的“业务领域”和“业务子领域”的概念,并将“业务子域”区分出 3 个类别:核心子域、通用子域、支撑子域


  • 所谓的“业务领域”,指的就是“业务领域模型”。因为 DDD 是“领域驱动设计”,所以“业务领域模型”是 DDD 的核心概念来源。而”业务领域“就是所开发软件系统需要对应的现实世界的某个“业务范畴”,比如:电商、物流、通信、交通、医疗、教育等等。


  • 在“业务领域”下,我们可以将其业务内容分为多个“子领域”,比如:“电商”业务领域下,有“客户”、“商品”、“库存”等等多个子领域。


  • 需要注意的是:“业务子领域”的划分其实是不考虑将来软件系统会怎么建设的,而更多是考虑现实业务中需要怎么区分这些业务单元。当然,有可能系统实际实现后,系统的模块也会有跟“业务子领域”一样的划分——但这只是“系统同构化映射现实业务”,并不是系统模块划分在影响业务单元划分。也就是说:“业务子领域”划分是“因”“软件模块”划分是果。甚至有可能根据实际项目的现实条件,软件系统并没有按照“业务子领域”进行分块。比如:重用一个既有的整体的 SAP ERP 系统来实现“采购”、“库存”、“财务”多个“业务子域”的支撑。


  • “业务子领域”按照如下的识别规则划分为 3 类:核心子域、通用子域、支撑子域。


  • “通用子域”就是那些无论在哪个行业、哪个业务领域下都可以通用的“业务子域”,比如:角色权限、组织管理、员工、IM 即时消息等等。这些“通用子域”所对应的软件实现,很多时候是可以直接在市面上采购成熟产品来实现的,不见得非要本项目的软件团队来实现。


  • “支撑子域”是那些虽然有本行业、本业务领域下特定的业务知识,但并不是本业务领域下最核心的业务单元。比如:“电商”业务领域下的“库存”、“物流”、“财务”就不是核心业务单元,而只是支撑“订单”、“客户”等核心业务单元的、后台人员所使用的与直接客户无关的业务单元。


  • “核心子域”就是那些体现本“业务领域”最核心业务价值的业务单元。当然,这其实是个“相对概念”,是在特定语境下才有效的说法。比如:在“电商”业务领域中,“物流”就是个“支撑子域”;但在“快递”业务领域中,“物流”就是个“核心子域”。


其次我们大致了解下 DDDUP 对“全局分析”要求的工作内容(这里您不必全部记住,只是大致浏览即可。我在本节的“群买菜”全局分析中会给您演示怎么做):


  • 价值需求分析——对目标软件系统的价值需求进行调研总结;


  • 核心业务流程分析——对目标软件系统将要覆盖的、体现最为“核心商业价值”的业务主流程进行调研分析,画出流程图;


  • 业务场景识别——识别出按照时间轴的跨度,业务主流程有哪些在时间线上“断裂”的业务场景;


  • 业务流程分析——对每个业务场景下的业务流程进行识别,并用跨角色的泳道图、业务服务蓝图、事件风暴图等工具(如果您不明白这些工具是啥,暂时不管它)表达出各场景下的、各情况的业务流程;


  • 业务用例识别——在泳道图、业务服务蓝图、事件风暴图等工具表达的业务流程基础上,识别出系统将要满足的“业务用例”。没错,就是 UML 的那个“业务用例”;


  • 编制业务用例规格书——就是每个业务用例给一个需求规格书(按照规定的模板格式)描述文档;


“解空间”映射:战略设计+战术设计+代码实现


首先,我们同样需要了解 DDD 中提到的关于设计的最重要几个概念:


  • 战略设计层面的 2 个重要概念:限界上下文、上下文映射


  • 限界上下文就是目标系统内部最粗粒度的模块划分,这个粒度的模块划分往往是后续“微服务”怎么切分的主要依据。


这种限界上下文的划分,最理想的情况就是一个“业务子域”对应一个“限界上下文”(所谓“同构映射”)。但在实际软件系统设计中,可能因为“第三方伴生系统”、“遗留系统”等情况的存在,而不得不出现“错配”的情况,就如下图所示——也就是说:只有所有“业务子域”对应的业务逻辑都全部由目标软件系统“全新实现”才可能出现“最理想情况”。


  • 限界上下文映射就是搞清楚这些“限界上下文”模块之间是怎样的协作关系(调用关系、事件通知关系等等)。


“限界上下文”的划分,最重要的就是追求的“高内聚、低耦合”。而这其实是个“无止境”的追求,并且不同的架构设计师、其经验和对业务的理解不同,自然设计成果也不会完全相同,所以严格来说这是一种“很艺术化”的设计成果。


但无论怎样,DDD 战略设计中有一系列的方法和原则来帮助达到您尽可能地达到“高内聚、低耦合”的设计效果,我们会在后面的实例演示中逐步看到。


  • 战术设计层面的 4 个重要概念:实体对象、值对象、聚合、领域服务


  • 实体对象是对象模型中最主要的类,需要数据生命周期管理的、根据 ID 标识而不是属性来判断是否同一个对象的类。如:订单、订单行等。


  • 值对象是不需要数据生命周期管理的(它们往往用来描述实体对象的属性)、只要其对象内的属性取值发生变化该对象就被认为是另一个对象。如:地理区域(含省市区)、家庭住址(含经纬度定位和详细地址)、身份证号(含编码规则)、姓名(含姓+名)等。


  • 聚合和聚合根。在实体对象中,有些实体对象是不需要单独出现的、总是跟着另一个实体对象的出现而出现、消亡而消亡的,如:”订单行”总是随着“订单”的出现而出现、消亡而消亡。往往,我们在完成“对象模型和关系识别”后,列出了很多实体对象,这些对象可按照它们之间的“绑定存亡关系”进行分组,分组后有一个实体对象是唯一的访问入口。这种分组就叫“聚合”,而那个作为唯一的访问入口的实体对象就是“聚合根”——一般情况下,给“聚合”的命名就是“聚合根”对象的名称,如:“订单”聚合可能就包含了“订单”、“子订单”、“订单行”、“商品快照”等多个对象(后面的对象都不需要单独出现)。需要说明的是:值对象是“附庸”在实体对象上出现的。


  • 领域服务。实体对象、值对象都是有行为的(也就是方法逻辑),很多业务逻辑就直接在这两类对象中实现了。那么,有了“聚合”就可以将很多业务逻辑在“聚合”内部的各个实体对象、以及伴随的值对象中方法逻辑中实现。但是,仍然有一些不能明确划分到单个聚合”职责“中去实现的业务逻辑,而这些逻辑就需要在“领域服务”中去实现。比如:“为客户取消订单”这一业务逻辑到底应该是由“客户”聚合中实现呢?还是在“订单”聚合中实现?显然,无论放在“客户”还是“订单”聚合中,都是不合适的,所以就有了“取消客户订单”这一领域服务存在的必要性。


其次,我们在了解 DDD 战略、战术设计的几个重要概念后,就可以来看看战略设计、战术设计分别包含什么工作内容:


  • 战略设计主要完成如下 3 方面工作:


  • 系统上下文定义——将目标系统与伴生系统进行职责分工。


  • 限界上下文识别及其对应的上下文映射


  • 战略层面的技术决策——主要包括:1)“系统整体”角度的软件分层(区分边缘层、业务价值层、基础层);2)系统整体角度的架构性决策:微服务的划分、事务一致性策略(全局一致性 vs 最终一致性)、数据库架构(单体数据库 vs 分布式数据库);3)必要的各限界上下文的技术栈选择(开发语言、技术组件、使用规则引擎考量、使用 CQRS/命令总线考量、事件消息机制等);


  • 战术设计主要完成 4 方面工作:


  • 对象模型的概念分析——识别出有多少实体对象、值对象。


  • 聚合设计——将实体对象进行聚合分组,选出每个聚合的“聚合根”。


  • 服务设计——设计出“领域服务”,并在“领域服务”的基础上设计“应用服务”。这两者的区别,以及如何设计在后面的实例中会介绍。


  • 战术层面的技术决策——包括但不限于:如何在前端界面和后端服务之间传输数据(VO: view object)、以及微服务远程服务调用时如何传输数据(DTO:data transfer object)、使用开发语言的哪个持久化框架实现数据持久保存(如 JPA/Mybatis 等)、如何实现资源库端口等。


好了,我们已经对 DDD 整体的工作框架做了一个特别简短的介绍,下面完成本篇文章的正题——群买菜全局分析。

“群买菜”系统全局分析

业务背景和价值需求分析


说实在的,我写这款“群买菜”小程序,是发现很多生鲜店老板或团长在使用“群接龙”这款小程序。而实际上“群接龙”并不能很好的满足生鲜行业的一些特定行业特性——如:活鲜类商品的多退少补等。


所以,“群接龙”其实是一款给生鲜社区店或社区团长提供的,允许消费者在线下单、接龙以及店主或团长进行后台店铺、商品、订单等管理的小程序。描述一个软件产品商业价值的最好方式是“商业模式画布”,下图就是“群买菜”小程序的商业模式画布:

通过该“商业模式画布”,我们能够看出我们开发“群买菜”小程序,其主要的用户就两类:消费者(生鲜客户)、商家(生鲜店老板、或社区团长),主要商业价值是通过满足“消费者”和“商家”之间的“在线交易”来实现的。所以,“群买菜”系统涉及到的利益干系人(stake holder)包括 3 个:

  • 消费者(生鲜客户)

  • 商家(生鲜店老板、或社区团长)

  • 平台运营方(群买菜软件的提供方、运营方)


基于这 3 个利益干系人,我们分析各方的“利益诉求”,得出如下的“价值需求规格书”:


产品需求输入和统一语言

首先,我们来看看“群买菜”系统的需求输入——产品原型设计。


在 DDD 社群中,大家争论和激烈的一个话题就是:“产品经理”在 DDD 设计中到底起到什么作用,还需要“产品经理”这个角色存在吗?


这里我分享下我个人的观点:DDD 作为软件设计方法,解决的是“工程性问题”;而产品经理作为产品直接负责人,是要从商业利益、用户心理、公司资源等多个方面进行综合考虑的,他在产品设计中所完成的“原型设计”作为产品设计中最重要的成果之一,是在将关于“非工程性问题”的思考结果表达出来。


所以,我在这里秉承的观点是:产品经理输出的产品设计,作为 DDD 全局分析的输入,而不是用 DDD 全局分析代替产品经理的工作。否则,这在公司“商业职责”的定位上就很不清晰了。


于是,我这里“群买菜”系统的“全局分析”是在“群买菜”产品原型设计的基础上进行的。“群买菜”产品原型的部分设计截图如下:

由于产品原型界面很多,这里就不一一介绍了,有兴趣的您可以到这里去在线浏览:《群买菜产品原型设计》


接下来,在开始后面的分析设计之前,我们需要完成 DDD 设计方法论中特别重要的一步工作:制定统一语言(UL)。我个人的理解,所谓“统一语言”其实就是一个“术语表”。在大型项目中这样的“术语表”特别重要,一种比较务实的做法是:不要为所有“业务子域”制定一个“大而全”的术语表,而制定“分业务子域”的术语表(即统一语言)。鉴于“群买菜”并不是一个“真正的大工程”,我这里只为“群买菜”系统给出一个集中的术语表。同样限于文章篇幅,我截图部分术语表如下图:

如果您对完整的“群买菜统一语言”(即术语表)感兴趣,可访问在线页面《“群买菜”统一语言》

核心业务流程和业务场景


有了价值需求分析、产品需求输入、以及“统一语言”定义,我们就可以开始基于业务的核心流程(也就是软件要实现的“最核心价值流程”)对业务场景进行划分、并对每个场景下的业务流程进行细化设计,进而完成两个最重要的工作:业务用例识别(也叫“业务服务”,是后续”应用服务“、“领域服务”设计的最主要基础)、业务子域识别与分类。


根据“群买菜”的价值需求分析,我们知道“群买菜”最核心的业务目的就是:满足“社区生鲜”这一“业务领域”下,“客户”和“商家”的在线交易和接龙活动。为此,我们设计出”群买菜“的核心业务流程如下图:


在进行后续的业务流程具体分析之前,我们需要将“问题空间”进行“简化”,也就是常用的“化整为零”。一般来说,对业务流程来说“化整为零”的第一步是进行“业务场景切分”——也就是按照时间轴、把时间上可以“断裂”开来的流程进行切分。就我们“群买菜”系统来说,从“时间轴”上可以“断裂”的业务场景分析如下:


  • 商家建立店铺。商家在线销售商品之前,需要先在系统中建立店铺,并设置店铺的相关营业属性(营业时间、是否送货上门等)。这个操作,对于商家来说,可能只需要几分钟的时间。


  • 商家建立和维护商品库。商家建立店铺后,系统并不会要求立即建立商品库,所以建立商品库和店铺是可以在“时间上断裂”的。


  • 客户在线浏览和下单。一般来说,客户只有在商家商品库后,才有可能在店铺浏览商品和下单。但显然,并没有一个业务规则要求“客户浏览和下单”必须和“商家建立店铺、商家建立商品库”在时间上是连续操作的。事实上,商家可能只需要建立一次店铺、建立一次商品库,但客户可以发生无数次在线浏览和下单。


  • 在线接龙活动。按照产品需求设计,系统还需要支持商家发起的在线接龙活动。在线接龙和在线销售的区别是:在线销售是一次建立商品库、但发生无数次销售;而接龙活动是在商家每次建立后、客户只能参加一次接龙。所以,商家建立接龙活动、到客户参加接龙活动在“时间轴”上是连续的。


  • 商家结算营业收入。商家可以定期进行营业收入结算,只要客户在系统上确认了收货(或者系统超时自动收货),则商家就可以将资金提现到自己的账户下。这其中,可能涉及到系统平台运营方与商家之间的手续费结算。这一营业收入结算过程,从时间轴上来说,也是一个独立的业务场景。


  • 商家加盟品牌。在产品原型设计中,我们可以看出产品经理还希望系统能够支持商家店铺之间的“轻加盟”模式,以实现店铺的“轻连锁”或实际的“加盟分销”。这种“轻加盟”模式,就是建立店铺和店铺之间的“品牌关联”关系,使得加盟某店铺的新店铺,可以销售被加盟店铺(称为“品牌店铺”)的所有已上架商品。从时间轴角度来说,显然作为品牌店铺设置加盟政策、以及选择哪些品牌店铺进行加盟,这是另一个”时间断裂“的独立业务场景。


根据如上的分析,再结合上述 6 个业务场景之间的逻辑关系,我们画出如下的主体业务流程图:


各场景下的业务流程(泳道图)

上面的 6 个业务场景,我们是可以针对每个场景给出业务流程的。分别设计如下:

  • 建立店铺。业务流程如下图:

  • 加盟品牌。业务流程如下图:

  • 建立维护商品库。业务流程如下图:

  • 在线销售。业务流程如下图:


  • 在线接龙。业务流程如下图:


  • 资金结算。业务流程如下图:


该流程中,需要特别说明的是:


  1. 客户下单后支付的资金,是进入平台账户的。只有在客户确认订单收货、或系统超时自动确认收货(目前为 48 小时,要求系统可配置)后,才转入商家账户。在转入商家账户之前,系统会按笔自动扣除服务费(目前按千分之六比例,要求系统可配置)。

  2. 加盟商佣金的结算,也是类似的逻辑,只有在订单被确认后才进行。

  3. 账户提现流程中,并不是商家一发起系统就立即同步完成提现,而是考虑到常规的金融操作逻辑,一般采用 T+n 模式。目前 n 为 0(也就是当天提现,一般为几分钟内到账,视系统性能而定),并且不排除将来根据商户等级、商户分类等支持 n 为 1~7 之间的分级模式。因此,商户发起提现到后台完成提现是分开两步完成的。

  4. 账户充值,主要是考虑可能商家账户余额为零,但商家又开通了订单短信提醒这类收费服务。为了让收费服务能够正常使用,商家是需要自行充值的。

服务蓝图和业务用例


在完成了业务场景和流程的设计之后(这两个工作应该是架构设计师或需求分析师的基础技能),就可以开始业务用例的识别的。个人以为,业务用例的识别使用“服务蓝图”是个很好的主意。因为服务蓝图按 3 个分割线:交互分割线、可见性分割线、内部可见性分割线(详情参见后面的实例介绍),将满足用户需求的整个过程从“前台服务”、“后台服务”、“后台支持”3 个角度进行了梳理,这将会是“最全面”的流程分析视角,能够保证不遗漏一些重要的“业务用例”。


鉴于“群买菜”系统的 6 个业务场景全部画“服务蓝图”、完成“业务用例识别”(其实是画“业务用例图”)的篇幅较大(在我的设计文档中,这部分占了 25 页篇幅),这里我就不一一展示分析过程,而只是就一个关键业务场景“在线销售”进行了解读,并将所有场景下的“业务用例图”给出来。


基于上一小节中“在线销售”的业务流程图,我画出如下的“在线销售服务蓝图”:

以该“服务蓝图”为样板,我稍微介绍下“服务蓝图”的相关概念和设计方法:


  • 交互分割线。交互分割线一般用于客户(可能是机器人)和一线服务人员(也有可能是机器人)之间的一个边界线。在“交互性分割线”之后的操作,我们一般称之为“前台”操作。对于有真人作为一线服务人员的情况来说(比如:营业员、柜员、客服坐席等),交互分割线就分割了用户和一线服务人员之间的“交互边界”(如:提出要求、交身份证、回答提问等等),前台操作是由营业员等完成的;对于客户通过网站或 app 自助进行服务的情况下,大部分情况下,前台的操作是由客户自行完成的,这时候前台操作就认为不存在。


  • 可见性分割线。可见性分割线一般是前台操作人员和后台服务人员之间的分割线。在“可见性分割线”之后,往往是后台服务人员(如:审核人员、财务人员等)。对于有真人作为一线服务人员的情况来说,可见性分割线就是客户看到一线服务人员在操作的内容(比如:看到营业员在操作电脑、收款等);对于客户通过网站或 app 自助进行服务的情况下,大部分情况下,前台的操作是由客户自行完成的,这时候会使得“交互分割线”和“可见性分割线”变成一条线。


  • 内部交互分割线。在“可见性分割线”之后的是“后台服务性工作”,而在“内部交互分割线”后面的是“后台支撑性工作”。一般来说,“后台支撑”并不对客户服务产生直接的影响,而是“提前”或“滞后”影响的,如:电商业务中维护商品库、每日盘点库存等。


下面我对“群买菜”在线销售“服务蓝图”的一些内容做特别说明如下:


  1. 前台操作中,除了客户自助完成的“商品浏览”、“在线下单”和“确认订单完成”外,其实是“商家”一线服务人员给“客户”的服务内容。在“群买菜”小程序为客户提供自助浏览商品和下单的基础上,其实“商家”一线服务人员能干的工作,就只有:在微信群分享或私聊“发送小程序店铺(或商品)链接给客户”、为客户备货后的“多退少补”、以及客户要求退货时的“退货退款”。

  2. 后台服务性操作中,一部分由伴生系统“微信支付平台”完成:创建预支付、完成支付转账、触发群买菜服务器生效订单;一部分由商家人工完成:备货、发货。

  3. 后台支撑性操作中,商家人工操作的,只有“维护商品库”;而“超时自动取消订单”、“超时自动完成订单”是电商系统的常规性操作,都是系统机器人自动完成。


而关于“每天自动恢复上架商品有货”我们需要特别解释下:这是一种简化的“库存盘点”机制——考虑到“生鲜”类商品,大部分是每日进货的,而系统并不打算支撑完整的“库存管理”(为了确保在线库存量的准确,在生鲜行业这是一个极其复杂的过程,需要每天进货后对所有货物的实际斤两进行准确盘点,并在每次线下销售后对售出斤两在系统中“进行准确扣减”,而对于“个体生鲜店”来说,人工投入少,这是不现实的),所以就采用了简单的方案:一旦商家备货时发现商品库存不足、就主动给客户退款并标注商品“售罄”。但问题又来了:如果店里有 200 个 SKU,每天售罄约 60%就是 120 个 SKU,在次日开业前如果让商家对这些已售罄的 SKU 手动标注为“有货”,就是个很繁琐的操作——为此,我们开发了一个系统机器人执行的“每天自动恢复上架商品有货”功能。


有了上图的“服务蓝图”,我们就能对“在线销售”场景识别出如下的业务用例图:




需要注意的是:这里的“用户管理”、“客户进店”、“客户购买”等用例分组,并不是严格意义的系统模块分组,这里只是为了理解方便而暂时做的分组。


在该业务用例图中,我对某些业务用例的特殊考虑,说明如下:


  1. 服务蓝图“客户下单”环节用到的商品管理相关业务用例说明:

  • “维护商品库”就是由“建立商品库”场景中相应的“商品管理”模块的业务用例来满足需求的;

  • 每天自动恢复上架商品有货。这个业务用例,前面已经说过了,不再赘述。


2. “客户进店”用例分组中,有 4 个业务用例需特别说明:


  • 分享店铺或商品到微信。这里我们根据产品经理提供的 UI 设计要求,系统是允许商家的授权操作人分享整个店铺、或单个商品页面两种方式到微信群或私聊的。


  • 系统自动定位店铺。有些情况下,客户可能是直接通过在微信平台搜索群买菜小程序进入系统的,这种情况下系统将自动根据客户的最近浏览历史、当前手机定位、店铺创建历史等信息,来为其推荐最合适的店铺来打开群买菜小程序。


  • 搜索店铺。与上一个用例相对应的,由于系统默认打开的店铺可能不是客户想要看的店铺,故系统支持客户自行搜索店铺。搜索结果将以列表方式显示给客户,供客户选择。


  • 查看店铺详情。客户也可以通过点击当前页面上显示的店铺进入查看店铺的详情情况,包括店铺门头图片、联系人和联系电话、以及支持通过微信自带的腾讯地图导航到该店铺位置。


3. “客户购买”用例分组中,相关业务用例的特别说明如下:


  • 浏览店铺商品、搜索店铺商品、查看商品详情,这 3 个业务用例对应服务蓝图中的“浏览商品”环节。


  • 加商品到购物车、确定订单付款,这 2 个业务用例对应服务蓝图的“选购并确认付款”环节。


  • 获取微信绑定手机号。这是在确定订单付款时,需要用户填写联系手机号,为了方便用户而允许用户直接点击按钮获取用户绑定微信的手机号。同样因为涉及到微信平台这一伴生系统,故独立提出该用例。


  • 创建订单预支付、完成订单支付。这是微信支付系统已经提供的功能,本系统只是集成该系统已经提供的开放能力,按照微信支付开放接口规范实现即可。需要明确的是,按照微信支付规范,需要先在系统后台调用微信支付系统接口创建预支付流水号、然后返回给前端小程序界面提示用户进行支付密码验证(或其它验证方式)后,微信支付系统“完成支付”,并调用本系统提供的开放接口(即“生效订单”用例)。


  • 生效订单。该业务用例是供微信支付系统在用户支付成功后,反向调用本系统的接口。在该接口的实现中,需要记录订单为已支付状态,并且需要特别说明的是:如果客户下单的商品中包含有商家上架到自家店铺、但是从品牌商导入的商品,则系统需要根据订单内容为品牌商创建子订单。子订单存在的目的,主要是为了用于两个场合:1)根据子订单为品牌商结算营业收入;2)根据子订单为加盟商结算佣金收入。


  • 超时自动取消订单。在客户填写好收货信息(选择收货方式是到店自提还是送货上门、以及送货上门地址、联系手机号等)后,确认对订单付款、微信弹出支付页面后,如果客户超过一定的时限(默认 60 分钟)没有付款,则订单自动取消。这么设计的目的,是因为商家可能在收到订单提醒后(虽然客户可能还没有完成付款),就会开始备货。如果客户不能最终支付,商家则需要将备好的货物再放回实体货架方便继续销售。


  • 浏览我的订单、查看订单详情,这两个业务用例,不在服务蓝图中有体现。但在实际电商交易类系统中,这两个是必不可少的业务用例,是为了方便客户随时查阅自己下单后的相关信息的 。同时,这两个业务用例也是客户进入后续“确认订单完成”用例的操作入口。


  • 确认订单完成。客户收到商品实物后,确认订单完成。在操作确认之前,客户可能会联系商家要求退货退款。只有订单被确认完成后,商家才能最终收到平台转账的营业收入。在订单确认完成时,如果订单包含了品牌商的商品,则系统需要自动同步完成所有品牌商子订单(可能有多个)的确认。


  • 超时自动确认订单完成。正常情况下,客户在收到货物后,需要对订单确认收货,系统才允许商家将该笔订单的营业收入进行提现。但如果客户没有进行手动确认操作,则系统将会在超过最大超时时限(默认 48 小时)后,由机器人自动确认完成订单。同样,自动确认完成订单时,如果订单包含了品牌商的子订单,则同步完成所有品牌商子订单(可能有多个)的确认。


4. “订单管理”用例分组中,有 4 个业务用例需特别说明:


  • 发送订单提醒。会有如下几个场合,系统后台机器人会给相应的对象发送订单提醒:

  • 客户在系统下单完成(即付款完成后),系统会给客户和商家发送订单提醒。对客户来说这只是个提醒,而对商家来说这是业务价值的关键一环(故商家消息是可点击链接打开小程序查看订单详情的):为了方便商家及时响应客户需求,因为如果不及时响应线上订单备货,可能线下有客户就将相应的货物购完,而线上客户最终没有库存可供发货。按照销售的“先到先得”原则,应该是谁先付款谁先拿货。为此,需要系统自动给商家及时发送订单消息提醒。

  • 商家备货完成后,会给客户发送订单纯文本消息提醒(无 UI 操作要求)。

  • 商家发货完成后,会给客户发送订单纯文本消息提醒(无 UI 操作要求)。

  • 商家退款完成后,会给客户发送订单纯文本消息提醒(无 UI 操作要求)。

  • 商家补收货款时,会给客户发送超链接消息提醒,可点击该消息后打开小程序进行付款(事实上,用户也可扫商家小程序端提供的二维码补款)。

  • 客户确认订单关闭、或系统超时自动关闭订单时,系统机器人会给客户和商家双方发送订单提醒。给客户发送的是纯文本提醒,给商家发送的是可点击链接打开小程序查看订单详情的消息。

  • 订单提醒方式的设计,考虑到早期平台的运营成本问题、以及微信平台的限制,只支持两种方式:1)微信公众号免费提醒;2)在商家的小程序管理后台界面的订单管理界面上,会有“未读红点”提示。将来新版系统会为商家提供 PC 端管理后台,会在 PC 端进行语音播报。


  • 记录订单备注。有些情况下,商家可能需要对客户订单特殊备注,比如:客户要求先备货、到下班回家后才来提货或送货上门等等。这种情况下,就需要系统为商家提供针对某订单的特殊备注说明。


  • 管理客户信息。为了能够给客户提供售后服务、以及某些情况下方便商家服务客户,商家需要了解客户的一些基本信息(如:客户姓名、性别、电话、标签、自定义等级等)。因为微信提供的往往是网络昵称,而这往往是不够识别客户身份的。所以,事实上需要目标系统为商家提供客户基本信息的管理功能。


  • 操作订单备货。在商家为客户订单备货的过程中,可能存在某些货物已经缺货,这种情况下需要系统支持同步将商品设置为无货状态。


  • 补收客户货款。

  • 生鲜是个特殊类别的商品,很多商品的规格并不标准化,尤其是活鲜类商品。这种情况下,类似活鲜类商品又是按斤销售的、但其重量又因为成品大小不一,无法准确在线上给出价格。为此,系统需要支持多退少补功能。对于“少补”的情况,需要系统支持商家在客户到店自提、或送货上门时,系统自动生成收款二维码,让客户补付差额部分。

  • 如果补收货款的商品中包含品牌商品,则需要进行品牌商子订单补款操作。


  • 退客户货款

  • 退客户货款用例,会使用在三个场合:1)“多退少补”情况下的“多退”;2)商家备货时,发现某个商品已经缺货,主动给客户退款;3)客户要求退货时商家退款给客户。

  • 如果退款的商品中包含品牌商品,则需要进行品牌商子订单的退款操作。


下面我将其它 5 个业务场景下所有的“业务用例图”截图如下:

  • “建立店铺”业务场景对应的业务用例图:

  • “加盟品牌”业务场景对应的业务用例图:

  • “建立商品库”业务场景对应的业务用例图:

  • “在线接龙”业务场景对应的业务用例图:

  • “资金结算”业务场景对应的业务用例图:


上面我们已经深入地展示了如何设计“服务蓝图”、并基于此给出“业务用例图”设计。在 DDD 全局分析中(也可以理解为需求分析),其实还有个特别重要的工作,就是对每个“业务用例”给出“用例规格书”——相当于是需求规格书。由于篇幅内容过多,而且比较适合放在 scrum 敏捷迭代的每个冲刺(sprint)中,故这里只是给出一个示例(备注:“业务用例”也叫“业务服务”,故下图中的“服务编号”其实就是“业务用例编号”):

业务子域识别和分类

终于到了本节的最后一个内容:根据业务用例的识别,对目标系统的业务子域进行识别和分类。下图是我对“群买菜”各业务子域的识别和分类结果:

对这个识别及分类结果,说明如下:


  • 系统子领域的识别,要从系统的核心价值出发。“群买菜”系统的核心价值,是通过为生鲜店老板/社群团长提供在线零售、在线接龙、加盟分销三大主要业务所需功能的微信小程序,让尽可能多的生鲜店和团购社团使用,平台方赚取尽可能多的系统服务费和资金沉淀收入。


  • 目标系统主要涉及到三大类利益干系人:生鲜店或社群(商家)、消费者(客户)、平台运营方。


  • 我们分别从三大类利益干系人来看。对于商家来说,分别从三大业务线来看:1)在线零售业务,从传统的电商系统设计来看,需要目标系统最起码提供商品库管理、订单管理、客户管理几个主要核心功能域。2)在线接龙业务,需要目标系统提供接龙管理、订单管理、客户管理几个主要业务功能域。3)加盟分销业务,需要目标系统提供加盟关系管理、加盟佣金结算几个主要业务功能域。


  • 对于消费者(客户)来说,主要涉及的功能域是在线选购和下单(可属于订单管理)、查询/查看自身所下订单的信息和状态(仍可属订单管理)、手机支付。


  • 对于平台运营方来说,主要涉及的功能域有:商家管理(主要是用来识别店铺的收支结算到哪个账户下)、平台资金结算这两个业务功能域。


  • 上述所有功能域汇总起来有:店铺管理、商品库管理、订单管理、客户管理、接龙管理、加盟关系管理、加盟佣金结算、手机支付、商家管理、平台资金结算合计 10 个功能域。其中,我们可以把加盟佣金结算和平台资金结算合并为资金结算,这样最终就是 9 个功能域。这 9 个功能域中,手机支付属于微信平台的功能,应该属于通用子域。剩下的其它 8 个都是核心子域,包括:商品库管理、订单管理、客户管理、接龙管理、加盟关系管理、店铺管理、商家管理、资金结算。


  • 另外,对商家来说,考虑到工作很杂,可能还会允许多个微信账号对店铺进行操作,故需要系统支持员工管理。考虑到该员工管理仅限于对目标系统的商家下微信账号做简单管理,不打算做到各行业通用的、一个复杂完善的员工管理体系,故认为其属于支撑子域。同时,目标系统本来就要对登录权限进行控制和用户身份识别,故用户与授权也是必不可少的功能域,该功能域属于通用子域。最后,考虑到为商家提供订单提醒等,我们还需加入消息子域,该子域也是由微信公众号平台、以及用短信通知实现,属于跟具体行业无关,故也认为是通用子域。


到此为止,本专题系列完成了第 3 篇,算是完成了“群买菜”的全局分析(也就是需求分析)过程,也就是完成了“问题空间”的分析。在后面的章节中,我们开始致力于“解空间”的映射。那将包括:战略设计、战术设计、代码实现 3 个部分,才是本专题系列中占最多篇幅的内容。

发布于: 2022 年 03 月 06 日阅读数: 187
用户头像

深清秋

关注

从菜鸟向大神攀登。。。 2020.11.15 加入

21年IT从业经验,热爱写代码、软件架构设计、软件产品设计。最近决定把自己的一些代码或设计经验分享出来,希望对大家有用!个人秉承职业理念:自己给自己加班,提升自己的稀缺性,其实所有人都可以突破年龄障碍!

评论

发布
暂无评论
DDD实战(3):从需求到代码实现生鲜电商系统_DDD_深清秋_InfoQ写作平台