架构进阶之路:复杂业务开发与领域驱动设计

简介: 以下是在现公司,给成员做分享的资料。业务案例来自:一文教会你如何写复杂业务代码。作者:张建飞,进行了重新整理。

以下是在现公司,给成员做分享的资料。业务案例来自:一文教会你如何写复杂业务代码。作者:张建飞,进行了重新整理。

一 业务开发职责

1.1 开发=CVS?

image.png

1.2 为什么会这样?

1、业务所限。非供应链、交易、金融等复杂业务领域,简单业务需求偏多

2、个人原因。接受需求时,只考虑局部实现,不考虑整体业务。

设计时还没有达到要求,只局限于当前需求实现这一最低要求;无法从更高一层的角度看待问题。如果当前级别的需求都存在很大的疏漏,那么到了复杂业务场景,真的有能力能够让人放心交给你来做吗?

1.3 业务真的简单吗?

上图是当前业务系统中的信息流投放与CRM交互过程。这只是CRM中的很小一部分,目前做了多家供应商支持,不同的回调码、消息结构;而且目前支持了组合,各种分支逻辑会更复杂。加上各种风控限制,供应商的稳定性问题,整体看起来,我们的业务也没有那么简单。

1.4 复杂业务场景下的设计开发

如何定义“复杂”?

image.png

1.5 基于经验的一些解决方法

二 业务案例与分析实战

2.1 背景

这里选择阿里零售通业务作为示例。领域:典型的供应链场景,涉及品牌商入驻、库存/仓储、配送、销售多个系统和环节

image.png

2.2 商品的生命周期

2.3 关键业务节点——上架

提问:从这张图,能看到哪些信息?

上图中红框标识的是一个运营操作的“上架”动作,这是非常关键的业务操作。上架之后,商品就能在零售通上面对小店进行销售了。上架操作非常关键,所以也是商品域中最复杂的业务之一,涉及很多的数据校验和关联操作

带来的问题:分支逻辑多;且结构复杂。 商品(单品),商品组/组合商品;状态、库存、佣金、运费、规格、限购、供货价、….

2.4 实现思路?

拆分:一个大service => check1(), check2(),…,createNo(), publish(),……

问题:流程如何管理?

是否需要引入流程引擎(工作流引擎):已有 or 自研的流程引擎,or 依赖于数据库配置的流程处理。 但过早考虑这些是否合理?

2.5 回归核心问题

回到商品上架的问题,这里问题核心是工具吗?是设计模式带来的代码灵活性吗?显然不是,问题的核心应该是如何分解问题和抽象问题,知道金字塔原理的应该知道,此处,我们可以使用结构化分解将问题解构成一个有层级的金字塔结构:

2.6 总结

   通过上面流程的分析,在做过程分解的时候,不要过早把太多精力放在工具和设计模式带来的灵活性上。而是应该多花时间在对问题分析,结构化分解,最后通过合理的抽象,形成合适的阶段(Phase)和步骤(Step)上。

   当问题被清楚地结构化分解之后,我们就可以很明确地通过简单的组合等手段实现业务流程。在保证实现的基础之上,再考虑工具或设计模式来提升灵活性和可扩展性。

2.7 过程分解后的两个问题

1、领域知识被割裂肢解

到目前为止做的都是过程化拆解,导致没有一个聚合领域知识(校验规则…)的地方。每个用例的代码只关心自己的处理流程,知识没有沉淀。

相同的业务逻辑会在多个用例中被重复实现,导致代码重复度高,即使有复用,最多也就是抽取一个 util,代码对业务语义的表达能力很弱,从而影响代码的可读性和可理解性。

2、代码的业务表达能力缺失

试想下,在过程式的代码中,所做的事情无外乎就是取数据 -- 做计算 -- 存数据,在这种情况下,要如何通过代码显性化的表达业务呢? 说实话,很难做到,因为缺失了模型,以及模型之间的关系。脱离模型的业务表达,是缺少韵律和灵魂的。【人话:赋予代码业务更强的表达能力,提升可读性、可维护性】

2.8 怎么做?

举个例子,在上架过程中,有一个校验是检查库存的,其中对于组合商品(CombineBackOffer)其库存的处理会和普通商品不一样。原来的代码写法:

引入领域模型:

image.png

使用模型的表达要清晰易懂很多,而且也不需要做关于组合商品的判断了,因为我们在系统中引入了更加贴近现实的对象模型(CombineBackOffer 继承 BackOffer),通过对象的多态可以消除我们代码中的大部分的 if-else。

三 复杂业务开发方法总结

3.1 总结:过程分解+对象模型 上下结合

所谓上下结合,是指我们要结合自上而下的过程分解和自下而上的对象建模,螺旋式的构建我们的应用系统。这是一个动态的过程,两个步骤可以交替进行、也可以同时进行。

这两个步骤是相辅相成的,上面的分析可以帮助我们更好的理清模型之间的关系,而使用模型表达可以提升我们代码的复用度和业务语义表达能力

四 领域驱动设计初探

4.1 领域驱动设计的一些基础概念

领域:本质上是一种边界划分,领域词语中的“域”也是边界的意思。

领域设计= 边界 + 设计。要求:具备领域知识、总结和概括能力、达成共同认知。

电商系统,有商品模型,但是一个商品模型只有商品的基本信息,数据。如果需要获取一个商品的总价,那么我们需要调用model里面的一个方法来计算。这就是典型的贫血模型。

如果我们在商品模型里面提供一个计算总价的方法。把数据和业务逻辑放在一起,这就是充血模型。

领域模型的基础是对象模型,对象是由属性和方法组成的。识别贫血模型有一个重要的指标是:模型自身需要处理的业务逻辑是否外漏

如果模型本身没有需要处理的业务逻辑,只包含属性那么他不应该称为贫血模型。

如果模型自身需要处理业务逻辑但是没有处理,而是由调用者来处理本属于模型本身的业务逻辑时就应该称之为贫血模型。

在处理表单数据校验时,通常使用的是外部校验方式

领域设计不是一件简单事情,首先你得有这个领域的知识,然后还有一套你对这个领域知识总结和概括,甚至摸清了领域中的逻辑关系,一般人不一定掌握得好,大概只有多年业务专家才会有这个本事,或者多年来一直在开发某个业务系统,直至公司人员组织结构都按照业务领域划分成不同部门了,比如电商公司有订单组、仓库组、支付组和货运组,这种带有业务性质的组织部门其实已经代表了大家的共同领域认识。

4.2 领域驱动实践历程

1. 套概念阶段

了解了一些 概念,然后在设计中“使用”聚合根,有界上下文等概念。更进一步,也会使用一定的分层策略。然而这种做法一般对复杂度的治理并没有多大作用。

2. 融会贯通阶段

DDD 的本质是统一语言、边界划分和面向对象分析的方法。

哪些能力应该放在 Domain 层,是不是按照DDD传统的做法,将所有的业务都收拢到 Domain 上,这样做合理吗?这并不是一个可以很容易说清楚的问题。因为在现实业务中,很多的功能都是用例特有的,如果盲目的使用 Domain 收拢业务并不见得能带来多大的益处。相反,这种收拢会导致 Domain 层的膨胀过厚,反而会影响复用性和表达能力。

所以,我们考虑逐步地进行能力下沉的方式,即不强求一次就能设计出 Domain 的能力,也不强制要求把所有的业务功能都放到 Domain 层,而是采用实用主义的态度,即只对那些需要在多个场景中需要被复用的能力进行抽象下沉,而不需要复用的,就暂时放在 App 层的 Use Case 里就好了。

通过实践,发现这种循序渐进的能力下沉策略,应该是一种更符合实际、更敏捷的方法。因为我们承认模型不是一次性设计出来的,而是迭代演化出来的。

4.3 能力下沉过程

五 开发的选择:技术 or 业务

   很多业务技术同学的困惑,也是我之前的困惑:即业务技术到底是在做业务,还是做技术?业务技术的技术性体现在哪里?

   通过上面的案例,我们可以看到业务所面临的复杂性并不亚于底层技术,要想写好业务代码也不是一件容易的事情。业务技术和底层技术人员唯一的区别是他们所面临的问题域不一样。

   业务技术面对的问题域变化更多、面对的人更加庞杂。而底层技术面对的问题域更加稳定、但对技术的要求更加深。比如,如果你需要去开发 Pandora,你就要对 Class Loader 有更加深入的了解才行。

   但是不管是业务技术还是底层技术人员,有一些思维和能力都是共通的。比如,分解问题的能力,抽象思维,结构化思维等等。这些,都需要我们在日常的工作生活中不断的加深思考,沉淀能力。

相关文章
|
8月前
|
人工智能 运维 安全
配置驱动的动态 Agent 架构网络:实现高效编排、动态更新与智能治理
本文所阐述的配置驱动智能 Agent 架构,其核心价值在于为 Agent 开发领域提供了一套通用的、可落地的标准化范式。
4004 110
|
8月前
|
SQL 前端开发 关系型数据库
如何开发一套研发项目管理系统?(附架构图+流程图+代码参考)
研发项目管理系统助力企业实现需求、缺陷与变更的全流程管理,支持看板可视化、数据化决策与成本优化。系统以MVP模式快速上线,核心功能包括需求看板、缺陷闭环、自动日报及关键指标分析,助力中小企业提升交付效率与协作质量。
|
8月前
|
NoSQL 数据可视化 安全
如何开发一套车辆管理系统?(附架构图+流程图+代码参考)
本文介绍了如何通过搭建车辆管理系统(VMS)帮助企业摆脱传统管理方式,实现流程化、可视化、合规化和自动化。内容涵盖系统架构、关键功能模块、数据模型、API设计、前后端实现及实施建议,提供可落地的技术方案,助力企业降低隐形成本、提升管理效率与透明度,实现数据驱动决策。
|
8月前
|
JSON 文字识别 BI
如何开发车辆管理系统中的加油管理板块(附架构图+流程图+代码参考)
本文针对中小企业在车辆加油管理中常见的单据混乱、油卡管理困难、对账困难等问题,提出了一套完整的系统化解决方案。内容涵盖车辆管理系统(VMS)的核心功能、加油管理模块的设计要点、数据库模型、系统架构、关键业务流程、API设计与实现示例、前端展示参考(React + Antd)、开发技巧与工程化建议等。通过构建加油管理系统,企业可实现燃油费用的透明化、自动化对账、异常检测与数据分析,从而降低运营成本、提升管理效率。适合希望通过技术手段优化车辆管理的企业技术人员与管理者参考。
|
8月前
|
消息中间件 缓存 JavaScript
如何开发ERP(离散制造-MTO)系统中的生产管理板块(附架构图+流程图+代码参考)
本文详解离散制造MTO模式下的ERP生产管理模块,涵盖核心问题、系统架构、关键流程、开发技巧及数据库设计,助力企业打通计划与执行“最后一公里”,提升交付率、降低库存与浪费。
|
7月前
|
前端开发 JavaScript BI
如何开发车辆管理系统中的车务管理板块(附架构图+流程图+代码参考)
本文介绍了中小企业如何通过车务管理模块提升车辆管理效率。许多企业在管理车辆时仍依赖人工流程,导致违章处理延误、年检过期、维修费用虚高等问题频发。将这些流程数字化,可显著降低合规风险、提升维修追溯性、优化调度与资产利用率。文章详细介绍了车务管理模块的功能清单、数据模型、系统架构、API与前端设计、开发技巧与落地建议,以及实现效果与验收标准。同时提供了数据库建表SQL、后端Node.js/TypeScript代码示例与前端React表单设计参考,帮助企业快速搭建并上线系统,实现合规与成本控制的双重优化。
|
8月前
|
消息中间件 JavaScript 前端开发
如何开发ERP(离散制造-MTO)系统中的技术管理板块(附架构图+流程图+代码参考)
本文详解ERP(离散制造-MTO)系统中的技术管理板块,涵盖产品定义、BOM、工序、工艺文件及变更控制的结构化与系统化管理。内容包括技术管理的核心目标、总体架构、关键组件、业务流程、开发技巧与最佳实践,并提供完整的参考代码,助力企业将技术数据转化为可执行的生产指令,提升制造效率与质量。
|
8月前
|
消息中间件 JavaScript 关系型数据库
如何开发一套ERP(离散制造-MTO)系统(附架构图+流程图+代码参考)
本文介绍了面向离散制造-MTO(按订单生产)模式的ERP系统设计与实现方法。内容涵盖ERP系统定义、总体架构设计、主要功能模块解析、关键业务流程(订单到交付、BOM展开、MRP逻辑、排产等)、开发技巧(DDD、微服务、事件驱动)、参考代码示例、部署上线注意事项及实施效果评估。旨在帮助企业与开发团队构建高效、灵活、可扩展的ERP系统,提升订单交付能力与客户满意度。
|
8月前
|
NoSQL 关系型数据库 BI
如何开发一套固定资产管理系统?(附架构图+流程图+代码参考)
固定资产管理涉及采购、入库、维修、盘点、报废等多个环节,是企业资产保值增值的关键。本文详解固定资产管理系统(FAMS)的核心功能、系统架构、资产全生命周期流程,并提供功能设计、开发实操技巧与关键代码示例,涵盖台账、申购、入库、报修、处置、盘点等重点模块。内容聚焦企业落地实践,帮助提升资产管理效率、降低风险、保障审计合规。
|
8月前
|
人工智能 安全 数据可视化
配置驱动的动态Agent架构网络:实现高效编排、动态更新与智能治理
本文系统性地提出并阐述了一种配置驱动的独立运行时Agent架构,旨在解决当前低代码/平台化Agent方案在企业级落地时面临困难,为Agent开发领域提供了一套通用的、可落地的标准化范式。
621 18
配置驱动的动态Agent架构网络:实现高效编排、动态更新与智能治理