《领域驱动设计》

领域驱动设计(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 我们大佬在实现新约束时就支持了两者并行🤩

屈楚萧