请用IoC容器卖给我


17

我已经看到一些建议在代码中使用IoC容器的方法。动机很简单。采取以下依赖项注入代码:

class UnitUnderTest
{
    std::auto_ptr<Dependency> d_;
public:
    UnitUnderTest(
        std::auto_ptr<Dependency> d = std::auto_ptr<Dependency>(new ConcreteDependency)
    ) : d_(d)
    {
    }
};


TEST(UnitUnderTest, Example)
{
    std::auto_ptr<Dependency> dep(new MockDependency);
    UnitUnderTest uut(dep);
    //Test here
}

进入:

class UnitUnderTest
{
    std::auto_ptr<Dependency> d_;
public:
    UnitUnderTest()
    {
        d_.reset(static_cast<Dependency *>(IocContainer::Get("Dependency")));
    }
};


TEST(UnitUnderTest, Example)
{
    UnitUnderTest uut;
    //Test here
}

//Config for IOC container normally
<Dependency>ConcreteDependency</Dependency>

//Config for IOC container for testing
<Dependency>MockDependency</Dependency>

(以上当然是假设的C ++示例)

尽管我同意通过删除依赖项构造函数参数来简化类的接口,但出于某些原因,我认为治愈的方法比疾病的方法还差。首先,这对我来说是个很大的问题,这使您的程序依赖于外部配置文件。如果您需要单个二进制部署,则无法使用这些类型的容器。第二个问题是,API现在是弱类型,更糟糕的是,是字符串类型的。证据(在此假设示例中)是IoC容器的字符串参数,并对结果进行强制转换。

所以..使用这些容器还有其他好处吗?或者我只是不同意那些推荐的容器?


1
示例代码看起来像是一个非常糟糕的IoC实现示例。我只熟悉C#,但是肯定有办法在C ++中进行构造函数注入和程序化配置吗?
rmac 2011年

Answers:


12

在具有许多层和许多活动部件的大型应用程序中,与优点相比,缺点似乎变得很小。

容器确实“简化了类的接口”,但是它以非常重要的方式做到了。容器是对依赖项注入所产生问题的一种解决方案,即需要在整个地方,向下通过对象图以及跨功能区域传递依赖项。您在这里有一个具有一个依赖关系的小示例-如果该对象具有三个依赖关系,并且依赖于该对象的对象有多个依赖于它们的对象,依此类推?如果没有容器,那些依赖关系链顶部的对象最终将负责跟踪整个应用程序中的所有依赖关系。

也有不同种类的容器。并非所有人都是字符串类型的,也不是所有人都需要配置文件。


3
但是一个大型项目使我已经提到的问题更糟。如果项目很大,则配置文件本身将成为一个巨大的依赖磁铁,并且在运行时使一个错字导致未定义的行为变得更加容易。(即,如果在配置文件中输入错字,则会导致类型转换,如果返回错误的类型,则会导致未定义的行为)。至于依赖关系的依赖关系,在这里无关紧要。要么构造函数负责制作它们,要么测试将嘲笑顶级依赖关系。
Billy ONeal,

...继续...当不测试程序时,默认的具体依赖关系将在每个步骤中实例化。还有其他类型的容器,您有一些例子吗?
Billy ONeal,

4
TBH我没有大量的DI实现经验,但是请看一下.NET上的MEF,MEF可以但不必是字符串类型的,没有配置文件,并且接口的具体实现已“注册”在课程本身上。顺便说一句,当您说:“构造函数负责制作它们”时-如果您正在这样做(也就是“穷人的构造函数注入”),那么您就不需要容器了。与之相比,容器的优势在于容器可以集中所有相关性的信息。
nlawalker

+1为最后一条评论-最后一句话有答案:)
Billy ONeal

1
很好的答案帮助我理解了整个观点。重点不仅在于简化样板,还在于使依赖链顶部的元素与底部的元素一样幼稚。
Christopher Berman

4

Java的Guice IoC框架不依赖于配置文件,而是依赖于配置代码。这意味着该配置的代码与构成您实际应用程序的代码没有什么不同,并且可以重构等。

我相信Guice是最终实现正确配置的Java IoC框架。


C ++是否有类似的示例?
Billy ONeal

@Billy,我对C ++不够熟悉,无法说出来。

0

这个伟大的SO答案本Scheirman详细介绍了C#的一些代码示例; IoC容器(DI)的一些优点是:

  • 您的依赖项链可能会嵌套,并且手动将其连接起来很快变得笨拙。
  • 允许使用面向方面的编程
  • 声明性和嵌套数据库事务。
  • 声明性和嵌套工作单元。
  • 正在记录。
  • 前/后条件(按合同设计)。

1
我看不到用简单的构造函数注入无法实现任何这些东西。
Billy ONeal

如果设计良好,那么构造函数注入或其他方法可能就足够了。这些IoC容器的优势可能仅在特定情况下才有。WPF项目中使用INotifyPropertyChanged给出的示例就是这样的示例。
dodgy_coder 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.