系统设计:你的service要用Dependency Injection吗?

当大潮退去,才知道谁在裸泳。
作者:A哥(YourBatman)
公众号:BAT的乌托邦(ID:BAT-utopia)
文末是否有彩蛋:有

前言

各位小伙伴大家好,我是A哥。以下文章来源于硅谷成长攻略 ,作者大西Xi

依赖注入,它不仅仅是Spring,而是一种通用思想。本文硅谷大佬用简短的语句道出了其核心思想,值得参阅。


正文

我最近在给一个Go service升级重构framework。我和一个朋友提了下,他点评到,搞这种基础升级,就是悟道啊,类似于《禅与摩托车维修艺术》。
在这里插入图片描述
他这个说法挺有道理的,大家平时写业务代码,更多是站在地面想着怎么快速完成目标。只有趁升级的时候,才有空飞在1000公里天上,想想为啥要这么设计的哲学问题。

今天就给大家介绍一个重要的基本设计原则:Dependency Injection。这个设计模式在复杂的业务service非常有用,没有它,每次改一个模块的初始化接口,你都要把用到这个模块的代码都改一遍,非常麻烦。

今天很多主流的开源framework都用到了它,比如:

  • Guice: Google 维护的一个基于Java的 lightweight dependency injection framework
  • Fx: Uber 维护的一个基于Go的dependency injection framework
  • AngularJS: Google 维护的基于JavaScript的前端 framework
  • Wire: Google维护的Compile-time Dependency Injection for Go

什么是Dependency Injection?

这个翻译成中文叫做依赖注入,用大白话解释就是即插即用。

举个例子,假设你的service里面有个模块A叫“笔记本”,它有个依赖叫“耳机”,用了这个设计原则,你需要听音乐,只用插”耳机“就可以了。后端service中常见的“耳机”依赖有哪些?比如Logging,输出Metrics等。
在这里插入图片描述
下面的代码是用 Dependency Injection 创建模块A的伪代码:

func CreateLaptopService() *LaptopService {
	panic(wire.Build(
		wire.Struct(new(Logger), "*"),
		NewHttpClient,
		NewHeadphoneService,
	))
}

不用这个原则,有什么后果?

你需要自己搞一堆耳机的原材料,然后自己组装配置。模块A需要耳机的时候,手动装一遍,模块B需要耳机的时候,再手动装一遍。
在这里插入图片描述
下面是不用Dependency Injection,创建模块A的伪代码:

func CreateLaptopService() *LaptopService {
	logger := &Logger{}
	headphone := &Headphone{}
	client := NewHttpClient(logger)
	return NewLaptopService(logger,client,headphone)
}

如果service很简单,还可以忍受。但是在业务很复杂时,项目里有上百个依赖的时候就更痛苦了。每次配置”耳机“,你都需要手动把所有模块的接口配置一遍。
在这里插入图片描述
下面是不用Dependency Injection,再创建模块B的伪代码:

func CreateDesktopService() *DesktopService {
	logger := &Logger{}
	headphone := &Headphone{}
	client := NewHttpClient(logger)
	cdDisk := &CdDisk{}
	cdDrive := &CdDrive{cdDisk}
	headphone := &Headphone{}
	
	return NewLaptopService(logger, client, headphone, cdDrive)
}

优点一:减少依赖关系、方便重复使用

有了Dependency Injection,每次配置时,模块A和模块B都是连接到同一个设置的耳机,你只要组装一次耳机。即使有100个模块都需要用耳机,你也只需要组装一次。
在这里插入图片描述

优点二:提高可维护性

而对于更复杂的场景,模块B依赖于一个”CD机“,而”CD机“又需要一个”CD碟片“。如果有100个类似的模块都有”CD机“,而你需要做的只是更改”CD机”里的CD碟片,有了Dependency Injection,你也可以省去在“电子厂”里面翻找所有”CD机“的时间,只需要换一张”CD碟片“。

优点三:简化测试流程

每次升级时,只需要测试”耳机“本身的性能,测试不需要和使用”耳机“的代码有任何关联。


总结

最后,划一下重点,Dependency Injection适用的场景,是复杂的大型系统,有很多个服务相互依赖的情况。它能够避免一些重复劳动带来的小错误,提高生产力。如果是一个人写的小玩具,那杀鸡就不用牛刀啦。


A哥私人微信

A哥私人微信

A哥私人公众号

A哥私人公众号

展开阅读全文
©️2020 CSDN 皮肤主题: 代码科技 设计师: Amelia_0503 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值