在DDD中,业务逻辑应该放在哪里?

21

我正在尝试找出构建易于维护和可测试的架构的最佳方法。在经历了几个项目后,我看到了一些非常糟糕的架构,我想避免在自己的项目中犯类似的错误。

假设我正在构建一个相当复杂的三层应用程序,并且我想使用DDD。我的问题是,业务逻辑应该放在哪里?有人说它应该放在服务(服务层)中,这确实有道理。拥有许多符合单一职责原则的服务是有意义的。

但是,有些人说这是反模式,业务逻辑不应该在服务层中实现。为什么会这样?

假设我们有一个IAuthenticationService,其中包含具有bool UsernameAvailable(string username)签名的方法。该方法将实现所有必需的逻辑以检查用户名是否可用。

“这是反模式”团队认为问题在哪里?

3个回答

26
如果你把所有业务逻辑放在(隐式无状态的)服务层中,那么你正在编写过程性代码。通过将行为与数据解耦,你放弃了编写面向对象代码的机会。这并不总是坏事:它很简单,如果你的业务逻辑很简单,就没有理由去投资于一个完整的面向对象domain model
业务逻辑越复杂(领域越大),过程性代码就越容易变成意大利面代码:流程开始以不兼容的顺序相互调用,并开始需要越来越多的状态对象。 Martin Fowler的关于贫血领域模型的文章可能是理解为什么(以及在什么情况下)人们反对将业务逻辑放在服务层中的最佳起点。

10

服务层本身并不是反模式,它是一个非常合理的放置业务逻辑的地方。然而,在设计服务层时需要谨慎,确保您不会从域模型及其组成对象中窃取业务逻辑。

如果这样做,您可能会得到一个真正的反模式,即贫血领域模型。 Martin Fowler在这里深入讨论了这个问题。

关于认证的大部分逻辑可以被视为存在于服务中,而不是与域对象相关联。因此,您提供的IAuthenticationService示例可能不是最好的来讨论这个问题。更好的例子可能是,如果您拥有某种IUserValidationService来验证用户,或者更糟糕的是一个处理订单的服务 - 验证服务正在从用户对象中剥离逻辑,而订单处理服务正在从您的订单对象以及表示客户、交付通知等对象中剥离逻辑...


1
我刚刚发现了一篇MSDN文章,其中写道:“服务层位于应用程序的领域模型之上,并提供一组可对其执行的操作。这为您提供了一个集中逻辑的地方,该逻辑属于您的应用程序,但可能不一定属于领域模型内部 - 否则可能会泄漏到控制器方法中。”...... 我猜这就是你们用不同措辞写的东西。不过,你们如何确定什么属于领域模型,什么不属于呢? - Vex
3
人们对“服务层”的理解有许多不同的含义,但如果您试图将所有业务逻辑放入您的领域模型中,那么您就不会误。这与应用程序逻辑相反(有关此区别,请参见此答案 - Jeff Sternal

5
您需要使用DDD有四个层次:演示层、应用程序层、领域层和基础设施层。
演示层向用户呈现信息,解释用户命令。
所有依赖于用例逻辑(应用实体、应用工作流组件,例如DTO、应用服务)都归属于应用程序层(应用逻辑)。此层不包含任何业务逻辑,不持有业务对象的状态,可以保留应用程序任务进度的状态。
所有与用例无关的逻辑(业务实体、业务工作流组件,例如领域模型、领域服务)都归属于领域层(领域逻辑)。该层负责业务领域和业务规则的概念。
基础设施层可能具有IoC、缓存、存储库、ORM、加密、日志记录、搜索引擎等。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接