域驱动的设计:服务和验证 [英] Domain driven design: Services and validations

查看:61
本文介绍了域驱动的设计:服务和验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在遵循域驱动的设计规则来设计系统。我对服务,外部系统和验证有疑问。

I am following domain driven design rules to design a system. I have doubts regarding services, external systems and validations.

集合必须与其他系统的Web服务交互才能进行验证和提供信息。我不确定允许聚合访问外部单词是否是一个好主意。如果创建用于访问外部服务的服务,我将无法执行不变式和验证。如果我将所有逻辑汇总在一起,听起来不是一个好主意,但是这些问题似乎消失了。

An aggregate must interact with web services of other systems to make validations and to provide information. I am not sure if allowing an aggregate to access the outside word is a good idea. If I create a service to access the external services I have trouble to enforce invariants and validations. If I put all the logic into the aggregate it doesn't sound a good idea but those problems seem to disappear.

为了使问题更容易理解,假设存在用户聚集,并且必须发送电子邮件以确保电子邮件正确(在我的实际问题中,我必须与外部Web服务进行通信)

To make the problem simpler to understand suppose that there is a User aggregate and it must send an email to make sure the email is correct (in my real problem I have to communicate with external web services)

public class User {
    public User (Long id, String name, String email) {...}
    public changeEmail(String newEmail) {...}
    ...
}

public interface EmailValidatorService {
    /**
    * Sends a test email
    */
    public verifyEmail(String email) throws EmailException;
}

我不确定这是个好主意还是电子邮件验证逻辑应该是用户集合的一部分。也许它可以是一项服务,而用户聚合可以使用它……但是听起来也不是一个好主意。

I am not sure if this is this a good idea or if the email verification logic should be part of the User aggregate. Perhaps it could be a service and the User aggregate could use it... but it doesn't sound like a good idea either.

如果它是服务的一部分用户聚合将承担额外的责任,如果它是一项服务,则我看不到强制域规则的简便方法。 ¿如果开发人员使用changeEmail但未通过服务对其进行验证怎么办?

If it is part part of the User aggregate it will have extra responsibilities and if it is a service I do not see an easy way to enforce the domain rules. ¿What if a developer uses changeEmail without validating it with the service?

推荐答案

您可以选择几种方法来实现此方案。一种是拥有处理此特定用例的应用程序服务,以调用验证功能:

You have a few options to implement this scenario. One is to have an application service which handles this specific use case invoke the validation functionality:

class UserService
{
  EmailValidatorService emailValidatorService;
  UserRepository userRepository;

  public void changeUserEmail(string currentEmailAddress, string newEmailAddress)
  {
    var user = this.userRepository.GetByEmail(currentEmailAddress);
    if (user == null)
       throw ...;


    this.emailValidatorService.verifyEmail(newEmailAddress);

    user.changeEmail(newEmailAddress);

    // commit, etc...
  }
}

应用程序服务是注入此类验证规则的便捷位置-要求对外部服务的调用或聚集无法轻松访问的服务。一般来说,应用程序服务可以是一种后备机制,用于处理纯DDD方法不太适合的情况。此外,无论您使用域模型还是交易脚本之类的应用程序,都可以存在。

An application service is a convenient place to inject validation rules of this sort - the sort where calls to external services are required, or services that the aggregate cannot easily access. More generally, the application service can be a sort of "fallback" mechanism for handling cases where a pure DDD approach doesn't quite fit. Also, an application service can exist regardless of whether you use a domain model or something like transaction script.

另一种选择是在User类的changeEmail方法中为汇总提供验证器:

Another option is to provide the validator to the aggregate in the changeEmail method on the User class:

class User
{
  string emailAddress;

  public void changeEmail(string newEmailAddress, EmailValidatorService validator)
  {
    validator.verifyEmail(newEmailAddress);
    this.emailAddress = newEmailAddress;
  }
}

这里的好处是聚合将所有与电子邮件地址更改关联的逻辑。结果,客户端代码无法在没有提供验证器的情况下更改电子邮件地址-应用程序服务方法无法强制执行此操作。同样,这与通过依赖注入引用验证程序服务的用户聚合不同,通常会被皱眉。相反,这是一种即时依赖注入。

The benefit here is that the aggregate encapsulates all of the logic associated with an email address change. As a result, client code cannot change an email address without providing a validator - something the application service approach cannot enforce. Also, this is different from the User aggregate referencing the validator service via dependency injection, which is typically frowned upon. Instead, this is a sort of on-the-fly dependency injection.

在此特定情况下要考虑的另一件事是您希望执行的验证的性质。一个特征是,如果某个电子邮件地址在某一时间有效,则将来可能不再有效。这意味着您已经需要适当的工作流来处理电子邮件地址无效的现有用户。如果该逻辑已经到位,那么为什么还要完全确保在域中进行验证呢?毕竟,即使验证器服务确保电子邮件地址有效且处于活动状态,也不能保证用户会访问它。

Another things to consider in this specific scenario is the nature of the validation your wish to perform. One characteristic is that if an email address is valid at one point, it may no longer be valid in the future. This means that you already need to have workflows in place to handle existing users having an invalid email address. If that logic is already in place, why bother with ensuring validation in the domain at all? After all, even if a validator service ensures an email address is valid and active, there is no guarantee the user will access it.

这篇关于域驱动的设计:服务和验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆