我正在努力找出构建易于维护和可测试的架构的最佳方法。经历了几个项目后,我看到了一些非常糟糕的架构,我想避免在我自己的项目中犯下未来的错误。
假设我正在构建一个相当复杂的三层应用程序,我想使用DDD。我的问题是,我应该在哪里放置我的业务逻辑?有人说它应该放在服务(服务层)中,这确实有意义。拥有一系列遵循单一责任原则的服务是有道理的。
然而,有些人说这是反模式,业务逻辑不应该在服务层实现。这是为什么?
假设我们IAuthenticationService
有一个带有bool UsernameAvailable(string username)
签名的方法。该方法将实现所有必需的逻辑,以检查用户名是否可用。
根据“这是反模式”的人群,这里有什么问题?
答案 0 :(得分:11)
如果您将所有业务逻辑放在(隐式无状态)服务层中,那么您正在编写过程代码。通过将行为与数据分离,您将放弃编写面向对象的代码。
这并不总是坏事:它很简单,如果你有简单的业务逻辑,就没有理由投资于一个成熟的面向对象的domain model。
业务逻辑越复杂(域越大),程序代码变得越快,意味着代码:程序开始以不同的前后条件(以不兼容的顺序)相互调用,并且它们开始需要 - 生长状态对象。
Martin Fowler's article on Anemic Domain Models可能是理解为什么(以及在什么条件下)人们反对将业务逻辑放在服务层中的最佳起点。
答案 1 :(得分:5)
服务层本身不是反模式,它是放置业务逻辑的某些元素的一个非常合理的地方。但是,您需要对服务层的设计应用自由裁量权,确保您不会从域模型和构成它的对象中窃取业务逻辑。
通过这样做,你可以得到一个真正的反模式,一个贫血的领域模型。 Martin Fowler here对此进行了深入讨论。
您的IAuthenticationService示例可能不是最好的讨论问题 - 许多围绕身份验证的逻辑可以被视为生活在服务中而不是真正与域对象相关联。一个更好的例子可能是,如果您有某种IUserValidationService来验证用户,或者甚至更糟糕的是执行类似流程订单的服务 - 验证服务正在从用户对象中剥离逻辑,并且订单处理服务正在从逻辑中取出逻辑您的订单对象,也可能来自代表客户的对象,交货通知等......
答案 2 :(得分:0)
您必须具有DDD的4个层:演示,应用程序,域和基础结构。 所有依赖用例逻辑(应用程序实体,应用程序工作流组件,例如DTO,应用程序服务)都进入应用程序层(应用程序逻辑)。 用例逻辑的所有不变量(业务实体,业务工作流组件,例如域模型,域服务)都进入域层(域逻辑)。 基础结构层可能具有IoC,缓存,存储库。