Go 工程化(十一) 如何优雅的写出 repo 层代码
注:本文已发布超过一年,请注意您所使用工具的相关版本是否适用
注:本文所有示例代码都可以在 blog-code 仓库中找到
本系列为 Go 进阶训练营 笔记,访问 博客: Go进阶训练营, 即可查看当前更新进度,部分文章篇幅较长,使用 PC 大屏浏览体验更佳。
还是以获取一篇文章为例,我们在获取文章的时候大部分时候可能都是通过 id
获取的,但是我们也可能通过标题等其它信息获取文章的数据,这时候我们的 repo 层代码怎么写呢?
最简单的方式,就是我们直接在 repo 这里写两个方法
1 |
|
这样最简单也最直观,但是问题是我们的实际的业务需求往往比我们的例子复杂,如果我们需要通过 id 或者标题获取呢?再添加一个 GetArticleByIDOrTitle
?
这么做的话也不是不行,但是这么做的话就会让我们的 repo 的代码随着时间的增长越来越多不说,命名也是问题,因为组合的方式可能是多种多样的
接下来给大家提供一种我们正在使用的一种思路,利用 Function Options
这种 Go 常见的编程范式,使我们的 repo 更优雅,也可扩展
DBOption
注意: 笔者这里使用的是 GORM,但是这种方式不仅仅适用于 orm 的情况,只是相对方便一点而已
1 |
|
我们定义一个的 DBOption
这个 Option
方法会作为我们 repo 层方法中的最后一个参数,这样我们在定义方法的时候就可以简洁一些,就不必定义很多 GetArticleByXXX
方法了,而是通过定义很多 WithByXXX
的 Option
方法来解决。
这样在 usecase 层,我们只需要这么调用即可
1 |
|
优点
复用: 虽然看上去我们只是把 GetArticleByXXX
换成了 WithByXXX
该有的方法并没有变少,但是我们拆分之后会发现很多可以复用的方法,例如 WithByID
这种几乎是每个实体都会有的方法,我们就不用重复写了。
1 |
|
最小化: 这么修改了之后,拆分组合更加方便了,很多查询条件都可以最小化,例如我们可以添加一个 WithSelects
的方法,我们在 usecase 调用的时候就可以传入当前场景只需要关注的字段就可以了
1 |
|
可测性: repo 层的测试会变得更加方便,这样修改之后我们可以将查询条件拆分出来进行测试,会比之前耦合在一起测试简单很多。
抽象: 这种方式可以让我们抽象 CURD 接口更加方便,在 repo 层实现的时候,我们可以直接把 curd 的方法都给抽象出来
1 |
|
总结
今天给大家介绍了使用 Function Option 的方式来写 repo 层的代码,接下来我们就简单总结一下
1 |
|
优点
- 复用: 虽然看上去我们只是把
GetArticleByXXX
换成了WithByXXX
该有的方法并没有变少,但是我们拆分之后会发现很多可以复用的方法,例如WithByID
这种几乎是每个实体都会有的方法,我们就不用重复写了。 - 最小化: 这么修改了之后,拆分组合更加方便了,很多查询条件都可以最小化,例如我们可以添加一个
WithSelects
的方法,我们在 usecase 调用的时候就可以传入当前场景只需要关注的字段就可以了 - 可测性: repo 层的测试会变得更加方便,这样修改之后我们可以将查询条件拆分出来进行测试,会比之前耦合在一起测试简单很多。
- 抽象: 这种方式可以让我们抽象 CURD 接口更加方便
缺点
- 最大的缺点就是有的问题在单测可能测试不出来了,usecase 的测试中,repo 层被 mock 掉了,repo 在测试的时候大部分我们只会测试当前的方法,所以 usecase 有使用比较复杂的查询语句的时候,repo 测试最好测一测真实的使用场景,不要仅测试单个 Option 方法
今天的文章就到这里,下篇文章给大家介绍一下 API 定义上的一点小技巧
关注我获取更新
猜你喜欢
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议,转载请注明出处,禁止全文转载