【发布时间】:2013-01-13 10:06:17
【问题描述】:
- 当应用程序使用 Repository(这是一个 Infrastructure 服务)时,Repository 接口 定义在 Domain 中层,而它的实现是在基础设施层中定义的,因为这样域模型没有传出依赖项。
a) 如果我们 100% 确定特定(非存储库)基础设施服务 InfServ 将永远不会被 中的任何代码调用领域层,那么我假设InfServ的接口不需要在领域层中定义?
- 假设 InfServ 不会被 Domain 层中的代码调用(因此我们不需要在 Domain 层 中定义它的接口):
a) 如果 应用层的服务 将调用 InfServ,我假设 应用层 应该对 Infrastructure 有隐式依赖层 而不是相反?换句话说,InfServ 的接口和它的实现都应该在基础设施层中定义?
b)应用层最好依赖基础设施层而不是其他方式的原因是基础设施层 em> 可以被许多应用程序重用,而 应用层 在大多数情况下仅特定于单个应用程序,通常不能被其他应用程序重用?
c) 如果我们 100 % 确定 Domain 层 中的任何代码都不会使用 Repository,那么我们就不需要在 中定义它的接口>域层?
更新:
1)
是的,但是领域层的定义可以包括应用 充当域外立面的服务。应用程序 服务通常引用存储库和其他基础设施 服务。它编排域对象和所述服务以实现 用例。
一)
...充当域的外观
难道我们不能争辩说“常规”(我在我的问题中提到的那些)应用程序服务也可以作为域的门面吗?
b)
应用程序服务通常引用存储库和其他 基础设施服务。
从您的回复看来,您似乎在暗示(尽管您可能不是)“常规”应用程序服务通常不引用基础设施服务 ,实际上他们是这样做的(据我所知)?!
2)
一)
如上所述,我通常将应用程序服务合并到 领域层。
“常规”应用层也是 BLL 层的一部分,所以我们不能说它与 域层 合并(它实际上位于域层 )?!
b)
我倾向于坚持六边形建筑风格...
看起来六边形架构没有明确的应用层概念(即应用服务)?
c)
在域中声明存储库接口的部分好处 层是它指定了域的数据访问要求。
所以我们应该在 Domain 层 中包含 Repository 接口,即使我们的域代码不会使用它?
第二次更新:
2a)
如果您所谓的“常规”应用程序服务与 域,我认为将其作为域的一部分是可以接受的 “层”。但是,域不应直接依赖于 围绕应用程序服务,因此可以将它们拆分 如果需要,可以分成单独的模块。
-
我不确定您是否暗示 应用层(在传统的分层架构中)的设计与合并时有任何不同 应用层 域层使用例如洋葱架构?
-
我想说,至少就模块而言,两者应该没有什么不同,因为在这两种情况下,我们都可以将 Application 和 Domain 层 模块分开? (尽管我必须承认我跳过了伴侣模块(Evan 的书),因为我认为在学习 DDD 时我不需要这些知识:O)
2b)
是的,因为它可以与分层架构进行对比。一个严格的 分层架构不符合声明的想法 领域层中的存储库接口并在 基础设施层。这是因为,一方面,你有一个 在一个方向上的依赖,但在部署方面依赖 在另一个。 Hexagonal 通过放置 域为中心。看看洋葱架构 - 它是 基本上是六边形,但可能更容易掌握。
我还不知道 MVC 模式或 Asp.Net MVC,但无论如何,从阅读该系列的前三部分(这让我感到困惑到我停止阅读它),它似乎:
a) 来自Onion article:
每一层都与它下面的层耦合,而且每一层往往是 再加上各种基础设施问题。
作者暗示在传统的分层架构 TLA 中,域层与基础设施层耦合,这当然不是真的,因为我们通常定义 域层中的基础设施接口(例如Repository接口)?!
b) 如果在使用 TLA 时我们决定在 Application layer 中定义 Infrastructure interfaces,那么 Application layer 也不会耦合到基础设施层?!
c) Onion 架构 不是*基础设施层* 耦合到应用程序核心(包括 应用程序层),因为 基础设施接口 在Application Core中定义?
d) 如果 c) 是,那么将 Application 层 耦合到 Infrastructure 层 不是更好吗(出于我让步的原因我最初的问题(这里我假设域层不会调用基础设施服务)?
4)
围绕领域模型的第一层通常是我们需要的地方 找到提供对象保存和检索行为的接口, 称为存储库接口。
控制器只依赖于接口,接口定义在 应用核心。请记住,所有依赖项都指向 中心。
作者似乎在暗示,由于依赖关系只是内部的,并且基础设施接口是围绕域模型定义的,因此域模型中的代码不应引用这些接口。换句话说,我们不应该将存储库引用作为参数传递给域实体的方法(正如您自己所说的那样):
class Foo
{
...
public int DoSomething(IRepository repo)
{
...
var info = repo.Get...;
...
}
}
出于上述原因,我必须承认,我看不到使用 Onion 架构 的好处,甚至看不到它与 TLA 有何不同(假设所有 Infrastructure 接口 都已定义域层 ) --> 换句话说,我们不能用洋葱架构图来描述TLA吗?!
最终更新:
2)
b)
是的。在 TLA 中,领域层将直接与 基础设施层声明的类的基础设施 反之亦然。
为了确定——您是说使用 TLA,Infrastructure 接口 将在 Infrastructure 层 中定义(我知道使用 Hexagonal/Onion 架构定义了它们在应用程序核心)?
d)
耦合是双向的。应用核心依赖于 基础设施和基础设施中的实现取决于 在应用程序核心中声明的接口。
我的观点是,由于在 Onion 架构中,InfServ 接口 是在 应用层 中声明的(这里的假设是 InfServ 永远不会被 Domain Layer 调用,因此我们决定不在 Domain Layer 内定义 InfServ 接口 >——见原1a问题),表示应用层控制InfServ接口。但我认为如果 Infrastructure 层 控制 InfServ 接口 会更好,因为原始 2b 中所述的原因 问题?!
4)
看来作者的意思是因为依赖关系只是向内的 由于基础设施接口是围绕领域模型定义的, 领域模型中的代码不应引用这些接口。
在我看来,您的代码示例适合代码。
所以我说洋葱架构不“允许”域模型引用基础设施接口是正确的,因为它们是在InDe(InDe 当然也存在于应用程序核心中)围绕 DM strong text并从 DM 引用它们是否意味着依赖关系从 DM 上升到 InDe?
DDD 通常以六角形/洋葱形建筑风格呈现 这就是为什么可能会有一些混乱。我想你可能已经 一直在做的已经是六边形了,这就是为什么它看起来像 同样的事情。
是的,我也有这种印象。虽然我确实计划在阅读完 Evan 的书后更深入地研究 Hexagonal 架构(特别是因为新的 DDD 书将基于它的一些示例)。
第四次更新:
2)
d)
如果基础设施拥有接口和实现,那么域 或应用层将负责实现持久性 为自己。
我假设 Application 或 Domain 层需要自己实现它,因为引用 Infrastructure 层 中定义的接口将遵循 Onion 的内层规则不依赖外层(基础设施层是外层)?
4)
域模型可以引用基础设施接口,例如 存储库,因为它们是一起声明的。如果应用层 从域中分离出来,就像在洋葱图中一样,然后是域层 可以避免引用接口,因为它们可以在 应用层。
但根据那篇文章,基础设施接口是在域层周围的层中声明的,这意味着它更接近应用程序核心的外边缘 而不是 Domain Layer – 正如文章所指出的,内层不应该依赖外层>!
谢谢
【问题讨论】: