如何编写易于测试的package

it2024-08-03  41

隔离db和rpc

《架构整洁之道》里面说了,对于db, rpc等外部访问,必须进行隔离,业务代码不能与具体的db和rpc交互,应该把db和rpc的stub抽象成interface,这样便于替换db和rpc,使用interface也便于unit test

设计模式

即便是对外部的访问抽象成了interface,比如rpc client,但是对于业务来说使用起来也是不方便的,比如这个client提供了很多复杂的接口,而业务使用的只是其中的一个子集,并且业务可能还需要加入鉴权限流等逻辑,于是需要把外部的interface 接口包装成业务需要的interface。业务代码作为使用方,应该最大程度的简化对外部的访问,从而专注于自身的逻辑

1, 依赖反转。 由业务代码定义对外访问的数据结构和接口,由dao/services来实现具体的逻辑

2,decorator/adaptor/facade 模式 dao/services package的输入是rpc/db client 的interface,输出是一个满足业务接口的对象

3,main组件 由main package负责初始化db/rpc的client,传递给dao/services接口,再将结果传递给业务package。并且在服务结束以后负责销毁这些client和对应的资源。main组件对db和rpc的初始化最好不要再做成package了,直接写在main package里面,对于程序的依赖一目了然。

例外

对于rpc, redis,kafka, mongodb。。。等等,一旦初始化以后他们的client都是一个interface, 但是rdb是个例外,它初始化之后的client是一个sql.DB,所以rdb的dao输入应该是sql.DB而不是interface,好在也有成熟的单测mock方法:sqlmock。具体参见:https://pkg.go.dev/github.com/DATA-DOG/go-sqlmock. 另外,对于性能要求高或者where查询不复杂或者需要连表复杂查询的时候,不要使用orm(gorm)

最新回复(0)