域模型的松散耦合程度如何?

时间:2017-06-19 00:43:53

标签: c# oop architecture domain-driven-design

问题:我是否应该依赖DomainModel Core来保持系统接口和高级策略?

我们是否认为富域模型代表实现细节?

后台:所以我将DomainModel放在一个没有外发依赖项的单独项目中。我的所有子系统服务都在单独的项目中,并且没有一个知道彼此。我还有一个Core项目,它包含所有系统特定的东西,如接口,枚举,验证类,扩展和所有服务共有的其他东西,我不会将其归类为低级实现细节。除Core外,DomainModel没有外向依赖关系,所有服务都依赖于Core,还有DomainModel

我当前的想法:我已经听过设计陈述,例如

  

" 域模型应该没有传出依赖关系"

可能相反

  

"高级别政策不应该依赖于低级别的实施细节"

  

"模块应该在稳定的方向上相互依赖"

我发现在开发系统时,域模型的实现发生了很大的变化,所有的业务规则和对象都在那里,我不会认为大多数域模型都是稳定的,可能是一些它就像ValueObject(s)。

我在DomainModel取决于Core时看到的优势是高层策略然后对域模型的实现细节一无所知,域模型也是孤立的来自系统的其他部分。实际上,其他每个项目都只依赖于Core而且对彼此一无所知。当我在DomainModel(我经常在开发时)进行更改时,构建将重新编译该项目,而不是目前的整个解决方案。

缺点我在实现这种额外松散耦合量时看到的是复杂性的增加?我必须为每个域模型对象创建接口,这些对象将存在于Core内的特殊文件夹中。对于那些接口,我也想放弃“我”。前缀并说MoneyType : Money [interface]。我想我可以实例化域对象的唯一方法是通过抽象工厂,所以我还需要更多这些。现在我喜欢能够实例化具体的域对象'任何地方'在系统中,几乎就像BCL的扩展或抽象(它是域模型的一部分,不是吗?)。

我可以想象这个系统可以使用这两种架构,所以这只是竞争设计问题的典型案例 - 还是我完全错过了什么?

编辑:这个高度投票的答案似乎表明域模型应该与每个对象隔离,只暴露与系统其余部分的接口。

https://stackoverflow.com/a/821300/7417812

目前这对我来说感觉更好,因为系统的其他部分没有对域对象的自由访问(因此每次有更改时都会重新编译它们)。然而,将这种依赖性转变为完全孤立将不是一项微不足道的任务,所以我对更多的讨论和答案非常开放。

更多编辑:所以我尝试了重构,在我开始尝试实现我自己的简单DI容器时,我认为事情开始变得有点臭,有点荒谬。

完全DomainModel隔离的任何可感知的好处都被复杂性和代码行的指数增加所抵消(至少对我而言)。所以我重构了这个架构,以便DomainModel仅依赖于CoreInfrastructure现在只能通过我使用的合同类,自定义集合,注释和常用扩展来保存我的设计。我把所有系统特定的接口和基础设施都带到了一个新的项目DomainModel中,所有子系统服务都依赖于这个项目(这里没有特定的技术,所以可能不是典型的基础设施层?)。

现在一切感觉都好一些,但我要回到依赖于具体的域对象,我很好。当我发现Core的一些改进和简化时,它并没有完全是浪费的练习,并且能够澄清Infrastructure并确定{{1}}的机会。

2 个答案:

答案 0 :(得分:2)

Onion architecture,其中一个与DDD良好对齐的架构中,Domain层可以进一步分为两个子层:

  1. 核心:包含不特定于任何域或技术的构建块,包含列表,案例类和参与者等通用构建块。它永远不会包括技术概念,例如REST或数据库。
  2. :所有业务逻辑所在的实际域层,其中包含使用域无处不在的语言命名的类和方法。通过API控制域并将所有业务逻辑放入域中,应用程序变得可移植,可以提取所有技术位而不会丢失任何业务逻辑。
  3. 所以,你可以拥有一个在有界上下文之间共享的Core组件,但我不认为这应该必然在一个单独的项目中。这取决于您希望如何将对此组件的更改传播到其他项目。

    关于依赖关系,Domain sub-layer将取决于Core sub-layer,因为它使用其低级别类,但这不会破坏Dependency inversion principle,因为两者都在同一层中。但是,(整个)Domain layer不应该依赖于ApplicationPresentationInfrastructure等任何其他层,Domain layer应保持纯净,没有任何一方效果,没有依赖。任何架构都应该遵守这条规则。

答案 1 :(得分:1)

  

我还有一个Core项目,它包含所有特定于系统的内容   接口,枚举,验证类,扩展和   所有服务共有的其他事项

您正在描述不依赖于特定层的不可知代码构造和模式。

  • 接口和枚举,只要它们是关于域概念,就应该在域层中。其他界面和枚举......好吧,无论它们最适合哪里。

  • “验证类”也非常模糊,但域验证在域中进行,在应用层中进行命令验证,在用户界面中进行用户输入验证等。

  • 可以在任何图层中找到扩展方法。

我认为你应该摆脱那些看起来并不真实的“核心”项目,并把所有内容都展示给相应的项目。

国际海事组织,所有“高级政策”都应该进入域名。您可以在类似库的项目或NuGet包中放置的所有项目共享的实用程序类,但不应该有太多这些,我也不会称之为Core。