问题标签 [dependency-inversion]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
1 回答
174 浏览

python - 对象如何在不违反依赖倒置原则的情况下进行通信?

我正在构建一个路径规划器,它将帮助人们通过 RPG 控制台游戏规划路径。

我想创建一个表格来显示整个阶段的每个步骤。我实际上已经实现了这个的工作版本,但是,它似乎是糟糕的 OOP 设计;它违反了各种原则,我认为它甚至不是合法的 OOP。问题是,很明显,那Table是神级。

因此,我决定重写它,同时尝试牢记正确的 OOP 原则。我想Table分成多个班级。

我的问题是我需要各种对象相互交谈。但是,我的解决方案是始终使用composition。这打破了依赖原则以及单一责任原则。

这是存储玩家步数的主表:

现在,我创建了一个InputManager负责接受和验证用户输入的函数:

但是,现在我不知道如何访问PathTable._table[position]. 在不打破各种OO设计原则的情况下。

这很令人沮丧,因为整个工作InputManager就是访问PathTable. 但是我不能用构图放在InputManager里面PathTable,因为它是糟糕的设计。

什么是完成此任务的干净方法?

我是初学者,我正在努力学习。

0 投票
2 回答
1483 浏览

java - 依赖倒置原则(适用于 Java)

我正在自学 SOLID 面向对象编程中涉及的原则,并且无法理解字母 D 中的所有细节(依赖倒置原则。)

我正在阅读它在 Wikipedia ( http://en.wikipedia.org/wiki/Dependency_inversion_principle ) 中的条目,但我不理解图中的所有内容:

http://en.wikipedia.org/wiki/Dependency_inversion_principle#/media/File:DIPLayersPattern_v2.png

我注意到有两种不同类型的箭头——一种是虚线的,一种是实心的。

根据我目前的理解,虚线代表Java中“implements”关键字的等价物,实线代表关键字“extends”。

这是正确的解释吗?

0 投票
2 回答
439 浏览

solid-principles - 跨模块使用依赖倒置原则的正确设计?

我理解在单个模块中工作时的依赖倒置,但是当我有跨模块依赖时我也想应用它。在下图中,我有一个现有的应用程序,我需要为参考数据服务实现一些新要求。我想我会创建一个新的 jar(将来可能是一个独立的服务)。第一个图显示了我过去处理此类事情的正常方式。referencedataservices jar 有一个接口,应用程序将使用该接口调用它。

第二个图显示了我尝试使用 DIP,应用程序现在拥有它的抽象,因此它不会因为参考数据服务发生变化而发生变化。这似乎是一个错误的设计,因为它创建了一个循环依赖。MyApp 依赖于referencedataservices jar,referencedataservices jar 依赖于MyApp。

所以第三个图通过创建一个额外的抽象层回到了更正常的依赖关系。我对吗?或者这真的不是 DIP 的目的吗?有兴趣了解其他方法或建议。

,依赖倒置图

0 投票
0 回答
939 浏览

spring - 使用 Maven 和 Spring 实现依赖倒置原理

根据这篇维基百科文章:实现依赖倒置原则可以通过两种方式完成:

  • 在单独的包中对低级组件进行抽象,高级和低级组件都依赖于该包。
  • 使低级组件的抽象驻留在高级组件的同一个包中。

下图描述了使用两种方法进行 DIP 之前和之后的依赖关系:

DIP 之前: repository 驻留在单独的 maven 模块中,没有接口,服务直接依赖 Repository 实现。 DIP 之前的依赖关系

方法一:引入存储库的接口(抽象)。该接口的实现是另一个模块,服务和存储库实现都直接依赖于该接口。 DIP 实施方法 1

方法 2:在这种方法中,接口驻留在服务的同一个包中。Fowler 用来描述分离接口模式的图表似乎也是这种方法的一个例子。 DIP 实施方法 1

我一直在关注Approach1,因为我使用了 spring 的 JavaConfig,所以服务模块必须对基础设施接口和实现模块都有 maven 依赖。除了我的@Configuration文件,绝对没有提到任何基础设施的具体实现。

我目前正在考虑切换到Approach2,但显然它不适用于 JavaConfig,因为我最终会在代码中直接引用接口实现模块,从而导致循环依赖,这是 maven 等构建工具无法处理的.

问题是如何配置spring和maven来实现Approach2?有没有办法让 spring扫描未添加为 maven 依赖项的组件?这需要改变我使用 Maven 的方式吗?

0 投票
2 回答
2229 浏览

r - R6 类的多重继承

实际问题

对于R6不支持多重继承这一事实,我有什么选择?

免责声明

我知道 R 主要是一种函数式语言。但是,它也确实内置了非常强大的面向对象。另外:我看不出模仿 OOD 原则/行为有什么问题

  1. 知道您正在为 C#、Java 等面向对象的语言进行原型设计。

  2. 您的应用程序原型需要自给自足(“全栈”,包括数据库后端、业务逻辑和前端/UI)

  3. 您拥有像 R6 这样出色的“原型制作技术”,并且可以随意使用

语境

我的 Web 应用程序R原型需要“全栈”/自给自足,尽可能接近我们的生产语言 (C#/.网)。

在这方面,我非常喜欢使用接口(或抽象类)来解耦代码模块并遵守OOD的SOLID原则的D依赖倒置原则)(“鲍伯叔叔”的详细解释) )。

尽管 R6 没有明确支持接口,但我仍然可以使用 R6 类完美地模仿它们,这些类只定义“抽象方法”(参见下面的示例)。这有助于我我的软件设计传达给我们对 R 不太熟悉的 OO 程序员。我力求他们尽可能少地进行“概念转换工作”。

但是,当我实际上想从其他具体(而不是“类抽象”模仿的接口类)继承时,我需要放弃我的价值,inherit因为这意味着不定义一个但在.R6Classinherit

例子

依赖反转之前:

Foo取决于具体类Bar。从 OOD 原则的角度来看,这非常糟糕,因为它会导致代码紧密耦合。

依赖反转后:

Foo并且Bar现在解耦了。两者都依赖于由 class 模仿的接口IBar。我可以决定我想在运行时将该接口的哪个实现Foo插入到实例中(通过属性注入实现:字段barFoo

为什么这对 OOD 有意义:Foo应该完全不知道存储在字段中的对象bar实现方式。它只需要知道它可以在该对象上调用哪些方法。为了知道这一点,知道字段中的对象实现的接口就足够了(在我们的例子中是方法)。barIBardoSomething()

使用从基类继承来简化设计:

到目前为止,一切都很好。但是,我还想通过定义某些我的其他具体类可以继承的具体基类来简化我的设计。

结合“接口实现”和基类继承:

这是我需要多重继承的地方,所以这样的东西可以工作(伪代码):

目前,我的价值inherit已经被“仅仅”用于模仿接口实现,因此我失去了继承对于我的实际具体类的“实际”好处。

另类的想法:

或者,以某种方式显式支持接口具体类之间的区别会很棒。例如像这样

0 投票
2 回答
106 浏览

oop - 具体实现是否应该提供其实现的接口中不存在的任何公共 API?

代码到接口”被认为是好的做法。这样的代码易于进行单元测试并支持松散耦合。用户只知道接口,连接具体对象的责任在最顶层(这可以在一些初始化代码或框架的帮助下完成)。

我的问题是关于遵循代码到接口的做法:这是否意味着具体类永远不能声明其接口中不存在的任何公共方法?

否则,它将迫使用户依赖具体的实现。这将使此类方法难以进行单元测试;如果测试失败,确定它是由于调用者代码中的问题还是由于具体方法而失败将需要额外的努力。这也将打破依赖倒置原则。它将导致类型检查和向下转换,这被认为是不好的做法。

0 投票
2 回答
377 浏览

c# - 这是对 DIP (SOLID) 的有效使用吗?

我想问一下类的实现是否Genotypes违反Individual了依赖倒置原则?如果是这样,如何解决?

类抽象层次

这是代码:

0 投票
2 回答
1957 浏览

javascript - 节点中的 Javascript 依赖注入和 DIP:需要与构造函数注入

我是来自 .NET 世界的 NodeJs 开发新手,我正在网上搜索在 Javascript 中重新分级 DI / DIP 的最佳实践

在 .NET 中,我会在构造函数中声明我的依赖项,而在 javascript 中,我看到一个常见的模式是通过 require 语句在模块级别声明依赖项。

对我来说,当我使用 require 时,我看起来像耦合到特定文件,而使用构造函数来接收我的依赖项更加灵活。

作为 javascript 的最佳实践,你会推荐什么?(我正在寻找架构模式,而不是 IOC 技术解决方案)

我在网上搜索这篇博文(评论中有一些非常有趣的讨论): https ://blog.risingstack.com/dependency-injection-in-node-js/

它很好地总结了我的冲突。这是博客文章中的一些代码,可让您理解我在说什么:

一个简单的测试看起来像这样:

与迪:

测试:

0 投票
1 回答
662 浏览

xcode - 如何将 XCTestCases 暴露给外部测试包?

我有一个Whiteboard封装我的业务逻辑的框架。我试图保持我的依赖倒置和解耦,因此由于Whiteboard依赖于存储库,它声明了一个协议WhiteboardRepository,并且它希望链接Whiteboard到的客户端提供WhiteboardRepository.

您可以在下面的屏幕截图中看到这一点。还要注意这个WhiteboardTests组,它包括一个WhiteboardRepositoryTests类以及一个WhiteboardRepositoryFake和它自己的测试子类。

在此处输入图像描述

为了确保实现的WhiteboardRepository行为符合预期,WhiteboardTests测试包定义了一个WhiteboardRepositoryTests子类XCTestCase

为了让客户端Whiteboard测试它的实现WhiteboardRepository,实现的测试类将实现的子类化,并将实现WhiteboardRepositoryTests的实例提供给测试子类,然后在运行测试时使用该实例。

例如,WhiteboardRepositoryFakeTests如下所示:

当然,这很好用,因为WhiteboardRepositoryFakeTests它在WhiteboardTests捆绑包中,所以WhiteboardRepositoryTests暴露于WhiteboardRepositoryFakeTests.

问题是:链接的应用程序Whiteboard需要创建自己的子类WhiteboardRepositoryTests来测试自己的实现,但是由于他们无权访问WhiteboardTests测试包,他们不知道WhiteboardRepositoryTests该类,因此无法对其进行子类化.

我有多个客户端正在使用Whiteboard,所以我不能简单地将WhiteboardRepositoryTests类复制到每个客户端中——我也不想这样做,因为Whiteboard定义WhiteboardRepository' 的行为是责任,所以WhiteboardRepositoryTests应该住在Whiteboard' 的测试包中。在一个理想的世界中,我可以将Whiteboard's test bundle 链接或注入到客户端的测试包中,以便WhiteboardRepositoryTests暴露给客户端的测试,但我不知道如何做到这一点。

有没有办法绕过这个障碍?如何WhiteboardRepositoryTests在客户端测试包中公开测试,以便客户端可以确保其实现WhiteboardRepository行为符合预期?

0 投票
0 回答
57 浏览

solid-principles - OCP 和 DIP 会破坏 YAGNI 吗?

据我了解YAGNI,只有在需要时我们才需要提取接口。因此,如果我们不需要多态性并且现在只有一个实现,我们就不需要使用接口。但是DIP说:

A. 高级模块不应该依赖于低级模块。两者都应该依赖于抽象。

B. 抽象不应该依赖于细节。细节应该取决于抽象。

看起来YAGNI和选项 B之间存在一些差异DIP。此外,如果我们想要应用OCP,我们需要反转依赖关系的控制并提取抽象,以便能够在不修改该类型的情况下扩展一个类型。

此外,一些技术需要提取抽象才能对类型客户端进行单元测试。但是例如在java中我们不需要它。所以我想知道如果我现在只有一个实现,是否需要提取抽象?