洋葱模型的Go语言布局
Contents
简介
洋葱模型是近期流行的、业务垂直划分的架构模型。
由于Go语言特有的包依赖特性,在实现洋葱模型时,代码布局和目录结构和其他语言(如C/C++/Java/Python)有所不同。
本文给出了一个用Go语言实现洋葱模型架构的例子,并阐述了这个例子背后的设计原理。
注:本文不涉及Go项目整体布局方案。
太长不看版
一个典型的业务需求是「添加订单」。组网结构如下:
要实现的是中间这个orders模块的「添加订单」功能,包括5个步骤:
- 接受「添加订单」的HTTP请求。
- 解析出请求中的订单信息。
- 判断订单是否合法。
- 将订单持久化到MySQL。
- 返回HTTP响应。
这个模块Go的洋葱模型实现如下(不包含web框架的启动部分)。
|
|
这个实现包含了3个包。
package 路径 | 描述 |
---|---|
orders | orders包定义了订单结构体Order 、核心结构体Service 、保存订单的接口Repo 。Service 实现了函数AddOrder(o *Order) ,这个函数判断订单的合法性,然后调用Repo 的方法SaveOrder 。 |
orders/http/echo | echo包负责从HTTP请求中解析出订单对象orders.Order ,然后调用方法orders.AddOrder 。这个包实现了http服务器框架echo的handler。 |
orders/repo/mysql | mysql包实现了接口orders.Repo ,将订单对象orders.Order 实际写入MySQL数据库。这个包依赖Go-MySQL-Driver以及某个ORM框架(如xorm)。 |
用六边形架构来理解的话,echo就是「输入适配器」,负责在echo框架和orders之间适配;而mysql就是「输出适配器」,负责在orders和mysql-driver以及xorm之间适配。
包之间的实际依赖注入,以及将orders/http/echo/
实现的handler函数注入echo框架,都由外部的代码(如main函数)实现。
具体依赖关系如下图所示:
注意:orders/repo/mysql里的OrderRepo并不直接依赖orders.Repo接口,这是因为Go语言特有的鸭子模型思想,struct只要实现了interface就可以完成接口的实现,而不需要在语言里显式地标明struct和interface之间的关系。
核心思想
要理解这个洋葱模型的实现,需要理解Go语言里包的特性。
- Go一个目录里只能有一个package。
- Go没有「子package」的概念,package和package之间只有直接或间接import的关系。
- 一个目录的package,和该目录下子目录的package,彼此之间完全无关,没有任何依赖或约束。(这一点和Java、Python都不一样)。
由此,就要改变其他语言里「同一层的代码放在同一个目录」的惯性思维,忘记「层」的概念,转化成「以package为唯一代码组织单元」的思想。
package应该自身保证自己在功能上的高内聚;而package所在的目录路径,只不过是用于描述package的功能名称,以减少代码里大量的业务名词。
在设计package的时候要记住:所谓package,就是接收「不明来源、不知何时」的 外部调用,经过内部的逻辑处理,在「业务逻辑规定的时间」用「业务逻辑规定的参数」调用「不知被谁、用什么方式实现了的」包内接口。
(不用读)一个更复杂的orders
下面给出一个稍微复杂一点的orders的布局,除了http输入和mysql输出,还增加了mq输入、redis输出、mq输出,需要查询用户表,还需要通过MQ上报统计结果。
|
|
这个结构可以和DDD的事件总线无缝对接,在输入适配器里添加EventHandler,在输出适配器里添加写EventBusWriter。
总结
这篇文章描述了洋葱模型在Go语言的一种实现方式,并描述了实现背后的思想。在实际工作中,需要根据这些原理,针对具体需求定制布局。
引用
[1] Clean Architecture in Go https://medium.com/@hatajoe/clean-architecture-in-go-4030f11ec1b1 [2] 阿里巴巴Java开发手册 https://github.com/alibaba/p3c [3] Go Microservice with Clean Architecture: Application Design https://medium.com/@jfeng45/ [4] Hexagonal (Ports & Adapters) Architecture https://medium.com/idealo-tech-blog/hexagonal-ports-adapters-architecture-e3617bcf00a0 [5] Duck typing in Go https://medium.com/@matryer/golang-advent-calendar-day-one-duck-typing-a513aaed544d
Author
LastMod 2022-02-24