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

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

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

一 业务开发职责

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 有更加深入的了解才行。

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

相关文章
|
3天前
|
API 持续交付 开发者
构建高效微服务架构:后端开发的新视角
【5月更文挑战第8天】 随着现代软件开发的演变,微服务架构已经成为了企业追求敏捷、可扩展和灵活部署的重要解决方案。本文将深入探讨如何构建一个高效的微服务架构,包括关键的设计原则、技术栈选择以及持续集成与部署的最佳实践。我们还将讨论微服务带来的挑战,如数据一致性、服务发现和网络延迟,并提出相应的解决策略。通过本文,后端开发者将获得构建和维护微服务系统所需的深度知识,并了解如何在不断变化的技术环境中保持系统的健壮性和可维护性。
34 8
|
1天前
|
存储 监控 API
构建高效微服务架构:后端开发的现代实践
【5月更文挑战第9天】 在本文中,我们将深入探讨如何在后端开发中构建一个高效的微服务架构。通过分析不同的设计模式和最佳实践,我们将展示如何提升系统的可扩展性、弹性和维护性。我们还将讨论微服务架构在处理复杂业务逻辑和高并发场景下的优势。最后,我们将分享一些实用的工具和技术,以帮助开发者实现这一目标。
|
2天前
|
Kubernetes 持续交付 开发者
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第8天】 随着现代软件开发的不断演进,微服务架构已成为众多企业解决复杂系统问题的首选方案。本文深入探讨了微服务架构的核心概念、设计原则以及实施策略,旨在为后端开发者提供一种清晰、高效的技术路径。通过分析微服务的优势与挑战,结合具体的应用实例,文章将展示如何通过容器化、服务网格和持续集成/持续部署(CI/CD)等先进技术手段,实现后端服务的高可用性、可扩展性和敏捷性。
|
2天前
|
消息中间件 监控 Java
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第8天】随着现代软件开发的复杂性日益增加,传统的单体应用架构逐渐难以满足快速迭代和灵活部署的需求。微服务架构作为一种新的解决方案,以其模块化、独立性强和易于扩展的特点,正在成为后端开发领域的重要趋势。本文将深入探讨如何构建一个高效的微服务架构,并分析其对后端开发实践的影响。
|
3天前
|
敏捷开发 持续交付 API
构建高效微服务架构:后端开发的现代实践
【5月更文挑战第8天】 在数字化转型的浪潮中,微服务架构已成为企业追求敏捷开发、持续交付和系统弹性的关键解决方案。本文将深入探讨微服务的核心概念,包括其设计原则、优缺点以及如何在后端开发中实现高效的微服务架构。我们将通过实际案例分析,展示微服务如何帮助企业快速适应市场变化,同时保持系统的可维护性和扩展性。
|
4天前
|
设计模式 Kubernetes 数据库
构建高效可靠的微服务架构:后端开发的新范式
【5月更文挑战第7天】在现代软件开发的浪潮中,微服务架构已经成为一种流行的设计模式。它通过将应用程序分解为一组小的、独立的服务来提高系统的可维护性和扩展性。本文深入探讨了微服务架构的核心概念、优势以及如何利用最新的后端技术构建一个高效且可靠的微服务体系。我们将讨论关键的设计原则,包括服务的独立性、通信机制、数据一致性和容错性,并展示如何在云环境中部署和管理这些服务。
17 3
|
4天前
|
缓存 监控 数据库
构建高性能微服务架构:后端开发的终极指南
【5月更文挑战第6天】 在现代软件开发的浪潮中,微服务架构以其灵活性、可扩展性和容错性引领着技术潮流。本文深入探索了构建高性能微服务架构的关键要素,从服务划分原则到通信机制,再到持续集成和部署策略。我们将透过实战案例,揭示如何优化数据库设计、缓存策略及服务监控,以确保系统的稳定性和高效运行。文中不仅分享了最佳实践,还讨论了常见的陷阱与解决之道,为后端开发者提供了一条清晰、可行的技术路径。
|
5天前
|
监控 负载均衡 持续交付
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第5天】在数字化转型的浪潮中,微服务架构以其灵活性、可扩展性和容错性成为企业追求的技术典范。本文深入探讨了微服务的核心组件、设计原则和实施策略,旨在为后端开发者提供构建和维护高效微服务系统的实用指南。通过分析微服务的最佳实践和常见陷阱,我们揭示了如何优化系统性能、保证服务的高可用性以及如何处理分布式系统中的复杂性。
|
6天前
|
负载均衡 Java 数据库
构建高效微服务架构:后端开发的新趋势
【5月更文挑战第5天】在现代软件开发中,微服务架构已经成为一种流行的设计模式。它通过将大型应用程序分解为一组小型、松散耦合的服务来提高可维护性、可扩展性和敏捷性。本文将探讨如何构建高效的微服务架构,包括选择合适的技术栈、设计良好的服务接口、确保数据一致性以及实现高可用性和负载均衡。
|
8天前
|
JavaScript Java 持续交付
构建高效微服务架构:后端开发的新范式
【5月更文挑战第3天】 在现代软件开发的浪潮中,微服务架构以其灵活性、可扩展性和技术多样性而受到重视。本文深入探讨了如何构建一个高效的微服务系统,包括关键的设计原则、技术选型、以及实现细节。我们将通过分析微服务的核心概念,提供一套实用的步骤和最佳实践,以指导开发者构建出既健壮又易于维护的分布式系统。文章将重点讨论如何在保证系统性能和稳定性的前提下,实现服务的解耦与独立部署,从而推动后端开发工作流的优化和创新。