Skip to content

Clean Architecure

干净框架,总体上分为

  • 实体层(Entities)
  • 用例层(Use Cases)
  • 接口适配层(Interface Adapters)
  • 框架驱动层(Frameworks & Drivers)

其中,依赖自外向内流动

综述

┌────────────────────────────┐
│ Frameworks & Drivers       │
│ (配置、DB 驱动、HTTP Server) │
└─────────────┬──────────────┘

┌────────────────────────────┐
│ Interface Adapter s        │
│ (Controllers, Repos, DTO)  │
└─────────────┬──────────────┘

┌────────────────────────────┐
│ Use Cases                  │
│ 业务流程 Port 接口和测试      |
└─────────────┬──────────────┘

┌────────────────────────────┐
│ Entities                   │
│ 领域模型 聚合根 规则          │
└────────────────────────────┘

实体层

最内层的层级,包含了领域模型,聚合根和一些其他逻辑。它是最“纯粹”的模块,应当与其他模块和外部依赖无关。 主要 ——

  • 领域实体(核心业务对象):在学生管理系统中定义“学生模型”
  • 值对象(不带身份标识、不可变的小对象):订单管理系统中的”货币“、学生签到的“日期”
  • 聚合根(领域实体和值对象作为一个聚合整体进行管理):订单管理系统中的“仓库”(是若干订单的集合)
  • 领域事件(领域内重要事态的发生):订单生成,订单取消等
  • 领域服务(将跨实体的业务逻辑抽象成无状态服务接口):订单计算优惠(涉及订单和价格等多个实体)
    • 方法签名应只接收所需的实体和值对象
    • 业务规则跨越实体边界,无法在单个实体内部完成校验或流程

用例层

框架中的第二层,用例层把业务流程集中管理 —— 相当于军师指挥军队一样,把这些规则按「谁在什么时候做什么」的顺序串联起来。 同时处理输入输出、事务边界、异常传播等 —— 使用端口+模型定义好“进来”和“出去”的接口,并在中间有序地调度领域实体和服务,实现完整的业务流程

有点抽象,举个创建订单的例子:

  1. 首先在实体层拥有了订单模型等实体
  2. 接着在用例层进行创建订单等具体逻辑的编排——
    1. 调用实体层的接口创建订单实体
    2. 调用实体层的接口进行订单实体的检验
    3. 调用接口适配层中的接口进行订单持久化操作

NOTE

用例层关注的是我们在什么时候做什么,而具体细节不是这个层级需要考虑的事情(仅调用接口)

接口适配层

和其名字一致 —— 作为Clean Architecture的第二外层,负责把将用例层和外部系统进行数据类型或者协议转化

需要实现的东西 ——

  • 数据适配:
    • 将外部请求映射成用例层的请求模型
    • 将用例层返回的类型转化成外部输出格式
  • 接口实现
    • 实现用例层的定义的逻辑接口
    • 沟通具体的”轮子“接口
  • 协议和错误处理
    • 把业务中出现的错误转化成外部可识别错误
    • 适配HTTP状态码等

DANGER

接口适配器只依赖外部框架和用例层的端口接口,而不依赖业务模型的内部细节(依赖倒置原则)

框架驱动层

最外层,组装依赖、初始化基础设施,以及启动应用 —— 比如书写main function

Released under the MIT License.