下面是软件体系结构的基础的摘录,第65页,我正在读:
不稳定性度量决定代码基的波动性。当由于高度耦合而改变时,表现出高度不稳定性的代码库更容易崩溃。例如,如果一个类调用许多其他类来委派工作,则如果一个或多个被调用的方法发生更改,则调用类会显示出很高的崩溃风险。
本章公开了几个度量标准,以帮助架构师理解代码库。
读了这篇文章后,我立即用依赖注入对此进行了交叉检查--据我理解,这是一个设计原则,旨在提供低耦合性和可测试性。
如果这是正确的,DI和不稳定指标不是相互矛盾的吗?DI鼓励将责任委托给依赖项(只要这样做有意义/不会损害凝聚力)--而不稳定似乎不愿意这样做--因为这会使组件更不稳定,因为它更容易崩溃。
我是误解了这个度量,DI,还是两者兼而有之?
发布于 2022-01-08 17:47:29
DI只在运行时使依赖关系显式化和可配置,但它不会改变依赖的数量和种类--至少不会直接改变。
例如,当一个类将持久化委托给一个存储库类,并为此使用5个不同的成员函数调用时,这5个不同的成员函数调用将通过一个接口进行,如果没有DI,它们将直接被硬编码(但仍然是相同的调用,在语法和语义上没有任何差异)。所以DI并没有真正改变这个指标,这两件事只是正交的。
当然,为了使DI成为可能,为了达到像可测试性这样的特定目标,人们可能需要首先重构一个类或组件,将应该成为“可注入”的部分移动到另一个组件中。因此,从这个意义上说,DI促进将代码库重构为更小的组件,并且随着更小的组件,不稳定性度量可能会增加。
然而,这并不是一件“坏事”。如果希望将不稳定性度量降到零,只需将整个大系统的代码放入一个组件中,可能只是一个类(即.a)。“大泥球”)。显然,这是不可取的,而且它表明,仅仅通过查看数字就可以应用这些指标,这很容易导致误导性。
要正确地应用不稳定性度量,需要比较系统的两个版本,然后将其构造成所需的或所需的组件数。然后,这些度量可能有助于在这些组件之间找到更优化的职责分配。然而,这些指标通常无助于通过DI来识别哪些组件应该是“可注入的”。
发布于 2022-01-09 21:33:54
不稳定度量和依赖注入是互补的,而不是对立的。误解来自于认为依赖注入会增加不稳定性。相反,考虑一下为什么首先要引入依赖注入。一个类与其他对象协作的越多,它的依赖性就越大。引入依赖项注入允许您将依赖项的初始化逻辑移到其他地方。大量的依赖增加了不稳定性度量。将参数添加到要使用DI的构造函数或方法中,实际上应该会稍微减少不稳定性度量,因为初始化逻辑已从当前类中移出。
对不稳定性度量的第二个误解是目标是低不稳定性。如果一个类有许多事情要做,那么它只是有许多事情要做,并且依赖于许多其他对象来完成它的工作。一个很高的不稳定性分数只是确定错误可能出现的地方。这是程序员评估风险的工具。当识别出一段高风险代码时,您可以想到允许您管理该风险的技术,而不是消除风险。这就是依赖注入发挥作用的地方。
依赖注入的重构代码使编写单元测试变得更容易。程序员可以在几秒钟内执行数千个单元测试。如果代码更改破坏了某些内容,这会给您提供非常快速的反馈。单元测试也更易于调试,这使得修复bug变得更容易和更快。这就是如何管理代码的风险,代码的不稳定性得分很高。有时,您只是不能使代码不那么容易崩溃。您能做的最好的事情是使打破更改更容易找到、调试和修复。
复杂的协作逻辑会产生很高的不稳定性分数,这可能会促使开发人员将代码转换为依赖项注入,以便编写单元测试。这给开发人员提供了关于代码更改是否破坏了“不稳定”代码的快速反馈。它不会减少代码中断的次数。
发布于 2022-01-08 19:47:54
我想你误解了依赖注入是什么。典型的依赖项注入重构将更改如下
class A {
InterfaceB b;
A() {
b = new BImpl()
}
int doStuff() {
return b.doOtherStuff() * 2;
}
}其中,对BImpl的依赖是在A中硬编码到
class A {
InterfaceB b;
A(InterfaceB b_) {
b = b_;
}
int doStuff() {
return b.doOtherStuff() * 2;
}
}提供依赖关系的地方。注意,在此重构过程中调用的其他类的数量没有变化。
您似乎更多地谈论的是重构一个“上帝类”,其中所有的功能都包含在A中,根本没有委托。虽然这样做是依赖注入的先决条件,但这是一个非常不同的概念。
https://softwareengineering.stackexchange.com/questions/435844
复制相似问题