资格校验接口的微服务设计与实现
资格服务的三层架构
由于在本接口中需要实现多种规则的校验工作,并结合实际需求,最终的代码设计遵循简洁架构设计,划分为如下几层:控制层(Controller)、业务层(Biz/Service)、存储层(Store)。 其中,从 Controller、Service 到 Store 的层级依次逐渐加深,具体代码架构如下图所示:
层与层之间导入包时,都有严格的导入关系,可以有效防止包的循环导入问题,即 Controller 能够导入 Service 的和 Store 的包。 但需要注意的是,如若没有特殊需求,Controller 要避免直接导入 Store 层的包,而是其业务功能都由 Sercive 层完成。
控制层(Controller)
Controller 负责接收 HTTP 请求,并进行参数的解析与校验、逻辑的分发处理、请求返回等操作。 Controller 将逻辑分发给 Service,Service 处理后返回,返回数据在 Controller 中被整合加工,最终返回给请求方,即实现了业务路由的功能。
业务层(Biz/Service)
Service,主要用来完成业务逻辑处理,可以把所有的业务逻辑代码放在本层。 Service 会处理来自 Controller 的请求,并根据需要请求 Store 完成数据的 CURD 操作。
存储层(Store)
Store,用来跟数据库/第三方服务进行 CRUD 交互,作为应用程序的数据引擎进行数据的输入与输出。 需要注意的是,Store 仅对数据库/第三方服务执行 CRUD 操作,不封装任何业务逻辑。
Store 同时也起到数据转换的作用:
- 将数据库/微服务中获取到的数据转换为 Controller、Service 能识别的数据结构;
- 将 Controller、Service 的数据格式转换为数据库或微服务能识别的数据格式。
层间交互
Controller、Service、Store 各层之间都是通过接口进行通信,如此,可使得相同的功能支持不同的实现(即插件化能力),同时也使得每一层的代码变得可测试。
-
Controller 依赖于 Service 层,意味着该层需要 Service 层来支持测试,此时可以通过
golang/mock
来 mock Service。 -
Service 依赖于 Store 层,意味着该层需要 Store 层来支持测试,此时可以通过
golang/mock
来 mock Store。 -
Store 依赖于数据库,如果调用了其他微服务,则还依赖于第三方服务,此时可以通过 sqlmock 来模拟数据库连接,通过 httpmock 来模拟 HTTP 请求。
资格服务代码设计
在了解本资格服务三层架构之后,我们就可以开始设计代码了。
由于在本接口中需要实现多种资格的校验工作,并结合实际需求,最终在 Service 层采用工厂方法设计模式,相关类图如下:
从图中明显可以看到,Server
接口定义了该服务所支持的功能,实现了接口就是规范的功能。
另外在 Server
的实现类 DjcRuleService
中持有 rule.Ruler
接口的引用,
该接口定义了 Ckeck
方法,rule.Ruler
接口的实现类(例如,DJCFFriendsRule
、DJCfmVipRule
)会实现 Ckeck
方法,从而实现规则的校验。
在 Controller 层中,我们定义了如下的代码结构:
它不仅持有 services.Servicer
接口,而且实现了 POST
/HEAD
/GET
等 HTTP 方法,实现了 HTTP 请求的响应、参数的解析与校验、Service 层业务逻辑的调用等操作。
整个软件体系采用了分层架构,即分为 controllers
、services
以及 rule
三个 Package,其中每一个 Packge 都采用了面向 interface
的编程范式。