领域驱动设计(Domain Driven Design,简称 DDD)是一种软件设计和开发方法论,旨在通过深入理解和建模业务领域,将业务知识和业务逻辑贯穿于整个系统的设计和开发过程中
最近 5 年越来越🔥,很多公司都把它作为解决复杂业务的良药。由于 DDD 不是一套框架,而是一种架构思想,所以在代码层面缺乏了足够的约束,导致 DDD 在实际应用中上手门槛很高。
对于前期的准备工作来说,你需要把公司的各业务域划分清楚,并且知道什么是公司的核心域。
在上篇文章末尾有咱公司的划分,涉及我的就是供应链、零售、信息化等域
网上关于 DDD 的资料基本都是 Java 栈的,确实对于 PHP 这个脚本语言来说,你想搞 DDD 还不如直接换语言实现来的快。但是咱公司技术确实 niubility,在自己的框架基础上实现了一套 DDD 约束。
Entity 领域实体作为核心内容,拥有着唯一标识(例如主键的值对象)和可变的内容。类似于 Laravel 中模型的关联关系,咱也实现了实体的关联关系,可以通过定义方法来实现实体间、实体与值对象间的一对一、一对多、多对多等。
Entity 和 VO(Value Object)的区别在于是否存在生命周期。
Persistence 持久化层,就是与数据库交互的位置。每个 PO 像 MVC 的 Model 一样映射了一张表,并且应该实现 2 个方法,一个是 PO 向实体进行转换,一个是让实体转换成本 PO。Repository 还是和其它规范一样,作为查询封装。
Cmd 入参规范定义,实现了数据校验与便捷的传递。Translator 对象转换,用于复杂的出入参处理。
DTO 数据传输对象 (Data Transfer Object),就是接口最终返回出去的规范。PHP 也一样可以通过类型约束、Annotation 注解来实现和 Java 一样的效果。
最终结构如下:
├── app
│ ├── Application 应用层
│ ├── Domain 领域层
│ │ └── AnonymousMail 领域名称
│ │ ├── Exception 领域异常
│ │ ├── Model 领域模型
│ │ │ ├── Entity 领域实体
│ │ │ │ └── Relationship 领域关联关系
│ │ │ ├── Repository 领域仓储接口
│ │ │ └── VO 领域值对象
│ │ ├── Setting 领域配置
│ │ ├── Service 领域服务
│ │ ├── Factory 领域工厂
│ │ └── Enum 领域枚举
│ ├── Infrastructure 基础设施层
│ │ ├── Bridge 外部依赖服务(Rpc/第三方服务)
│ │ │ └── Notify 服务名称
│ │ │ └── Cmd 传入参数
│ │ ├── Console(Laravel Console)
│ │ ├── Exceptions 基础异常类
│ │ ├── Persistence 持久化层
│ │ │ ├── PO 持久化对象
│ │ │ └── Repository 仓储实现
│ │ ├── Setting 基础配置
│ │ └── Providers(Laravel 服务提供者)
│ └── Interfaces 接口层
│ └── AnonymousMail 领域名称
│ ├── Cmd 传入参数
│ ├── Controllers 接口类
│ ├── DTO 响应对象
│ └── Translator 传入/响应 对象转换类
作为第一个吃螃蟹的,我用这套设计完成了一个迭代的新系统。在开发的前期由于刚走出舒适区,无论是设计还是实现,都需要花费 4 倍于之前的时间。经过一两个领域中的基础接口实现后,这个倍数大概会降到 2。
以老项目来实现时,需要考虑两个底层同时存在的情况
But 我们大佬在实现新约束时就支持了两者并行🤩
- 领域(Domain):指业务领域,包括业务的核心概念、规则和业务流程。领域是领域驱动设计的核心,我们需要深入理解业务领域,与业务专家进行合作,以便将领域知识融入系统设计中。
- 领域模型(Domain Model):领域模型是对业务领域的抽象和映射。它由领域对象(Domain Objects)和领域之间的关系组成,反映了业务概念、行为和规则。领域模型是领域驱动设计的核心成果之一,它帮助我们理解和描述业务需求,指导系统的设计和开发。
- 聚合(Aggregate):聚合是一组相关的领域对象的集合,它们一起形成一个有内聚性的单元。聚合定义了内部的一致性边界和一些约束规则,封装了领域对象的状态和行为。聚合是领域模型中的重要组织单位,通过聚合根(Aggregate Root)来访问和管理聚合内的对象。
- 实体(Entity):实体是具有唯一标识的领域对象,它有自己的生命周期和状态。实体通常具有可变的属性和行为,可以通过标识来唯一地区分和识别。
- 值对象(Value Object):值对象是没有唯一标识的领域对象,它们通过其属性来定义和区分。值对象通常是不可变的,它们的相等性通过属性的值来判断,而不是通过标识。
- 聚合根(Aggregate Root):聚合根是聚合中的一个特殊实体,作为聚合的入口点。它负责保护聚合内的一致性和约束规则,并与外部系统进行交互。通过聚合根,我们可以管理聚合内的对象,保持聚合的完整性。
- 领域事件(Domain Event):领域事件表示在业务领域中发生的有意义的事情。它们可以用来记录和通知系统中其他部分的状态变化,促进领域模型的协作和反应。领域事件有助于解耦和异步处理领域逻辑。
- 限界上下文(Bounded Context):限界上下文是领域驱动设计中的一个关键概念,它定义了在系统中的一个特定领域范围内的边界。每个限界上下文都有自己的领域模型、语言和规则。限界上下文之间通过明确定义的接口进行交互,帮助团队在大型系统中分解和组织领域模型。