假设我有一个Groups和Users,当用户想要加入一个组时,我正在调用groupsService.AddUserToGroup(group,user)方法。在DDD中,我应该做group.JoinUser(user),看起来不错。
但是,如果手头的任务过于复杂或不适合实体模型,则DDD还鼓励您使用(无状态)服务来执行任务。可以在域层中提供服务。但是域层中的服务应仅包含业务逻辑。另一方面,外部任务和应用程序逻辑(例如发送电子邮件)应在应用程序层中使用域服务,例如,在其中可以使用单独的(应用程序)服务来包装它。
如果我有一些添加用户的验证规则,则会出现问题...
验证规则确实属于域模型!它们应封装在域对象(实体等)中。
...或将用户添加到组时需要启动一些外部任务。拥有这些任务将导致实体具有外部依赖性。
虽然我不知道您在说什么外部任务,但我认为这就像发送电子邮件等。但这实际上不是您的域模型的一部分。它应该驻留在应用程序层中,并在那里恕我直言。您可以在应用程序层中拥有一个服务,该服务在域服务和实体上运行以执行这些任务。
但是,实体依赖于某些外部服务/类这一事实在我看来并不那么好,也不是“自然的”。
这是不自然的,不应该发生。实体不应该知道不属于其职责的东西。服务应用于协调实体交互。
在DDD中处理此问题的正确方法是什么?
在您的情况下,该关系应该是双向的。用户是加入组还是组带用户取决于您的域。用户是否加入该组?还是将用户添加到组?它在您的域中如何运作?
无论如何,您具有双向关系,因此可以确定用户集合中用户已经属于的组的数量。确定负责任的班级后,从技术上讲是将用户传递给组还是将组传递给用户都是不重要的。
然后,验证应由实体执行。整个事情是从应用程序层的服务调用的,该服务还可以做技术性的工作,例如发送电子邮件等。
但是,如果验证逻辑确实很复杂,则域服务可能是更好的解决方案。在这种情况下,将业务规则封装在那里,然后从应用程序层调用它。