【问题标题】:IoC Containers and Domain Driven DesignIoC 容器和领域驱动设计
【发布时间】:2009-11-17 22:12:05
【问题描述】:

我一直在寻找在域驱动设计中使用 IoC 容器的指南。不幸的是,埃文的书没有涉及这个主题。我可以在互联网上找到的唯一实质性指南是 here

马洛维奇的许多观点都是常识,但我担心其中的一些观点。他建议应保留 IoC 容器仅用于解析服务,并且使用 IoC 容器来解决域依赖关系是一个坏主意。然而,他没有用任何例子来支持这一断言。他简单地陈述了事实。

他接着说,混合 IoC 容器和工厂是没有意义的。这似乎与他的第一点相矛盾。事实上,如果域依赖不应该由 IoC 容器解决,那么应该如何解决它们呢? Evan 的书明确指出工厂是合乎逻辑的选择。

如果您对此事有任何意见,我将不胜感激。在 DDD 和 IoC 方面,我都是新手。我正在努力理解 IoC 和 DDD 如何协同工作。

【问题讨论】:

  • 你需要解决什么样的域依赖?如果我正确理解了 Malovic 的文章,他的主要观点是域模型不具有 DI/IoC 容器旨在处理的那种依赖关系(主要是基础设施依赖关系)。

标签: dependency-injection domain-driven-design ioc-container


【解决方案1】:

在我看来,他在域模型中不使用 IoC 容器是正确的。我自己也遵循这种做法。基本思想是服务可能包含基础设施依赖项,因此模拟它们是明智的。域实体没有这些,因此模拟它们并不重要(仍然对接口进行编码是一种很好的做法)。

域实体的工厂不应该在 IoC 容器中,但服务的工厂应该。基本上你可以在你的服务中引用实体工厂。这不是很紧密的耦合。

可以在Billy McCafferty's blog post "Dependency Injection 101" 找到有关 IoC 的好读物

【讨论】:

  • 您能否详细说明为什么使用 IoC 容器来解决域依赖关系是一个坏主意?你使用它们时遇到什么样的麻烦。你有什么建议呢?每个聚合根的工厂和创建工厂的工厂?
  • 首先,IoC 容器/ServiceLocator 是基础设施,我不希望它出现在我的模型中。其次,在我的测试中,我必须配置容器来创建被测系统。第三,为什么域模型甚至应该与服务对话。我认为你不需要那么多工厂。有时我使用工厂方法模式,但我自己并没有创建太多工厂。在 Evans 的书中,它说工厂用于封装值对象和聚合根。
  • “当创建一个对象或整个聚合变得复杂或暴露太多内部结构时,工厂提供封装。” [Evans, DDD, p136] 你不应该需要太多的工厂,因为领域模型中的一切都没有那么复杂。
【解决方案2】:

IOC 容器在设计可单元测试的代码时非常宝贵,并且与 DDD 正交。如果您愿意,您可以创建自己的工厂和构建器模式实现...为什么要经历这些麻烦?

当然。使用足够强大的 IOC 容器来满足您的特定要求;不多不少。

【讨论】:

    【解决方案3】:

    我们使用 DDD 和依赖注入(模式),但不使用依赖注入框架。

    流行的依赖注入框架的一个问题是它们如何将配置分离到 XML 文件中。 XML 是一种很棒的标记语言。它是如何成为一种配置语言的,我永远不会明白。当然,问题是您必须先运行应用程序,然后才能知道一切是否正确连接。也很难看出在哪里使用了哪些代码。如果您使用接口,那么对实现的唯一引用将在 XML 文件中,这很难发现。最后你失去了类型安全和泛型。 (我曾经在生产中看到一个可怕的错误,如果我们不使用 XML,编译器会发现它。)

    我应该指出,我并不是说依赖注入不好。它是良好对象设计的基本模式。但是在工厂里做接线绝对没有错。

    在我最近的两个项目中,我们已经从 XML 文件中删除了大量“代码”,并进入了工厂。这些工厂与容器管理的服务(例如 JDBC 连接、JMS 连接等)连接起来。应用程序变得更易于理解,因为工厂比 XML 更简洁。作为一名 Java 程序员,使用控制空间将程序连接在一起要容易得多,而不是 XML 玩弄——当你破坏某些东西时,你的 IDE 会突出显示。

    在集成测试中,只需像在工厂中一样创建对象。

    即,

    dbConnection = DatabaseConnectionFactory.connection();    
    serviceUnderTest = new PaymentProcessor(new CustomerRepository(connection));
    

    【讨论】:

    • 我一直在试验 Castle Windsor,它具有对代码内配置的 API 支持。 container.AddComponent()。如果没有必要,我会尽量避免使用 xml 配置。
    • StructureMap 具有扫描仪功能,几乎可以自动映射。如果你愿意,你可以创建一些使用反射来绑定服务的约定(示例实现可以在github.com/marektihkan/Arc/tree/master/Arc/Source/…找到)
    • necro,我知道,但我不知道任何需要 xml 进行配置的 c# DI 容器。也许对于更奇特的用例来说是统一的,但在大多数情况下,这个答案不再适用了。
    • 我会给你一个很大的+1,但今天有很多投票:-(如果我在配置文件中遇到类名,那么我认为这种反模式。如果没有非常好的 IDE重构整个系统会立即崩溃......最重要的是,编写工厂比复杂配置的解析器要容易得多......我也使用没有框架的模式。
    猜你喜欢
    • 2012-12-10
    • 2016-09-29
    • 1970-01-01
    • 2011-10-06
    • 2017-11-09
    • 2011-06-21
    • 2016-07-18
    • 2013-09-16
    相关资源
    最近更新 更多