Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Design patterns 依赖注入将业务层内部暴露给UI层——这肯定是一件坏事吗?_Design Patterns_Dependency Injection_Encapsulation - Fatal编程技术网

Design patterns 依赖注入将业务层内部暴露给UI层——这肯定是一件坏事吗?

Design patterns 依赖注入将业务层内部暴露给UI层——这肯定是一件坏事吗?,design-patterns,dependency-injection,encapsulation,Design Patterns,Dependency Injection,Encapsulation,我现在正在使用依赖注入。实际上,这涉及到UI层(例如web应用程序),其中包括一个DI容器,该容器包含一大堆关于它将使用的接口的数据,以及每个接口使用的实现 但是,由于需要满足依赖关系,DI容器还需要了解它不需要访问的接口和类。例如: UI层需要使用IWidgetManager接口。配置的实现是ConcreteWidgetManager。这是在DI容器中注册的 iWidgetManager依赖于IWidgetRepository。这方面的理想实现是ConcreteWidgetRepository

我现在正在使用依赖注入。实际上,这涉及到UI层(例如web应用程序),其中包括一个DI容器,该容器包含一大堆关于它将使用的接口的数据,以及每个接口使用的实现

但是,由于需要满足依赖关系,DI容器还需要了解它不需要访问的接口和类。例如:

UI层需要使用
IWidgetManager
接口。配置的实现是
ConcreteWidgetManager
。这是在DI容器中注册的

iWidgetManager
依赖于
IWidgetRepository
。这方面的理想实现是
ConcreteWidgetRepository
。因此,DI容器还必须了解
IWidgetRepository
ConcreteWidgetRepository

如果我只是硬编码了
ConcreteWidgetManager
ConcreteWidgetRepository
的依赖,那么
ConcreteWidgetRepository
就可以成为内部的,因此对我的UI层不可见。任何UI代码都不能绕过管理器层而直接与存储库层一起工作

因此,从UI层的角度来看,DI的使用,尽管在许多方面是一种令人敬畏的模式,但似乎会破坏封装


我这样想对吗?有没有办法缓解这种情况?

您描述这种情况的方式意味着UI层负责创建DI容器

这在您的特定应用程序中可能是正确的。但是请记住,初始化部分只是整个代码的一小部分

是的,有一些代码以特定的顺序创建DI容器和UI层。UI层可能会调用一个函数
createdContainer
,该函数初始化所有组件。但是这一个函数是唯一提到实现的实例;UI层的所有其他方面都处理抽象接口。纯粹主义者可能会提出质疑,但实际上,在99.5%的代码不是
createdContainer
的情况下,UI不知道实现是什么。将初始化函数移动到单独库中的一个单独的静态类中,如果这样做会让您更高兴的话


我也很好奇你说

如果我只是硬编码了ConcreteWidgetManager对ConcreteWidgetRepository的依赖关系

你把它作为一种选择提出来让我想:你有什么理由不硬编码这种关系吗?我在必要时使用依赖注入——最终的好处是,我可以在自动化测试中模拟部分代码

是否要模拟
ConcreteWidgetRepository
?如果你不是,那就继续硬编码这段关系。否则,你只是为了架构而引入架构


(请参阅。)

不,依赖项注入并没有破坏封装。正是您分层应用程序的方式打破了封装。通过在不同的程序集中分离接口和实现,并将容器配置放在自己的程序集中,您可以避免UI层必须依赖于具体的
ConcreteWidgetManager
,或者如果您愿意,甚至依赖于
IWidgetRepository


但是,添加额外的程序集会增加成本。在维护和编译解决方案所需的时间方面。我不会使用程序集强制执行体系结构规则,而是使用清晰简单的指导原则,或者使用诸如NDepend之类的工具来强制执行它们。然而,当团队规模足够小时,使用代码审查将足够有效地防止架构侵蚀。

是的,它确实破坏了封装。但这是使用DI所需要付出的代价。它使您的代码更易于测试,但会破坏封装


从类的API角度来看,请求注入依赖项的类变得尽可能愚蠢,但调用该类的类现在知道的太多了。在您的案例中,框架是。如果您在代码中使用DI,比如构造函数注入,那么调用类需要了解几个类

答案是肯定的,DI确实破坏了封装。它是的副本,另请参见如何对UI层可见
ConcreteWidgetRepository
?框架配置中提到它并不意味着它是“可见的”,除非您的UI代码自动连接到
IWidgetRepository
。这是一个编码问题,与包含对
ConcreteWidgetRepository
@parsifal的硬编码引用的UI代码完全相同-DI容器是UI层的一部分。如果它需要了解
ConcreteWidgetRepository
(它需要知道,将一个知识注入
ConcreteWidgetManager
),那么该知识在UI层的其他地方也可以免费获得。@David-在我看来,DI容器就是应用程序:它将UI与业务逻辑关联,并连接任何内部依赖项,但它不是这两者的一部分。@parsifal-我不知道您在哪个平台上开发,所以我不太确定如何构建这个问题,所以我将以.NET方式给您介绍。那么,您如何创建您的解决方案?DI容器与UI项目(例如web应用程序)位于不同的项目中??DI容器只包含UI层代码的一小部分,但它需要了解这些类这一事实意味着UI层的其余部分也需要了解。关于是否对依赖项进行硬编码的问题非常有趣。问题是我想要另一个实现的可能性有多大?有时,我需要另一个imp,这是出于“操作”原因