DDD领域驱动设计

一、背景

在 DDD领域驱动设计中, DDD架构师负责定义出领域模型,而领域专家负责将领域模型转换为具体的软件系统。
对于传统的面向对象(OOP)架构来说,为了适应新的软件技术和新的业务需求,系统通常需要重新进行重构,或者修改核心流程或行为。这在传统架构中是非常常见的现象,它并不是 DDD所要解决的问题。为了解决这个问题,我们需要给出一种架构范式来简化这种重构和修改,这就是领域驱动设计(Domain Driven Design, DDD)。在 DDD中,它试图提供一种指导方法,来让架构师更容易地从应用程序和业务逻辑中分离出领域模型。DDD通过“领域模型”来定义软件系统的行为和运行方式。每个应用程序都有自己特定的功能、数据和行为逻辑。例如:我们需要根据订单状态进行订单创建、订单管理、运费管理等操作;我们也需要根据销售状况进行客户管理、库存管理等操作。通过将这些应用程序定义为一个领域模型(即业务逻辑)来规范这些功能和行为之间的联系,时还可以通过这些功能之间的关系来构建一个更好的应用程序。在传统架构中,我们往往很难将一套新技术和新业务模式引入到已有系统中。因此,传统架构通常将其设计成一个简单的、静态的系统以满足各种需求(如用户体验)。我们将这种架构称为“业务驱动”架构,因为它涉及到设计核心流程和功能;然而当我们引入新技术或新模式时,通常不会引入一些新功能或核心流程(如数据结构)。

二、什么是 DDD

DDD (Direct Design Decision Definition)是一种架构方法,它通过将大型系统分解为若干个较小的部分,然后在这些部分中分解出更小的领域(Domain),然后在这些较小的领域中进行软件设计。
DDD最早由著名软件架构师 Alan Fogg在2007年提出。他将复杂系统拆分成若干较小的子模块,然后再对每个子模块进行详细设计。他认为将复杂系统分解成若干个较小的子系统并不是很困难,但是如何从一个子系统扩展到一个更大的子系统,却并不容易,而且如果每个子系统都需要额外的设计工作,那么整个系统也将变得异常复杂。因此,他提出了一种适合于大型系统的、独立于各个子系统的 DDD架构方法,用来简化大型系统结构和业务流程。他将软件设计领域中著名的“领域驱动设计(Domain Driven Design)”概念引入到 DDD中,通过分解为子领域模型和功能模块来简化大型系统结构。他认为在大型系统中存在许多对系统具有重要影响、但又容易被忽略的子领域。通过对这些子领域进行建模,可以很好地进行软件设计和代码实现。
在 DDD架构中,每个“子领域”都是一个独立的、相对较小的子系统,每个“子领域”都可以看做一个完整系统下的一个“部分”。
在这个层面上,我们将每个领域看作是一个可独立部署、可独立扩展和可独立重构的软件实体。
这种架构方法能帮助我们更好地理解并解决大型系统结构和业务流程中出现的问题。

三、如何设计领域模型

我们可以从领域模型的4个特征来理解:

特征一:领域模型是对问题域中的类、对象和关系的抽象和组织,是解决问题时发现的领域范围中最重要、最相关的类,它反映了问题域的领域特性。

特征二:领域模型是对问题域中某个或某些类、对象和关系的抽象,反映了这些类和对象对问题域所作的贡献。

领域模型是一种模式,它规定了问题域中各个对象之间和问题域与系统环境之间的交互方式,为问题域中的类、对象和关系提供了一种标准接口,以定义它们之间如何交互。
在 DDD中,领域模型通常不是从具体对象开始的。它由概念、公理、规则和约束组成。概念是对某一类事物或者某一组事物进行定义和描述,这些概念都是由一套普遍有效的规则构成,共同描述了某个特定类或者系统行为。

领域模型是一个抽象概念,它描述了一个特定领域中最相关的概念,这个概念表示特定系统行为之间以及系统与环境之间最相关、最有意义的部分。一个概念可以由多个实体或者一组实体来组成。

通常情况下,我们使用“实体”或者“对象”来表示领域模型。对于那些需要大量共享数据但是不会暴露给外部世界的应用程序而言,使用“实体”更加合适。

四、如何设计数据模型

数据模型是 DDD的核心,在设计数据模型时我们要重点考虑:

领域业务实体:领域的核心业务实体,包括系统实体、外部实体以及中间实体。这里强调下,我们一定要从业务角度去设计,不要只是从技术角度去设计,否则会导致系统的耦合性更大。
领域业务概念:领域的核心概念,包括一些业务属性、业务行为以及在数据层面的一些表现形式,比如状态、行为等。

数据依赖是指数据存储时所依赖的数据实体的集合,包括系统间的依赖和外部依赖。对于系统间的数据依赖一定要在设计时提前考虑好,不要等到开发阶段才发现还有这个问题。而对于外部依赖一定要做好接口设计和开发规范。

领域对象:在设计领域对象时,我们要将领域对象与各模块进行分离,包括设计为不同的类,并明确其功能以及之间的关系;如果一个类是一个业务实例的话,那么就不要再增加业务实例了。
我们要去设计一种数据模型来支持这种架构模式下不同模块之间的独立和解耦。
当我们有了上面这些数据模型后就可以进行下一步的数据建模工作了。

领域对象建模:
领域对象模型主要由以下三部分组成:领域实体、属性、值(关系)。

首先我们需要为每个类定义一个唯一的 ID,这样我们就可以将属性和值映射到某个唯一 ID上;然后再为每个类定义一个属性值(关系);最后使用属性值(关系)去匹配每一个类对应的 ID。
当我们完成了领域对象模型后就可以对表进行设计了。

五、领域驱动设计中的错误

虽然 DDD已经被广泛应用,但在实际项目中,我们发现并不是所有的项目都能进行 DDD,这主要有两个原因:
1、缺乏领域驱动设计的知识(或者不知道怎么做)
2、没有意识到领域驱动设计的重要性(或者意识到了但缺乏工具)

对于缺乏领域驱动设计知识这一点,大家都能理解,也都明白,所以很多人会直接照搬 JavaScript的代码实现方式来解决问题。这也是为什么很多人没有领域驱动设计思维的原因。
对于没有意识到领域驱动设计的重要性这一点,大家可能会比较疑惑:领域驱动设计与我们平时写的代码有什么区别呢?怎么区分?
对于这个问题,我们可以用一个简单的例子来说明:
我们经常看到这类代码,中既有领域驱动设计的思想、又有数据模型,也有面向对象等设计思想。这类代码可以看作是两个完全不同的领域驱动设计。

再举个例子:
一个用户界面系统,上面有两个用户界面元素,分别代表不同的功能:用户A和用户B。由于没有领域驱动设计思想的指导,这种两个界面元素之间相互独立的代码设计模式给整个系统带来了不小的问题:
A和B之间无法直接进行交互,而只能通过消息机制来传递消息给对方;
A和B之间无法进行数据交换;

由于没有领域驱动设计思想做指导(或者没有工具),系统中可能会出现以下问题:
某个功能A或B是由多个应用程序所支持、但缺少领域模型;
这些问题的原因主要在于:缺乏领域驱动设计思想(或者工具)。

六、如何解决性能问题

领域驱动设计的核心思想是将系统抽象为领域,从而对领域进行理解,然后再进行架构设计,这样既可以降低开发难度,也可以提高系统的可扩展性。
那么如何解决性能问题呢?
在做这个架构设计之前,我们需要了解清楚系统的业务流程和应用场景,这样才能更好的进行架构设计。当然这个业务流程和应用场景是由很多细节组成的,这些细节往往是不容易被发现的,而我们可以从以下几个方面进行考虑:

  1. 业务流程
  2. 应用场景
  3. 性能

这三个方面往往是相互关联的,当我们先从业务流程着手时,可以知道系统可能存在哪些性能问题。当我们确定了系统可能存在性能问题后,再根据这些问题来制定解决方案。
业务流程
我们可以通过对业务流程进行拆解,然后发现系统可能存在哪些性能问题。通常情况下是一个简单的业务逻辑所导致的问题,也有可能是因为其他系统之间发生了交互导致的性能问题。再根据这些问题来制定解决方案就可以了。
应用场景
很多时候我们需要分析出系统可能存在哪些性能问题后才能决定如何解决这些性能问题,但是在分析这些业务流程和应用场景时通常会出现很多不确定因素。比如:数据量过大、并发请求过多、网络环境较差等等。在分析出这些性能问题后再去设计架构,就可以更容易的进行解决。
比如:我们经常会遇到并发请求过多的情况,通常解决这种情况时只能增加服务器、增加数据库表、增加查询条件等等来处理这些问题。这样就会导致系统性能下降严重影响用户体验。

七、小结

在 DDD领域驱动设计中,通过使用领域模型对不同的系统进行分层,定义了不同层次的需求(包括但不限于以下内容),从底层的接口、数据和功能需求一直到上层的业务流程。这样能使业务需求得到更加明确、清晰的表达,能减少开发过程中与业务需求相悖的情况,并且提高了设计工作的效率。在领域模型中还定义了一个层次模型来组织不同的系统,可以看出领域驱动设计在 DDD架构中的重要地位。
在使用领域驱动设计时,还需要注意以下问题:

  1. 确定系统边界
    我们需要从全局角度来确定系统边界,这里可采用静态和动态两种方法来确定。静态方法是指将系统中所有应用程序所涉及到的元素进行集中管理,以“模块”为单位进行划分。动态方法则是指将整个系统中所有需要考虑的元素进行重新划分,以“对象”为单位进行划分,包括系统中需要考虑到的所有属性和特征。
    确定系统边界有多种方法:
    1. 直接利用 UML图或者用 DDD思维导图来画出整个系统边界
    2. 根据代码来划分。
  2. 定义领域模型
    领域模型是将特定领域中的主要元素和概念映射到一个类中。通过对该领域模型定义,我们能在维护这个领域模型的同时创建出一个更抽象、更易用和更加稳定的领域模型。通常,我们需要在业务模型和概念建模之间进行平衡,确定哪些元素属于概念建模;哪些元素属于业务模型;哪些是对概念建模需要定义或者有一定限制的领域元素。这个过程要确保在领域驱动设计中不会产生不必要的混淆。

你可能感兴趣的:(DDD领域驱动设计,Java,DDD,领域驱动设计,驱动开发,DDD驱动开发,领域模型)