DDD模式

浅谈一下对于DDD模式的理解,相互学习交流,不对之处欢迎大家指正。

在说到DDD(Domain-Driven Design)设计模式之前,先要说下我们在对系统进行架构设时需要遵循的几个原则:

  1. 单一职责(SRP)

    1. "单一职责原则"(Single Responsibility Principle,SRP)是面向对象编程中的一项基本原则,它是SOLID原则中的一部分。单一职责原则的核心思想是:'一个类或模块应该有且仅有一个引起它变化的原因。

      简而言之,这意味着一个类或模块应该只有一个职责,只负责一种类型的任务或功能。如果一个类有多个职责,那么它变得不稳定,难以维护,容易引发错误。

  2. 开闭原则(OCP)

    1. "开闭原则"(Open-Closed Principle,OCP)是面向对象编程中的设计原则之一,它是SOLID原则中的一部分。开闭原则的核心思想是:

      软件实体(类、模块、函数等)应该对扩展开放,对修改关闭。

      这意味着一个软件实体在不修改其源代码的情况下应该能够通过扩展来添加新的功能或行为。换句话说,应该能够通过添加新的类、模块或函数来扩展软件,而不需要修改现有的代码。这有助于保持现有代码的稳定性和可维护性。

  3. 里式替换(LSP)

    1. 里式替换原则(Liskov Substitution Principle,LSP)是面向对象编程中的一个重要原则,它是SOLID原则中的一部分。里式替换原则由计算机科学家Barbara Liskov提出,其核心思想是:

      子类型必须能够替换其基类型(父类型)而不影响程序的正确性。

      这意味着在使用继承的情况下,子类应该能够完全替代父类,而不引发错误或不一致的行为。简单来说,如果一个类是另一个类的子类,那么它应该具有与父类相同的行为,或者说,子类应该继承父类的所有约定和行为。

  4. 接口原则(ISP)

    1. "接口隔离原则"(Interface Segregation Principle,ISP)是SOLID原则中的一项,它关注的是接口的设计和使用。接口隔离原则的核心思想是:

      一个类不应该被强迫依赖它不使用的接口。

      这意味着接口应该足够小,以便客户端只需了解与其相关的方法,而不需要了解不相关的方法。接口隔离原则的目标是避免"胖接口"(Fat Interface)和"依赖过多"的问题,以提高代码的可维护性和灵活性。

  5. 依赖倒置(DIP)

    1. "依赖倒置原则"(Dependency Inversion Principle,DIP)是SOLID原则中的一项,它关注的是依赖关系的管理和解耦。依赖倒置原则的核心思想是:

      高层模块不应该依赖于低层模块。两者都应该依赖于抽象。

      这意味着在软件设计中,应该将高级别模块(例如,业务逻辑或应用程序逻辑)和低级别模块(例如,具体的实现细节或服务)都依赖于抽象接口或抽象类。高层模块和低层模块都应该依赖于共同的抽象,而不是彼此直接依赖。

我们在进行架构设计时说白了就是通过架构设计时软件系统可以使用尽可能少的人力成本去完成用户需求。而DDD模式主要是为了解决系统老化后,各种业务逻辑混杂,导致维护成本大大增加,明明一个很小的功能往往要花费很高的成本。系统设计的目前就是:高内聚、低耦合。

DDD模式首先需要根据业务情况,把系统划分为多个隔离的领域,领域与领域直接是分隔的,我们把这种分隔叫做 "限界上下文"(Bounded Contexts),领域之内应该要完成充分的自治,领域与领域之间需要通过接口层进行交互,接口层可以表现为:http接口、rpc调用、mq消息的定于 等等。每个领域只能处理自己领域内的事情,领域外的事情应该调用别的领域的接口进行处理。例如:我们可以把一个商城中的订单模块设计为订单领域、商品模块设计为商品领域。那么当用于进行下单扣减库存时,订单领域需要调用商品领域的接口完成实现,而不是之间操作商品库存数据。

边界设计好了之后,根据微服务的设计,个人理解我们可以把这一个个领域划分为一个个微服务。那么在这个大领域内我们也需要按DDD4层架构进行设计。DDD中把系统划分了四个层级分别为:用户接口层、应用服务层、领域层、基础设施层。对于我们之前的MVC架构,我理解是在servcie层面进行了跟细致的划分,为了高内聚、低耦合。

用户接口层,也称为表示层,这是与用户交互的界面层,包括用户界面、Web界面、API等。它主要负责用户输入的接收和显示,以及向应用程序传递用户请求。

应用服务层主要是完成对领域服务的组织和编排完成需求的流程和组织。应用层是业务逻辑的主要驱动者,它负责接收来自用户界面层的请求,协调领域层和基础设施层的工作,并执行具体的应用用例(Use Cases)。应用层通常包含应用服务(Application Services)和应用用例(Use Case)。

领域层就是以实体的维度根据业务要求进行业务实现。领域中的实体是充血模型。什么是充血模型了,如果我们有一个订单类,那么这个类里面只有订单各个字段的各个set get方法,我们把他成为贫血模型。如果我们把订单的业务操作也放入到实体里面,例如:订单的生成、订单的更新、订单的删除、订单相关所有的业务操作都放入到这个订单实体中,那么这个订单实体就称为充血模型。当我们同时要操作多个订单实体的能力,如果同时更新两个订单,这么这项业务能力放在实体里面就不合适了,那么我们需要定义一个服务,去同时操作这两个对象,那么对这个服务我们称之为领域服务。领域层是唯一进行业务逻辑实现的层。领域层的能力往往需要通过基础设施层实现,如果一个写库操作,具体的数据库操作会在基础设施层,那么领域层需要依赖基础设施层接口去完成具体的操作。这个接口类称之为仓库:Repository。 领域层内的实体对象创建往往是比较复杂的,往往我们可以通过工厂去灵活的创建实体对象。领域层是DDD的核心,它包含了领域模型、实体、值对象、聚合、仓库、领域服务等,用于表示应用程序的核心业务逻辑。领域层负责处理领域规则、状态管理和业务规则的执行。

基础设施层包括所有与技术和外部资源交互的组件,例如数据库、消息队列、外部服务、文件系统等。它提供了与这些资源进行通信的接口,并为应用程序提供支持,如数据访问、日志记录、安全性等

六边形架构又是啥呢?

六边形架构,也称为端口与适配器架构(Port and Adapter Architecture)或六边形架构模式,是一种软件架构模式,旨在将系统划分为多个不同的层次,并以六边形的形状来表示其结构。这个模式的目标是实现系统的高内聚、低耦合和可测试性,同时使系统更易于扩展和维护。

六边形架构的主要组成部分包括:

  1. 应用层(Application Layer) :应用层是系统的核心,包含了应用程序的业务逻辑和用例(Use Cases)。它负责协调和组织领域层中的领域对象来满足外部请求。
  2. 接口适配器(Interface Adapters) :接口适配器位于系统的外部,与外部世界(用户界面、外部服务、消息队列等)进行交互。接口适配器将外部请求转换为应用层可以理解的形式,并将应用层的响应适配为外部期望的格式。
  3. 端口(Ports) :端口是接口适配器与应用层之间的接口定义,用于定义外部请求如何访问应用层的业务逻辑。端口通常是抽象的,不包含具体实现。
  4. 领域层(Domain Layer) :领域层包含了领域模型、实体、值对象、聚合根、仓库等,用于表示应用程序的核心业务逻辑。领域层负责处理领域规则和业务规则。
  5. 适配器(Adapters) :适配器负责将外部依赖(例如数据库、外部服务、文件系统)适配为应用程序可以使用的形式。适配器包含了与外部依赖交互的具体实现。
  6. 依赖关系:依赖关系通常是从外部适配器指向应用层和领域层,表示外部请求通过适配器进入系统,然后由应用层和领域层处理。

六边形架构模式的核心思想是将核心业务逻辑(领域层)与外部依赖(接口适配器和适配器)分离开来,使系统更易于测试、扩展和维护。这种分离也有助于将外部依赖的变化隔离在适配器中,不会对核心业务逻辑造成影响。

这个模式的名字来源于图形表示,其中中心的应用层和领域层被描绘为六边形的中心,而外部接口和适配器则位于六边形的边缘,形成了一个六边形的形状。这种图形表示有助于清晰地理解架构的结构。六边形架构也与领域驱动设计(DDD)和依赖倒置原则(Dependency Inversion Principle)紧密相关。

六边形和DDD的关系是什么,我理解6变形架构 和 DDD设计模式 有相同之处,叫法不同其核心都是为了 高内聚、低耦合。

端口:DDD中的接口层

Adapters :可以理解为接口层中VO->DTO的转换

应用层:应用服务层

领域层:领域层

适配器:基础设施层

因为DDD模式往往需要较大的人力成本,比较适合核心和复杂的业务。而MVC这种清晰的分层模式往往效率比较高,适合非核心业务。我们在架构设计可以考虑这两种架构结合使用。需要考虑根据业务进行架构设计。技术本身需要适配业务才有其价值。架构的核心就是以最小的人力成本完成业务需要,适合的架构设计 需要考虑 成本 系统老化 人员能力 等各方面因素,不能一概而论。

相关推荐
老肖相当外语大佬2 天前
解决DDD最大难题-如何划分领域
ddd·领域驱动设计·软件设计
rolt7 天前
[pdf,epub]105页《分析模式》漫谈合集01
ddd·架构师·uml·领域驱动设计·分析模式
rolt13 天前
[答疑]是不是互联网更适合用DDD
ddd·领域驱动设计
rolt22 天前
有向无环图的约束怎么表达-《分析模式》漫谈39
ddd·uml·领域驱动设计·面向对象
老肖相当外语大佬2 个月前
反DDD模式之“复用”
开源·实战·ddd·领域驱动设计
xin4972 个月前
领域模型和数据模型还傻傻分不清? 如何实现领域模型
后端·领域驱动设计
老肖相当外语大佬2 个月前
反DDD模式之关系型数据库
ddd·领域驱动设计·关系数据库·三范式
老肖相当外语大佬2 个月前
欢迎加入d3shop,一个DDD实战项目
开源·实战·ddd·领域驱动设计
老肖相当外语大佬2 个月前
图穷匕见-所有反DDD模式都是垃圾
ddd·领域驱动设计
老肖相当外语大佬2 个月前
主观与客观,破除DDD凭经验魔咒
java·ddd·领域驱动设计·dotnet