写点什么

依赖注入是否值得?

  • 2007-12-14
  • 本文字数:1552 字

    阅读完需:约 5 分钟

在博客的世界里进行了一场关于使用依赖注入(DI)之优点和缺点的有趣讨论。论题是:依赖注入是否真的值得?

讨论始自 Jacob Proffitt ,他撰文解释他的观点说,依赖注入的伸缩性不好。据 Proffitt 认为,DI 流行的唯一原因是 Mocking。

DI 进来这么流行的真实原因,和正交性、封装性或者其他“纯粹的”架构考量都没有关系。真正的原因是很多开发者都用 DI 来帮助使用 Mock 对象进行单元测试。随你怎么说,这个因素实际上说服了聪明的开发者选择 DI 而不是更简单的实现。

Proffitt 甚至声称 DI 只对单元测试有好处:

不管怎样,我真的希望人们能够承认 DI 除了单元测试之外,没什么其他有说服力的应用。

不过,Proffitt 虽然做单元测试,却不用 DI。他使用 TypeMock 框架。这个框架可以拦截对依赖对象的调用,哪怕依赖是在被测试代码中创建的。这意味着 Proffitt 不用解耦他的对象也能为单元测试创建 Mock。

Ayende RhinoMocks 的创造者,他在自己的博客上回应说

虽然能够方便地编写 Mock 代码是很棒的特性,但这只是主要利益之外的附带好处,主要的利益是降低了对象间的耦合。我可以修改数据访问部分的代码,而不需要触及负责工资计算的引擎,这是我得到的主要益处。

Nate Kohari 也回答了 Proffitt 的原帖。Kohari 不但给出了一个 DI 的代码示例,还详细阐述了什么是真正的 DI

如果你是 GoF 的爱好者,这其实就是 Strategy 模式。依赖注入(按照我的观点)本质上是大规模使用的 Strategy 模式。

Kohari 是 NInject DI 框架的作者,他强烈反对 DI 框架无用的说法:

一旦你开始倚靠 DI 框架来编写代码,连接对象所需的代价就下降到接近于零。于是,要想达到单一职责的目标,其难度会指数级地下降。

在随后的帖子中,Kohari 重申了使用框架的重要性,以此来回应Proffitt 原先认为 DI 的伸缩性不佳的说法:

在真实世界的使用场景中,手工进行的依赖注入的确伸缩性不佳。

Proffitt 不同意:

你怎么能说依赖注入(我不是针对整个控制反转模式,但也未尝不可。只是还没轮到。)创造了易于复用的松散耦合的单元?DI 本身就要求调用者去提供被调用者的所需。任何理性的评价都会认为这是提高了耦合程度。把耦合的负担丢给框架并不能改变事实,使用一个对象,仍然需要先给它提供外部的东西。

Kohari 解释在大多数情况下,如何创建和注射特定类型的对象只需要配置一次,而且是由框架完成的,不是由调用者。

Kohari 还谈到了代码的变化能力:

……简单来说,依赖注入让你的代码更容易改变。这就是它在敏捷社群中流行的原因,他们的整个软件开发实践都围绕着快速变化。

Eli Lopian 是设计出 TypeMock 的公司的 CTO 也加入争论,他对争论的核心有不同的看法:

当你把 DI 当作是“银弹”来使用,你就丧失了所用编程语言的一大半能力。你不能用静态方法,不能用“new”关键字,不能用封闭类型。哦,你还要把所有的方法都变成虚拟的。

他还争辩说,仅仅为了方便变化而使用 DI,违背了 YAGNI 原则

Lopian 继续说:

TDD 刚兴起时,首先被讨论的一个问题就是“我们是否应该修改代码来满足可测试的要求?”我们应不应该改变代码的可见性?我们应不应该改变代码的设计?这个问题导致了可测试的代码与 OO 封装性之间的冲突。开发者们开始为了能够测试,而把代码中的私有部分暴露出来。开头只是私有方法和属性,现在扩大到了整个设计。

这是一个老问题了。有些人认为改变代码让它更容易测试是一件好事;其他人认为这样做打破了封装性,因此是坏事。

Kohari 对封装与依赖的的关系提出了看法:

这是让依赖注入物有所值的秘密:当谈到依赖的时候,封装是坏的。

如果出于单元测试的意图而改变代码,能让耦合变得更松散(Proffitt 对此有所质疑)——这是不是一件好事呢?

松散耦合与封装都是重要的 OO 特征,那我们如何作出平衡呢?哪条路才是对的?

查看英文原文: Does Dependency Injection pay off?

2007-12-14 04:204720
用户头像

发布了 225 篇内容, 共 71.7 次阅读, 收获喜欢 52 次。

关注

评论

发布
暂无评论
发现更多内容

“5G+区块链”护航新生儿转诊“生命通道”

CECBC

元宇宙,以区块链为核心的Web3.0数字生态

CECBC

【量化】量化交易入门系列5:量化交易学习书籍推荐(一)

恒生LIGHT云社区

金融科技 量化策略 量化投资 量化交易 量化

激发数字化时代权益运营新动能

鲸品堂

运营 数字化 通信运营商

x86架构应用如何向Arm架构低成本迁移

北京好雨科技有限公司

MongoDB find getmore操作慢问题排查

MongoDB中文社区

mongodb

聊聊Netty那些事儿之从内核角度看IO模型

bin的技术小屋

Netty nio Linux Kenel Linux网络编程 #java

Avaya大中华区CTO李农:阿里云计算巢加快Avaya应用云部署

阿里云弹性计算

弹性计算 年度峰会 计算巢

Sql server之sql注入篇

喀拉峻

网络安全 信息安全 SQL注入

Web or Native 谁才是元宇宙的未来(上)?

Orillusion

开源 WebGL 元宇宙 Metaverse webgpu

一篇域名从购买到备案到解析的详细教程

冴羽

前端 vuepress 域名解析 域名 域名备案

便捷、高效、智能—从运维视角看星环科技大数据基础平台TDH

星环科技

大数据

【量化投资入门】带你通过恒有数数据接口来实战量化指标

恒生LIGHT云社区

量化策略 量化投资 量化交易 量化

文末有惊喜| 青藤ATT&CK论文入选国家级期刊

青藤云安全

设计电商秒杀系统

奔奔

反直觉投资--《香帅中国财富报告》摘录(4/100)

hackstoic

投资

Hoo虎符研究院 | 币海寻珠——波卡平行链Moonbeam生态一览

区块链前沿News

虎符交易所 波卡

政法委社会治安防控平台建设,重点人员联防联控系统开发

a13823115807

CODING 携手 Thoughtworks 助力老百姓大药房打造“自治、自决、自动”的敏捷文化

CODING DevOps

敏捷 thoughtworks CODING 项目协同 老百姓大药房

Golang:定时器的终止与重置

CRMEB

基于javaweb,springboot银行管理系统

叫练

银行 毕业设计 计算机毕业设计

sql审核-避免离线sql导致的db集群故障

名白

sql db sql检测 SQL审核 SQL审批

如何保证redis与数据库一致性

zdd

redis

如何帮助金融客户“用好云”?

金融 混合云 数智化

Sophon联邦学习,让数据发挥真正的价值

星环科技

联邦学习

Go 分布式令牌桶限流 + 兜底策略

万俊峰Kevin

Go 微服务 限流 Go 语言 令牌桶

TDengine在中节能风力发电运维系统中的落地实践

TDengine

数据库 大数据 tdengine 物联网

multi-key索引和wildCard索引场景比较

MongoDB中文社区

mongodb

netty系列之:让TCP连接快一点,再快一点

程序那些事

Java Netty 程序那些事 1月月更

12 Prometheus之监控Kubernetes

穿过生命散发芬芳

Prometheus 1月月更

Web3:创作者经济的黄金时代

CECBC

依赖注入是否值得?_.NET_Niclas Nilsson_InfoQ精选文章