根据域和服务层的薄/厚程度,您是否走在 DDD 的正确轨道上。 DDD 表示知识(即业务逻辑)应该被整合到领域模型中。将数据访问问题移至 DAL 符合 DDD,但我认为将业务逻辑移至服务层则不然。如果您有一个薄的域“数据模型”层(主要用于实体)和一个厚的服务层(主要用于“业务逻辑”),那么您可能有一个贫血区 http://martinfowler.com/bliki/AnemicDomainModel.html.
此外,从技术上讲,DDD 中不存在“服务层”。可能有一个“应用程序层”,但它应该很薄,并且只负责应用程序流/管理域类生命周期。这本质上就是控制器在 .NET MVC 中所做的事情,在 Web http 上下文中管理应用程序流。
如果将所有逻辑填充到模型中会使您的代码过于复杂,我有兴趣听听您所说的“过于复杂”的示例。您可以正确地对复杂的领域进行建模,或者您也有可能采用 DDD 模式来使事情变得简单。我想说,正如您在问题中列出的那样,拱门不是 DDD。我只是将其称为“分层架构”,但那是因为我更喜欢仅在谈论物理拱门时使用术语“层”。但是,您的逻辑架构是分层的。
我真的很喜欢达林在他的回答中与洋葱拱门的联系。我正在成为它的忠实粉丝,并且我发现它根本不是 DDD 所独有的。如果您的代码使用依赖注入来解决运行时实现的接口依赖关系,您可能会遇到某种形式的洋葱拱。例如,您是否在 DAL 中定义了任何接口?这些接口的实现是否在运行时解决?
这是我开始在新项目中使用的拱门示例。它是洋葱+DDD的组合:
API
项目/程序集:所有其他层使用的通用接口、枚举、类和扩展方法。不需要与域分开,但可以。
Domain
项目/程序集:所有实体和业务逻辑。依赖于取决于API
仅有的。使用 DDD 模式,如工厂、服务、规范、存储库等。还包含更多 API 中未定义的特定于域的接口。
Impl
项目/程序集:定义的接口的实现API
and Domain
。这是实现 EF DbContext 以及日志记录、电子邮件发送等的地方。所有这些实现都是依赖项注入的,因此从技术上讲,您可以拥有多个 Impl 项目/程序集。
UI
项目/程序集:这是 MVC 项目。控制器直接使用域表面,不经过应用程序或服务层。工厂、服务、存储库等中的任何接口依赖项都由控制器使用 MVC IoC(构造函数注入)注入到域中。
我在最核心放置了一个 API 层,但您可以将 API 和域项目合并为一个。不管怎样,洋葱的大肉部分是领域,它有内部分层。例如,服务可能依赖于工厂,而工厂又依赖于存储库,而存储库又依赖于实体。
Impl 项目就是您在巴勒莫图中看到的“基础设施”洋葱皮。它与 UI 一起位于外边缘,并且不包含特定于领域的知识。它知道如何使用 EF 发送电子邮件、存储/检索数据等。如果您愿意,您可以拥有其中 1 个以上 — 例如 1 个用于数据访问的 Impl,1 个用于处理邮件的 Impl 等。
MVC 具有控制器和视图,并专注于 UI 和 Web 应用程序流程。任何需要特定领域知识的内容都被委托给域,并且域类通过构造函数注入到控制器中。这意味着域类中任何构造函数注入的接口都会由 IoC 容器自动解析。
最后一点,根据 API 和域类中定义的接口进行编程意味着您可以将域项目与 MVC 项目分开进行单元测试。