01 介绍
Bob 大叔在他的一篇标题为「整洁架构」的博客中提及,现在一些流行的系统架构,都采用软件分层设计,都主张以下 5 个规则:
- 独立于框架
- 可测试的
- 独立于用户界面
- 独立于数据库
- 独立于任何外部依赖
Bob 大叔的架构设计遵循依赖规则,他画了一张同心圆的图,共分为 4 层,同心圆由内向外依次为 Entities、Use Cases、Interface Adapters 和 Frameworks and Drivers,该规则规定依赖只能是由外向内,内圈不关心外圈,外圈不要影响内圈。
但是,不要认为必须是分为这四层,这里描述的四层只是一个示例,也许你会发现你的业务不仅仅需要这四层,重点是要遵循由外向内的依赖规则。
本文我们介绍整洁架构在 Go 语言中的实践。
02 整洁架构分层设计
参照 Bob 大叔的整洁架构软件分层设计,我们将架构分层分为以下 4 层:
- Models
- Repository
- Usecase
- Delivery
其中,Models 与 Entities 相同,将在所有层中使用,我们可以将所有对象的结构体和方法,以及其他需要在所有层中使用的变量、常量和函数放在 Models 层。这也可以避免遇到循环导入的问题。
Repository 层,我们可以将处理数据库的程序和调用微服务的程序放在该层,仅处理数据输入和输出,不要有其它关于业务逻辑的代码。该层依赖操作的数据库或调用的微服务。
Usecase 层,我们可以将业务逻辑代码放在该层,它负责接收表示层的输入数据,将数据处理之后,调用 Repository 层,将处理后的数据存储在数据库或传递给调用的微服务。反之,将数据库中的数据或调用微服务的返回数据,处理之后,返回给 Delivery 层。该层依赖 Repository 层。
Delivery 层,负责将处理后的数据展示出来,可以采用 RESTful、HTML 或 gRPC 等各种形式。同时,它也负责接收用户输入的数据,将数据传递给 Usecase 层。该层依赖 Usecase 层。
实践应用的目录:
.
├── app
│ └── main.go
├── go.mod
├── go.sum
└── todoList
├── delivery
│ └── http
│ └── todoList.go
├── models
│ └── todoList.go
├── repository
│ └── mysql
│ └── todoList.go
└── usecase
└── todoList.go
03 分层之间通信
分层之间是怎么通信的,除了 Models 层之外,其它层之间通过接口通信,例如 Usecase 层与 Repository 层之间通信,Repository 层定义接口,并实现接口中的所有方法。Usecase 层通过接口与 Repository 层通信。
示例代码:
type TodoListRepository interface {
Create(ctx context.Context, t *Todolist) (err error)
}
同理,Delivery 层与 Usecase 层之间通信,Usecase 层定义接口,并实现接口中的所有方法。Delivery 层通过接口与 Usecase 层通信。
示例代码:
type TodoListUsecase interface {
Create(context.Context, *Todolist) (err error)
}
04 总结
本文我们介绍整洁架构的软件分层设计,并且通过一个简单的 TodoList 项目,在 Go 语言中实践「整洁架构」的架构设计。但是,在 Go 语言中实际上并没有标准的架构设计,我们可以尝试构建自己的标准。
完整代码,请查阅 github。