learn go with tests 学习笔记(四)依赖注入
知识点
依赖注入举例
首先我们应该明白什么是控制反转 -> 控制反转(IoC)与依赖注入(DI)
控制反转的目的很简单,即”解耦“
下面用一个打印示例来说明:
那么我们该如何测试它呢?调用 fmt.Printf 会打印到标准输出,用测试框架来捕获它会非常困难。
我们所需要做的就是注入(这只是一个等同于「传入」的好听的词)打印的依赖。
我们的函数不需要关心在哪里打印,以及如何打印,所以我们应该接收一个接口,而非一个具体的类型。
如果我们这样做的话,就可以通过改变接口的实现,控制打印的内容,于是就能测试它了。在实际情况中,你可以注入一些写入标准输出的内容。
如果你看看 fmt.Printf 的源码,你可以发现一种引入(hook in)的方式:
有意思!在 Printf 内部,只是传入 os.Stdout,并调用了 Fprintf。
os.Stdout 究竟是什么?Fprintf 期望第一个参数传递过来什么?
io.Writer 是:
如果你写过很多 Go 代码的话,你会发现这个接口出现的频率很高,因为 io.Writer 是一个很好的通用接口,用于「将数据放在某个地方」。
所以我们知道了,在幕后我们其实是用 Writer 来把问候发送到某处。我们现在来使用这个抽象,让我们的代码可以测试,并且重用性更好。
依赖注入的作用
测试代码。如果你不能很轻松地测试函数,这通常是因为有依赖硬链接到了函数或全局状态。例如,如果某个服务层使用了全局的数据库连接池,这通常难以测试,并且运行速度会很慢。DI 提倡你注入一个数据库依赖(通过接口),然后就可以在测试中控制你的模拟数据了。
关注点分离,解耦了数据到达的地方和如何产生数据。如果你感觉一个方法 / 函数负责太多功能了(生成数据并且写入一个数据库?处理 HTTP 请求并且处理业务级别的逻辑),那么你可能就需要 DI 这个工具了。
在不同环境下重用代码。我们的代码所处的第一个「新」环境就是在内部进行测试。但是随后,如果其他人想要用你的代码尝试点新东西,他们只要注入他们自己的依赖就可以了。
引用
版权声明: 本文为 InfoQ 作者【半亩房顶】的原创文章。
原文链接:【http://xie.infoq.cn/article/a0be9b811702f6b1bc2a5410c】。
本文遵守【CC BY-NC】协议,转载请保留原文出处及本版权声明。
评论