17

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

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

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

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

根据“这是反模式”的人群,这里有什么问题?

4

3 回答 3

21

如果您将所有业务逻辑放在(隐式无状态)服务层中,则您正在编写过程代码。通过将行为与数据解耦,您就放弃了编写面向对象的代码。

这并不总是坏事:它很简单,如果你有简单的业务逻辑,就没有理由投资一个成熟的面向对象的领域模型

业务逻辑越复杂(域越大),过程代码变成意大利面条代码的速度越快:过程开始以不同的前置条件和后置条件(以不兼容的顺序)相互调用,并且它们开始需要不断增长的状态对象。

Martin Fowler 关于贫血领域模型的文章可能是了解人们为什么(以及在什么情况下)反对将业务逻辑放入服务层的最佳起点。

于 2011-07-31T17:41:43.920 回答
9

服务层本身并不是一种反模式,它是放置业务逻辑某些元素的非常合理的地方。但是,您确实需要对服务层的设计进行判断,确保您不会从域模型和组成它的对象中窃取业务逻辑。

通过这样做,您最终可以得到一个真正的反模式,一个贫乏的域模型。Martin Fowler在此处对此进行了深入讨论。

您的 IAuthenticationService 示例可能不是讨论该问题的最佳选择-围绕身份验证的许多逻辑可以被视为存在于服务中,并且与域对象没有真正的关联。一个更好的例子可能是,如果您有某种 IUserValidationService 来验证用户,或者更糟糕的服务是处理订单之类的事情 - 验证服务正在从用户对象中剥离逻辑,而订单处理服务正在从您的订单对象,也可能来自代表客户的对象、交货通知等...

于 2011-07-31T17:38:15.787 回答
0

DDD 必须有 4 层:表示层、应用层、域层和基础设施层。

表示层向用户呈现信息,解释用户命令。

所有依赖于用例逻辑(应用程序实体、应用程序工作流组件,例如 DTO、应用程序服务)都进入应用程序层(应用程序逻辑)。该层不包含任何业务逻辑,不保存业务对象的状态,可以保存应用任务的进度状态。

对用例逻辑(业务实体、业务工作流组件,例如领域模型、领域服务)的所有不变性都进入领域层(领域逻辑)。该层负责业务领域和业务规则的概念。

基础设施层可能有 IoC、缓存、存储库、ORM、密码学、日志记录、搜索引擎等。

于 2018-12-20T17:26:47.743 回答