在 2025 收官前,看清 Data + AI 的真实走向,点击查看 BUILD 大会精华版 了解详情
写点什么

依赖注入是否值得?

  • 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:204892
用户头像

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

关注

评论

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

CAD图纸如何批量打印?CAD批量打印教程来了

在路上

cad cad看图 CAD看图王

数据交换机案例详解|基于smardaten实现智慧园区数据处理与分析

数睿数据

智慧园区 smardaten 数睿数据

总奖金超40万!高德空间智能开发者大赛开启报名和作品提交通道

高德开放平台

低代码助力企业协同办公:不止降本增效,更是增长新引擎!

天津汇柏科技有限公司

AI智能体 - 目标设定与监控模式

Hernon AI

AI开发 AI智能体 AI开发框架 AI设计模式

转卖分佣商城小程序系统:一站式移动营销解决方案

微擎应用市场

「开发者扶持计划」正式上线,MemOS 云平台全面免费!

记忆张量MemTensor

MemOS 记忆管理 记忆张量

鸿蒙手机打开开发者模式

lichong951

HarmonyOS HarmonyOS NEXT

当销售额下降时,ChatBI 如何实现多维下钻、归因分析?

Aloudata

数据分析 归因分析 ChatBI 智能问数 dataagent

SSL证书申请与安装全攻略:关键注意事项深度解析

防火墙后吃泡面

海外网红营销服务公司评估指南:5大维度筛选优质合作伙伴

Wolink

出海 海外社媒营销 海外营销推广 海外红人营销 品牌推广

品牌出海战略解码:从中国品牌到全球品牌的进化路径

Wolink

跨境电商 品牌营销 出海企业 品牌出海 品牌推广

海外平台推广算法解读:如何让平台算法为你精准推送流量

Wolink

跨境电商 海外社媒营销 海外营销推广 海外推广 海外红人营销

AI 智能体 - 学习与适应能力

Hernon AI

AI智能体 AI开发框架 AI开发方法论 AI设计模式

通往可信数据智能的路线图,就在这本《NoETL to Trusted AI》白皮书

Aloudata

数据分析 AIAgent noetl ChatBI 智能问数

校二叔校园外卖社区小程序系统 :一站式校园生态解决方案

微擎应用市场

《独立开发者精选工具》第 023 期

Immerse

蚂蚁数科跻身中国AI智能体开发平台“领导者”阵营

Lily

人大 DeepAnalyze 免费体验通道开启!上传数据,坐等报告!

ModelWhale

人工智能 数据分析 大模型 DeepAnalyze

骁龙大赛技术分享第4期来了——直播问题&答疑整理

极市平台

星畅家政小程序系统:一站式家政服务数字化解决方案

微擎应用市场

harmonyos 大屏设备怎么弹出 u 盘

lichong951

区域市场深度渗透:东南亚海外网红推广的本地化实战策略

Wolink

跨境贸易 出海 海外营销推广 品牌出海 海外红人营销

创新服务模式探索:海外网红营销服务公司的转型升级趋势

Wolink

跨境电商 电商营销 海外社媒营销 海外营销推广 海外红人营销

光伏策略控制服务器是什么?核心功能与系统定位详解

西格电力

分布式光伏并网 分布式光伏发电 分布式光伏 分布式光伏产品 光伏策略控制服务器

品牌出海组织变革:构建支持全球化业务的敏捷团队架构

Wolink

跨境电商 出海企业 品牌出海 海外红人营销 品牌推广

RelativeLayout 根布局里有一个子布局预期一直展示,但子布局RelativeLayout被 覆盖了

lichong951

android Android Studio

Agent如何重塑跨角色协作的AI提效新范式

Comate编码助手

AI 编程 文心快码 编程智能体

案例宝公众号管理系统:全行业客户案例管理神器,高效转化成交好帮手

微擎应用市场

如何运用 Scrum 打造一个高绩效的团队

ShineScrum

Scrum 高绩效团队

CAD图纸闪退、打不开?快来试试CAD图纸清理?

在路上

cad cad看图 CAD看图王

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