新浪新闻客户端

惟客数据DDD实践探索之路 发挥软件系统的业务价值

惟客数据DDD实践探索之路 发挥软件系统的业务价值
2022年07月06日 16:33

  DDD早在2004年就由埃里克·埃文斯提出,但一直处于不温不火的状态,直到微服务盛行之后,DDD再次回到人们视野之中。京东、美团、华为等巨头也都在自家架构中实践了DDD。

  DDD究竟有什么优势?它是如何落地的?实施难点又在哪里?结合惟客数据实践DDD的经验,今天就来一起探讨下。

  咱们先从一个场景说起。

  通常在研发流程中,需求评审完毕后就交由某个研发做设计,方案的设计完全取决于某个人的经验和对依赖模块的熟悉程度,可能很难识别出模块设计上的不合理。即使可以识别出,往往都会以技术的语言和产品经理进行沟通,产品经理可能很难理解,最终难达到预期的目的。

  以惟客服务过的某地产集团案例为例。客户的诉求是实现“转赠功能”,比如用户A下单5件商品,将其中2件转赠给用户B,此时用户B的“我的订单”栏会出现一笔含有2件商品的订单,且不可退款的同时,用户B还可以再次实行转赠。

  这意味着需要在订单领域生成一种“特殊的订单”和“特殊的拆单”,该订单仅能使用且不能退款。

  需求评审完后,产品、研发一起开始做“领域建模”,由于涉及订单领域,也对照之前的“订单模型图”做了方案的设计,发现订单域承载更多的是交易相关,把转赠业务耦合进来,十分困难。

  但研发在模型图里发现了专门承载履约的“核销聚合根”,只要核销权限能转出去,就可以满足业务场景,产品经理也十分认可,最终将产品做了修改,将原先的订单转送,变为了履约权限的转赠。

  在上面的案例中,无论从产品设计角度,还是转赠场景和交易场景,划分都更清晰;从代码设计角度,减少冲击到订单域,避免现实中独立的两块业务在系统中耦合成一个模块,从而造成订单的核心代码被冲击,后续难维护的后果。最终实现了“多赢”的局面。

  这种“多赢”的局面,就取决于DDD过程中带给我们的几点改变:

  1、领域模型设计一定程度上拉齐了团队的设计水平,不再取决于某几个人的“经验”。

  2、产品、研发建模的过程中,深究业务场景,推导出技术设计的同时也回补了需求漏洞。

  3、团队内统一语言,尤其是产品和研发之间,沟通成本低,减少了由于理解差异导致的风险。

  4、原先依赖的模块,也采用了DDD的设计,有完整的模型文档,并且有效识别出来了“订单聚合”、“核销聚合”,才使得转赠模块在做设计有了很好的基础。

  基于对以上场景的了解,我们再回归定义,从定义出发,一步步拆解。

  概念理解:DDD是什么?

  DDD全称是领域驱动设计,这里的“领域”可以理解为业务边界,以及指定范围内待解决的业务问题。因此DDD它不是一种架构,而是一套思想,是一种拆解业务、划分业务、确定业务边界的方法。

  DDD可以通过合理运用面向对象的封装、继承、多态等设计要素,降低或隐藏整个系统的业务复杂性,帮助我们设计出清晰的领域和边界,并使得系统具有更好的扩展性,很好的实现技术架构的演进,应对纷繁多变的现实业务问题。

  DDD的优势在哪里?

  程序员擅长从技术角度来解决项目问题。但一个软件系统是否真正可用,需要通过其提供的业务价值来体现。因此在关注技术的同时,DDD更强调将关注点转向软件系统所提供的业务价值。

  我们先回顾下产研团队的协作模式,通常是将一个产品开发上线的各个过程拆出来,由市场/运营、产品、UI交互、前端、后端、测试等角色来做分工,每个过程专人负责。

  这么做的好处是标准流水线作业,个体生产效率比较高,但坏处是大家都盯着眼前的一亩三分地,自然很容易忽略整体,更难从整体业务价值出发。同时也容易出现信息不对称的问题,比如产品在讨论A时,前端以为是说B。

  那么,根据惟客数据在核心产品“惟客云”中实践DDD的经验总结,其优势可以包含以下几点:

  统一语言:领域专家、产品、技术、测试等人员都在一起进行事件风暴(整理出相关联的业务指令和事件),在同一个场景下使用统一语言进行领域模型构建,信息传递不会丢失。

  提高效率:设计就是代码、代码就是设计,可以根据领域模型图对编辑进行翻译,即使是新人接手也能快速理解整个业务和代码,上手就能写。

  边界清晰:战略设计帮助产品决策人理解哪些投入是最重要的、哪些既有软件资产是可以重新拿来使用的、哪些人应该被加入团队中?战术设计则帮助产品研发人员具体实施。

  降低成本:先划分业务边界,确认核心业务,避免伴随功能迭代后的代码不断叠加,导致代码耦合,降低维护成本。

  以降低成本为例,假设我们要做一个电商订单下单需求,涉及到用户选定商品,下订单、支付订单、对用户下单时的订单发货:

  常见做法是在分析好业务需求之后,开始设计表结构,订单表、支付表、商品表等等,然后编写业务逻辑当功能迭代,订单支付后要支持取消,下单商品要支持退换货,就又需要加表,并针对实现的逻辑不断进行修改。这也意味着当功能不断迭代,代码也会层层上叠。

  而DDD要求先划分业务边界。该场景下的核心是订单,那么订单就是业务领域里的聚合逻辑体现。支付、商品信息、地址等等都是围绕订单实体。订单本身的属性决定之后,类似于地址只是一个属性的体现。当你将订单的领域模型构建好之后,衍生了仓库的上下文。

  总结来说,DDD优势在质量、效率、成本3方面都得到了体现。

  惟客是如何实践DDD的?

  从时间线来说,可以分为3个阶段:

  2020年7月,引入DDD,在小项目和模块进行试点;

  2021年6月,完成在大会员模块进行实践和应用;

  2022年3月,完成公司交易、营销、会员、家装产品线的改造和重构。

  重点以3月份的项目为例。惟客投入70人参与本次项目,目的是解决老旧项目之间耦合严重、业务边界不清晰、代码重复率高、维护成本高等问题。从落地步骤来拆,包括5个部分:

  需求评审

  1、过需求、了解相关联业务的用户故事

  2、产品输出用户故事地图、原型图、流程图,开发理解相关资料

  拆用户故事

  1、对照用户故事地图将用户故事进行细分

  2、整理出相关联的业务指令和事件(事件风暴)

  3、用户故事评审,确保需求没遗漏、业务指令和事件划分正确

  领域模型图设计

  1、识别应用上下文,划分领域界限(核心、通用、支领域),拆分成多个子域

  2、根据用户故事及业务指令区分出查询模型和命令模型

  3、在领域内绘制出相关联业务的领域模型图(包含查询模型、聚合、聚合内聚合根、实体、值对象的关系、实体具有的能力、领域服务、领域事件)

  4、领域模型图评审

  代码实现

  1、对照领域模型图建业务指令、事件、实体、值对象、实体能力及领域服务

  2、完成领域模块开发,建db入库

  3、代码评审,对照领域模型图

  4、完成所有业务开发

  单元测试

  1、对于聚合能力的单元测试

  2、领域服务,指令的单元测试

  实践过程中遇到哪些问题

  为创建通用语言腾出来的时间和精力

  通用语言是指非技术岗位也能很容易理解的语言,在目标拉齐的基础上,需要拉齐各个角色对术语都使用统一名词,对业务价值以及规则的描述使用统一的描述方式和规则,并且需要使得每一个人都能听的懂。

  以商品条形码为例:

  领域专家:从场景角度分析,它主要是供小程序扫描这个条形码进行购买商品

  产品:从规则角度分析,商品编码,长度是多少位,组成规则是什么。

  开发:按照功能事项的角度去分析,barcode,商品的sku级别的唯一标识,存储方式是什么。

  很明显,大家分析问题的角度不一样,给出的语言不同,但本质上商品条形码=商品编码=barCode,因此需要花时间拉齐不同角色间的语言。

  领域专家对于实践DDD很重要,但这个角色通常是业务专家,他们工作繁忙、时间难约,较难持续在一个项目中消耗太多时间。

  因此在落地中,建议尽可能一次性把业务相关的疑问和问题准备好,减少对接次数、提高效率。

  由过程编码 -> 面向对象编码

  由数据模型 -> 领域模型

  领域模型关注的是领域本身,是业务领域的核心实体,体现在问题域关键概念和之间的联系。构建领域模型的目标是看模型能否清晰表达业务语义、模型能否显性化,扩展性是其次。

  数据模型关注的是数据存储,在我们所有的业务中都离不开数据,离不开对数据的CRUD。构建数据模型目标是看扩展性、性能等非功能属性,业务语义的表达则是其次。

  人最难转变的是思维惯性,而不是技术和策略本身。因此在实践前,对以上3点有心理预期,并提前做好应对方案,可以更快地落地DDD。

  总之,如果企业希望能更好地发挥软件系统的业务价值,从长期价值主义出发,提高代码的可维护性、可扩展性,那么DDD绝对是一套值得尝试的方法

  (来源:新视线)

责任编辑:于安绪

迭代

举报邮箱:jubao@vip.sina.com

Copyright © 1996-2022 SINA Corporation

All Rights Reserved 新浪公司 版权所有