DI(依赖注入)

DI (Dependency Injection)依赖注入,即将组件的依赖关系外部化,而不是由组件内部创建和管理这些依赖。这样可以提高系统的可测试性可维护性扩展性。

例如,考虑以下 Go 代码,为 UserCache 组件创建一个 Redis 客户端

type UserCache struct {
    client *redis.Client
}
func NewUserCache() *UserCache {
    return &UserCache{redis.NewClient(&redis.Options{
            Addr: "localhost:6379",
    })}
}
func (cache *UserCache) Get(ctx context.Context, id uint64) (domain.User, error) {
    ......
}

这种写法有几个弊病,不管什么东西都要自己内部创建:

  1. 内部创建依赖、耦合性高:
    1. NewUserCache这个方法内部直接创建了redis.Client,意味着它要知道如何初始化redis.Client,在这部分逻辑扩展后,若客户端更换,这段代码更改起来比较麻烦。
  2. 测试困难:
    1. 在进行单元测试时,直接依赖外部服务会带来很多问题。外部服务可能会不稳定、响应慢,甚至在测试环境中不可用,这会导致测试结果不稳定。而在模拟(mock)redis.Client 时,如果它是在 UserCache 内部创建的,就很难替换成一个假的实现,进而难以进行有效的单元测试。

为了解决上述问题,依赖注入(DI)提供了一种更好的设计方式。在依赖注入的模式下,我们可以将 redis.Client 的创建交由外部管理,而 UserCache 只需要接受一个 redis.Client 实例作为参数:

func NewUserCache(client *redis.Client) *UserCache {
    return &UserCache{
        client: client,
    }
}

尽管它已经符合依赖注入,但这种写法仍然存在一些问题。虽然它解决了内部创建的问题,但它仍然依赖于一个具体的 redis 客户端,如果更换客户端是需要更改参数的。对于它,有一种更符合依赖注入的写法

func NewUserCache(client redis.Cmdable) *UserCache {
    return &UserCache{
        client: client,
    }
}

redis.Cmable是 Go 中的一个接口,代表 redis 客户端的行为,是一种抽象,它不依赖于具体的 redis 客户端,因此如果将来更换客户端,只要它实现了该接口,这个构造方法的代码就无需更改,并且在 mock 时,mock工具也可以根据这个接口所定义的行为去模拟一个 redis 客户端。

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
下一篇