问题:我是否应该依赖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
仅依赖于Core
,Infrastructure
现在只能通过我使用的合同类,自定义集合,注释和常用扩展来保存我的设计。我把所有系统特定的接口和基础设施都带到了一个新的项目DomainModel
中,所有子系统服务都依赖于这个项目(这里没有特定的技术,所以可能不是典型的基础设施层?)。
现在一切感觉都好一些,但我要回到依赖于具体的域对象,我很好。当我发现Core
的一些改进和简化时,它并没有完全是浪费的练习,并且能够澄清Infrastructure
并确定{{1}}的机会。
答案 0 :(得分:2)
在Onion architecture,其中一个与DDD良好对齐的架构中,Domain
层可以进一步分为两个子层:
所以,你可以拥有一个在有界上下文之间共享的Core
组件,但我不认为这应该必然在一个单独的项目中。这取决于您希望如何将对此组件的更改传播到其他项目。
关于依赖关系,Domain sub-layer
将取决于Core sub-layer
,因为它使用其低级别类,但这不会破坏Dependency inversion principle
,因为两者都在同一层中。但是,(整个)Domain layer
不应该依赖于Application
,Presentation
或Infrastructure
等任何其他层,Domain layer
应保持纯净,没有任何一方效果,没有依赖。任何架构都应该遵守这条规则。
答案 1 :(得分:1)
我还有一个Core项目,它包含所有特定于系统的内容 接口,枚举,验证类,扩展和 所有服务共有的其他事项
您正在描述不依赖于特定层的不可知代码构造和模式。
接口和枚举,只要它们是关于域概念,就应该在域层中。其他界面和枚举......好吧,无论它们最适合哪里。
“验证类”也非常模糊,但域验证在域中进行,在应用层中进行命令验证,在用户界面中进行用户输入验证等。
可以在任何图层中找到扩展方法。
我认为你应该摆脱那些看起来并不真实的“核心”项目,并把所有内容都展示给相应的项目。
国际海事组织,所有“高级政策”都应该进入域名。您可以在类似库的项目或NuGet包中放置的所有项目共享的实用程序类,但不应该有太多这些,我也不会称之为Core。