当前位置: 首页 > news >正文

【领域驱动设计 开篇】零 来源及学习路径

DDD是什么

2003 年,Eric Evans 写了《领域驱动设计:软件核心复杂性应对之道》一书,正式提出了这种方法。领域驱动设计的英文是 Domain-Driven Design,简称 DDD。

按照作者自己的说法,“DDD 是一种开发复杂软件的方法”。

我们把作者的原话做一个扩展:“DDD 是一种开发复杂软件的系统化方法学思想”,通俗的说就是提供了一套复杂软件开发的标准步骤。

下面我们把上面的话拆解一下

什么是方法学

方法学(Methodology)是一门学科,指在特定领域进行研究或活动时所采用的一套方法、规则和原则的体系。这里的方法学指的是面向对象的方法学:

  • 如果你的Java 代码写得特别溜,可以说掌握了面向对象的编程方法;
  • 如果你很熟悉面向对象的设计原则,掌握很多设计模式,可以说你懂面向对象的设计方法;
  • 如果你能为业务概念构建领域模型,那么你就懂了面向对象的分析方法

面向对象的分析、设计、编码三种方法融会贯通,成为一个有机的整体,这个叫面向对象的方法学。其中面向对象的分析方法,或者说领域建模的方法,正是DDD的重点

什么是系统化

系统化方法的作用在于,提供了一套相对容易的步骤,能够使我们这些中等智商的人,也能做到原来高智商的人才能做到的事情,从而让你能够省出时间和脑力,来探索更复杂的问题。

DDD中蕴涵了哪些思想

归纳一下,大概有构建知识、分而治之、抓大放小、统一语言、抽象化、可视化、协作以及演进等等。DDD 是通过总结了一套系统化的方法学,能够把这些大词落地。

DDD是怎么出现的

按照作者在原书中的说法,DDD 是来自面向对象的方法学和敏捷软件开发。DDD 对它们进行了总结和提炼,使之更容易学习和实践。但是面向对象方法学从 80 年代兴起,到了2000 年左右已经成熟。既然有了面向对象,为什么还要有DDD 呢?这是因为传统的面向对象方法学存在一些问题。

传统面向对象方法学的问题

早期面向对象的成功,主要是在几个特定的领域,比如计算机语言、图形用户界面、办公自动化软件等等,但在企业应用方面还没有取得成功。所谓企业应用,包括像银行的贷款系统、保险公司的理赔系统、电信公司的计费系统等等。

那个时候的面向对象方法学还不能很好地应用于企业应用,大体上有以下几个原因。

  • 开发人员只重技术不重业务,也就是技术驱动业务。企业应用是用来解决业务问题的,但很多开发人员把主要精力放到技术的研究上,比如语言、框架、工具等等。以为把技术学会了,自然就能把系统开发好。同时重技术、不重业务的思想造成了业务和技术人员之间难以相互理解,技术人员难以真正满足业务需求。
  • 领域建模落地难度高。面向对象方法学主要是围绕领域建模开展的。领域建模是一种“手艺”。凡是手艺,都不是看看书、学学理论就能掌握的,而是要经过实践中的磨炼,学习成本自然就高。
  • 早期面向对象方法学主要考虑的是建模技术,很少考虑协作问题。历史上很多伟大的软件开始时都是个人作品,比如 UNIX 和 C 语言。作者在一开始是写给自己用的,所以并不存在协作问题。但是企业应用则不同,多数都是团队作战。即使只有一线开发人员,也免不了和需求方打交道。所以协作变得很重要。
  • 难以适应变化。企业应用的需求往往变化频繁,很多变化根本无法预料。传统的面向对象方法学也很少讨论怎样应对变化的需求。

DDD如何落地企业应用

针对以上四个问题,DDD是这么解决的:

  • 把开发者从只重技术的弯路上拉回来,也就是用领域来驱动设计。从“领域驱动设计”这个名字就可以看出,“领域”指的就是软件系统要解决的业务问题,也可以叫“业务领域”。用领域来驱动设计,就是说要从业务出发进行系统的设计。
  • 总结出了一套围绕领域建模进行软件开发的模式。要搞清业务,就要学会领域建模。为此,DDD对面向对象方法学和敏捷软件开发方法进行了提炼,总结出了一套围绕领域建模进行软件开发的模式,一共有四十多个。最基础的模式包括:模型驱动设计,实体、值对象。
  • 强调业务人员和技术人员一起协作进行领域建模,在这个过程中提炼领域知识。和协作密切相关的模式有通用语言、模型驱动设计、限界上下文
  • 提出柔性设计概念。软件设计之初,仅进行必要的设计,而非过度设计;随着业务变化,仅对变化频繁的部分进行迭代,使其越来越灵活。也就是说,模型中扩展性高的部分,是自然演进形成的,这个过程就是柔性设计,它能够避免过度设计。

从上面看,DDD提炼了一套更容易掌握的原则、模式和实践,能够解决企业应用开发过程中的各种问题。

既然DDD这么好,为什么之前不火?

《领域驱动设计》这本书其实是 2003 年写的,到现在已经20多年了。但直到2020年左右,DDD才真正开始普及起来。主要有两个原因:

  • 使用DDD的必要性不强。
    • 一方面,很多企业软件不太复杂,而复杂软件的迭代也不像现在这样频繁;
    • 另一方面,当时的新兴产业,例如互联网,还处在跑马圈地、野蛮生长的阶段。这时关注的是系统快速上线,抢占市场,至于软件质量好不好,容不容易维护,暂时不是考虑的重点。
  • DDD 普及的一些前提条件也还没准备好。
    • 首先是敏捷软件开发刚刚出现不久,还不普及。如果没有迭代开发、持续重构、测试驱动、持续集成等敏捷实践的支持,构建良好的领域模型并在代码上落地是很困难的。
    • 其次是配套的开发框架还不成熟。那时 J2EE 还被认为是企业应用事实上的标准,而基于这种框架开发程序,是很难和 DDD 的领域模型相衔接的。2004 年,Spring 发布了 1.0 版,从技术上基本解决了 EJB 的问题,理论上可以比较好地支持 DDD。然而 Spring 的真正普及,还要假以时日。

DDD为什么近几年又火了呢?

  • 数字化时代的到来,使 DDD 变得非常有必要。
    • 数字化时代,技术逐渐成为企业核心竞争力的主要因素,无论业务还是系统都变得更加复杂。因此,如何将业务和技术融为一体,就成了很多企业的主要问题,而这正是 DDD 的主要优势。
    • 行业竞争的加剧也要求系统具有更好的用户体验、更高的质量、更快地满足变化的需求。这些问题很难解决,必须引入系统化的方法。
    • 另外,云计算、微服务等新技术架构的产生,也需要方法学的支持。
  • DDD 普及的道路已经铺好,这项技术逐渐变得可行。
    • 现在敏捷软件开发已经普及。迭代、演进、协作等思想已经深入人心。
    • Spring boot 等轻量级框架已经得到广泛使用,这些框架支持了领域模型与具体技术的关注点分离,使开发人员从技术细节中解放出来,将更多的精力投入到领域逻辑本身的分析和设计。
    • 支持DDD落地的相关架构实践也已经研究得比较透彻,比如整洁架构、事件驱动架构以及 CQRS 等等。
    • DDD 本身也在不断完善,比如补充了像领域事件等新的模式,出现了事件风暴等新的实践。

DDD的适用场景

开发中哪些场景推荐使用DDD呢?

  1. 业务复杂的企业应用。当业务过于复杂时,经常出现业务人员和开发人员的理解不一致、沟通效率低的情况;或者经常要用一段加了很多限定词的话来描述一个业务数据。这些时候,就有必要采用DDD进行领域建模,形成一些业务概念,并与业务达成一致,来提升后续沟通效率。
  2. 迭代成本高的系统。在系统前期因为业务迭代速度快,经常出现补丁式的代码或者定制化代码,使得系统的扩展性和可维护性下降,维护成本越来越高。这个时候,同样也可以通过领域建模,将业务过程拆分为多个领域,并明确各领域边界。后续业务迭代时在对应领域内进行升级,将影响范围降到最小。
  3. 有重构诉求的系统。因为各种各样的问题吧,有些系统的架构和代码已经严重腐化了,希望通过重构来提高代码质量和可维护性,但不知道往哪个方向重构,怎么在重构过程中降低风险,并且兼顾业务需求呢?同样,可以通过领域拆分,划分子领域边界。采用每次重构一个子领域的方式逐步完成项目整体重构。

DDD的学习路径

学习DDD要经过三个阶段:

阶段一:夯实基础

通过这个阶段,你可以打通一个“需求 - 模型 - 代码”的最小闭环,对 DDD设计及落地过程有一个初步的感觉。

  • 首先学习“事件风暴”方法,梳理行为需求,同时介绍“统一语言”。
  • 其次实操DDD 的核心技能“领域建模”,引入实体、关联、模块几个重要的模式。
  • 最后进行模型的实现,包括数据库设计、编码。

阶段二:渐入佳境

这个阶段学习一些高级技能。

  • 首先会从理论、模型和编码层面学习“聚合”
  • 其次学习值对象,包括值对象的本质和优点,并解决值对象在建模和编程上的一些具体问题。
  • 最后学习一个重要的建模技巧——泛化,这是领域建模由初级走向中、高级的关键技能。

阶段三:更进一步

  • 首先介绍“限界上下文”模式
  • 其次学习事件驱动和 CQRS两个架构模式。
  • 最后会介绍实践落地的关键要点,包括DDD 切入点的选择,遗留系统的改造等等

几个思考题

Q1:为什么领域建模需要经常迭代,而非一步到位呢?

我觉得主要有两部分原因:

  • 人对一个业务领域的理解是逐步加深的过程,而非一步到位,所以领域模型也是逐步迭代的。
  • 业务是不断变化的,领域模型为了适应业务的变化也要不断迭代。

Q2:有人说DDD的目的就是为了开发微服务,你觉得呢?

  • DDD 是一种设计思想(方法论),适用于任何复杂业务系统,可以用在单体、模块化、也可以用在微服务里。它最开始被提出,核心目标是解决复杂业务软件的建模问题——让代码能够准确表达业务意图。(Eric Evans 在 2003 年提出)
  • 微服务是一种架构风格,可以用 DDD 指导拆分,也可以不用。微服务更多是技术架构层面的拆分策略,解决的是组织协作、部署独立、弹性伸缩、技术异构等工程化问题,重点围绕"如何拆"、"拆多小"这些工程实践。(Martin Fowler 和 James Lewis 在2014年推广微服务)

因为 DDD 的限界上下文和微服务的服务边界在划分思路上一致,都是强调"高内聚、低耦合"。所以可以用 DDD 的思路去指导微服务的拆分。DDD 是手段,微服务是可能的结果之一,但不是唯一目的。

写在最后

一个新的设计思想的出现及流行一定有其必要性,DDD也不例外。随着经济的发展,业务日益复杂,对系统可维护性及扩展性的诉求必然会提高,DDD就能很好的解决这个问题。通过事件风暴方法,将业务过程拆分为多个业务领域,并划定领域边界,将产生的概念与产研测、业务、运维等形成共识,对于后续的沟通及业务的发展都有极大的帮助。

学习资料

本系列为极客时间的《手把手教你落地 DDD》学习笔记。

《领域驱动设计:软件核心复杂性应对之道》电子版:https://zhongjinggz.github.io/ddd-reference-cn/#/README

http://www.jsqmd.com/news/794032/

相关文章:

  • 视觉语言模型心智理论评估:意图理解与视角采样的能力分离现象
  • IMMACULATE框架:黑盒LLM服务的可验证审计技术
  • EDA技术演进全景:从物理验证到AI驱动的设计自动化
  • 示波器有效位数(ENOB)实战指南:从原理到选型与应用
  • IoT设备无线通信合规测试全解析
  • Oracle诉Google案:API版权与合理使用对软件互操作性的深远影响
  • 从苹果三星2016年困境看消费电子行业创新与供应链管理
  • 树莓派创意相机实战:从图像处理到嵌入式系统集成
  • DevSquad:一体化开发者工具箱,提升本地开发与调试效率
  • 数据库安全与权限管理详解
  • 《Java面试85题图解版(二)》进阶深化下篇:Redis缓存
  • 观察使用Token Plan套餐后月度AI调用成本的变化趋势
  • Java多线程:从入门到进阶
  • 构建产品级AI智能体:五层架构与审美工程实战指南
  • 鸣潮自动化终极指南:5分钟解放双手,告别重复刷图
  • [具身智能-660]:具身智能系统 三层分级架构(基于 ROS2 分布式全域组网):上位机可视化层 + 中位机 AI 决策层 + 下位机实时感知执行层三级分层架构。
  • 从绕接到焊接:硬件连接技术的演进与工程思维启示
  • ARM TPIU调试接口原理与应用实践
  • 面向对象——面向对象基础
  • Docker镜像逆向分析:dfimage工具原理、实战与CI/CD应用
  • 从美光收购尔必达看DRAM产业格局:技术、市场与整合逻辑
  • 抖音下载器终极指南:3种场景下的高效内容获取方案
  • AI智能体规则引擎:从提示词约束到运行时控制的架构实践
  • openclaw官网入口中文版_一键1分钟免费使用小龙虾AI!
  • 手把手教你学Simulink——基于Simulink的储能PCS(功率转换系统)离网V/f控制仿真示例
  • 以太网技术演进:从局域网到万物互联的生态系统
  • SDN与IoT融合:构建云边端一体的智能网络神经系统
  • 【AI大模型春招面试题31】什么是“零样本学习(Zero-Shot)”“少样本学习(Few-Shot)”?大模型实现这类能力的核心原因?
  • 芯片验证覆盖率:从度量陷阱到有效策略的实战解析
  • 别再只盯着信号强度了!深入浅出解读LoRa天线S11、驻波比与回波损耗