4

我一直在阅读依赖注入框架。我真的爱上了分离关注点并让对象完成其核心工作的想法——这无疑是一个优秀且长期存在的设计原则!

然而,我在 DI 框架上阅读的越多,我就越担心:1)它们“自动”解决依赖关系的方式 2)关于配置文件中引入的极端复杂性

就第 2 点而言,我看到我的客户花费数百万美元来培训人们使用产品,其中重要的部分是如何“不”接触配置文件。管理员现在害怕这些配置文件。

尽管如此,我看到了另一种称为服务定位器的模式,我可以在应用程序开始时很好地组装所有我想要的“全局”服务(可能是应用程序主机或应用程序上下文或其他)。让这个服务定位器在全球范围内可用,瞧!

但是,我发现当我需要基于某些标准(谁知道?)的不止一种“全局”服务时,使用服务定位器方法的灵活性会降低!

所以,在这里我比以前更困惑于该采取哪个方向。虽然我非常喜欢设计原则,但现有框架的复杂性让我望而却步!

我的担忧是真的吗?其他人有同样的感觉吗?如果是这样,对于如此庞大的压倒性“框架”有什么好的选择吗?

4

6 回答 6

3

我个人非常喜欢使用Autofac。容器配置是通过代码完成的,同时消除了冗长的 XML 并启用了重构支持。

但是,最好的功能之一是模块。它们是容器配置单元,允许您管理组成应用程序的许多不同组件的复杂性。

我目前正在做一个非常大的项目,体验与小时候大致相同,这意味着这种方法可以很好地扩展。

启用 DI 的类的主要原则是它们不引用基础结构代码。这是服务定位器模式的对立面。Service Locator 的主要缺点是,除了增加引用容器的类的复杂性之外,没有能力更改解决哪个版本的依赖项。

对于不引用容器的“纯”类,任何给定依赖项的解析版本都在被注入的类之外。

于 2009-08-25T06:26:35.380 回答
2

正如 Nate 所说,“魔法”是可选的;如果需要,您可以手动配置所有内容。

我最初(或永远!)会避免使用配置文件并在代码中配置容器。这往往更容易阅读和维护。大多数时候,您不需要即时更改配置。客户不能接触配置文件,因为它们不存在。

服务定位器有缺点;一方面,他们倾向于将您的类与定位器类/框架耦合。一个好的 DI 框架会让你使用 Plain Old Objects;您的项目中可能只有一个实际使用 DI/IoC 框架的类。

StructureMap 和 Unity 都非常简单。试一试。从小处着手。

这是一个非常简单的 Unity 示例(包括内联配置):

using Microsoft.Practices.Unity;

static void Main()
{
    using (IUnityContainer container = new UnityContainer())
    {
        container.RegisterType<IRobot, MrRoboto>();

        Console.WriteLine("Asking Unity container to give us a Model...");

        Model model = container.Resolve<Model>();
        model.MoveRobot();
    }
}

// class Model

public Model(IRobot robot)
{
    // Unity will hand the constructor an instance of MrRoboto!
}
于 2009-08-25T01:16:48.187 回答
2

如果您真的在考虑采用依赖注入路线,我强烈建议您快速阅读 Martin Fowler 出色的依赖注入文章:

http://martinfowler.com/articles/injection.html

我现在正在处理一个包含大量配置文件的 Java 项目。我们预先选择了单例模式来表示我们的配置(有点类似于全局解决方案)。以下是让我发疯的事情,让我希望我们有一个依赖注入模式:

  1. 具有全球化模式的单元测试很糟糕。依赖注入模式很容易使单元测试更容易,尤其是模拟对象测试。在单例类型的情况下,您现在拥有所有这些仍然需要全局状态才能运行的单元测试。使用依赖注入,您可以制作传递给测试的特定于测试的模拟配置对象。我不能夸大这使单元测试变得多么容易。另一篇题为“Endo-Testing: Unit Testing with Mock Objects”的优秀论文:http: //connextra.com/aboutUs/mockobjects.pdf

  2. 使用全球化的方法在较小的系统中效果更好,但是随着线程数量的增加,它们都开始竞争配置资源。您可能会遇到同步问题,您的配置访问甚至会开始成为瓶颈。这对我们来说还不是一个大问题,但它开始让我们所有人烦恼。

  3. 一旦你沿着非依赖注入路线走了一小段路,就没有真正的回头路了。从依赖注入到某种全球化模式很烦人,但可以逐步进行。试图从全球化模式回到依赖注入是一场噩梦。我一直想在我们的项目上这样做,但我做不到。这将需要一个完整的开发周期。

无论如何,希望文章和经验可以帮助您做出决定。我在你正在考虑的道路上走了很长一段路,我有点希望我们会采取依赖注入路线:-D

于 2009-08-25T04:45:11.403 回答
1

对于 DI,这些都不是“必需的”——它们是某些 DI 框架提供的选项。就个人而言,我也不喜欢“自动”注入 - 我可以看到它适用于非常小的项目,但会导致更大的项目出现问题。对于第 2 点 - 我不确定我是否明白这一点 - 我主要使用 Spring。Spring 提供 XML 和 Java 配置选项。它提供嵌套配置。如果您不希望任何人更改配置的一部分并且您需要更改一部分 - 将它们分成单独的配置文件 - 或者使“可更改”一个 XML 和另一个 Java。Spring 还支持使用属性文件中的值,这是我希望管理员更改的所有内容 - 管理员不是程序员 - 他们不应该是“

于 2009-08-25T00:19:51.027 回答
0

根据您使用的语言,有些 DI 框架并不那么可怕,尽管您会有一些配置文件,但它们不应该很可怕,但很有用。

例如,我有一个用于开发的配置文件,一个用于测试,一个用于生产。

因此,根据我使用的那个,可以更改数据库连接,我可以换出数据库层进行测试,并使用模拟测试。

系统管理员应该控制生产配置文件,因为理想情况下,开发人员不应该将任何东西推送到生产环境。

Spring 为 DI 提供了很好的设置,尽管它不是轻量级的。

我发现 Unity 框架学习起来并不简单,但是一旦你使用它,添加新的注入类就很容易了。

因此,任何新事物最初都可能令人恐惧,但当您熟悉该概念时,您会看到优势,例如我对三个配置文件的解释。

于 2009-08-25T00:15:09.417 回答
0

我的情况可能与您的不同,因为我们已经有一个为非常灵活的配置而设计的系统,因此向该配置添加依赖注入几乎是微不足道的,但在我看来,使用服务定位器模式不会像您必须那样为您节省太多配置仍然指定如何定位服务。能够灵活地注入模拟对象进行测试是使用依赖注入的一个几乎无价的好处,所以我想说配置开销可能只是做生意的成本,你需要接受才能获得好处。

于 2009-08-25T00:19:35.490 回答