困惑于SOLID和Dependecy Injection

MrC*_*arp 5 .net c# dependency-injection inversion-of-control solid-principles

所以我想学习SOLID原理和依赖注入.我已经阅读了一些关于这个主题的博客文章,我开始明白了一点.但是,有一种情况我无法找到答案,并会尝试在此解释.

我已经开发了一个用于文本匹配的库,它包含一个Matcher具有调用函数的类,该函数Match将结果返回给MatchResult对象.此对象包含百分比,已用时间,是否成功等信息.现在从我在依赖注入中理解的是,高级别的类不应该"知道"关于低级别的类或模块.所以我已经设置了我的库和Matcher类来使用类的接口Matcher,这将允许我使用IoC容器注册它.但是,因为该函数返回一个MatchResult对象,所以"高级类"必须知道MatchResult违反DI规则的对象.

我该如何解决这个问题,建议的方法是什么?

Ale*_*scu 7

DI声明使用接口的类不应该知道有关具体实现的任何细节.但是,这MatchResult不是一个实现细节,而是接口契约的一部分(DTO,方法的返回类型Match) - 这没关系.您可以有一个额外的类以不同的方式实现该IMatcher接口,但它应该仍然返回一个MatchResult,就像它预期的那样.

  • 您总是可以添加一个`IMatchResult`来使合同更加通用,而不是将用户绑定到实现 (2认同)

Sco*_*nen 4

“高级”和“低级”是与依赖倒置相关的术语,它与依赖注入相关,但是不同的概念。它们都有首字母“DI”,并且两者中的“D”都代表“依赖”,因此它们可能会造成一些混乱。

\n\n

(我是这样想的——依赖注入是实现依赖倒置的一种方法。)

\n\n

但在我看来,定义依赖倒置时使用的术语对于试图理解该概念的 .NET 程序员来说确实令人困惑。它是适用的,但某些术语在 .NET 开发人员中并不使用。

\n\n

根据维基百科引用的罗伯特·马丁的定义,

\n\n
\n

高层模块不应该依赖于低层模块。两者都应该依赖于抽象。抽象不应该依赖于细节。细节应取决于抽象。

\n
\n\n

什么是“高级模块”和“低级模块”?如果您觉得这令人困惑,那么您并不孤单。我们并不真正使用这些术语。我们真正能够理解和应用的部分是我们应该依赖于抽象

\n\n

就 而言MatchResult,如果它只是一些属性的容器,那么它可能就足够抽象了。一段时间以来,DTO 一直是一种常见的做法,因此,如果时间表明我们需要将它们包装在接口中,那么这种模式现在就会出现。它不会造成伤害,但通常没有必要。

\n\n

回到依赖倒置——真正的混乱来自于名称本身。什么叫颠倒?当您看到类似于维基百科页面上的图表时,我的建议是不要看那些令人眼花缭乱的图表。

\n\n

马丁这样解释了他对“反转”一词的使用(回到他关于该主题的原始论文)

\n\n
\n

有人可能会问为什么我使用 \xe2\x80\x9cinversion\xe2\x80\x9d 这个词。坦率地说,这是因为更传统的软件开发方法,例如结构化分析和设计,倾向于 创建高层模块依赖于低层模块、抽象依赖于细节的软件结构。实际上,这些方法的目标之一是定义描述高级模块如何调用低级模块的子程序层次结构。图 1 是此类层次结构的一个很好的示例。因此,设计良好的面向对象程序的依赖结构相对于通常由传统过程方法产生的依赖结构来说是\xe2\x80\x9c\xe2\x80\x9d。

\n
\n\n

换句话说,倒置是应用依赖倒置与应用依赖倒置的“传统”风格之间的对比。如果您来自“高级模块依赖于低级模块”的背景(并且您使用术语“模块”),那么这可能会更清楚。但如果这不是您以前的“传统” ” 那么你在“反转什么?”什么也没有。

\n\n

所有这些细节仍然有意义,但是当您第一次尝试学习这些概念时,它们会非常令人困惑。我的建议是应用这一部分,就像您已经做的那样:依赖于抽象。

\n\n

如果你这样做,那么你就应用了这个原则,因为无论“高级模块”和“低级模块”是什么,你的类都不会太依赖于其他类 - 高级、低级、或其他方式。

\n