Проверка сущности DDD - PullRequest
       13

Проверка сущности DDD

8 голосов
/ 10 марта 2012

У меня есть вопрос, связанный с проверкой сущности.Например, есть User, который может быть зарегистрирован в системе с данными email и password.Бизнес-правило гласит:

  1. email должно быть действительным (должно соответствовать формату электронной почты) и уникальным;
  2. password должно содержать от 6 до 20 символов.

Моя первоначальная мысль - поместить валидацию в User.Register(email, password).Основным преимуществом этого подхода является то, что User контролирует, как он регистрируется, проверяя себя правильность регистрационных данных.Недостатком является то, что для проверки уникальности электронной почты требуются вызовы UserRepository, поэтому User может зависеть от Repository.Чтобы решить эту проблему, проверка подлинности электронной почты и пароля может быть учтена для каких-либо BusinessRule объектов.Таким образом, проверка в методе User.Register() может выглядеть следующим образом:

var emailValidationErrors = _emailRule.Validate(email);
var passwordValidationErrors = _passwordRule.Validate(password);

, где _emailRule и _passwordRule могут быть переданы в качестве аргументов конструктора: User(EmailRule emailRule, PasswordRule passwordRule).

В этом случае User напрямую не связан с UserRepository.Таким образом, правила явно отображаются в домене, что делает его более выразительным.

Итак, вопрос: что вы думаете об этом подходе?Есть ли другие решения?

Ответы [ 4 ]

4 голосов
/ 12 марта 2012

Вы можете реализовать Доменную службу , которая инкапсулирует это. Обычно в DDD вы используете доменную службу, когда бизнес-логика выходит за рамки одного отдельного агрегата; в этом случае это проверка уникальности. Итак, что бы я сделал, это:

public class UserRegistrationService : IUserRegistrationService
{
   private readonly IUserRespository _userRepository;

   public void Register(string email, string password)
   {
        if (!_userRepository.DoesEmailExist(email))
           throw new Exception("Email already registered");

        User user = User.Create(email, password);

        _userRepository.Save(user);
   }
}

Кроме того, если вы беспокоитесь о том, что User.Create вызывается вне службы регистрации и, следовательно, обходит проверку уникальности, вы можете установить для метода User.Create значение Internal, то есть единственный способ создать пользователя - это через RegistrationService.

3 голосов
/ 11 декабря 2012

В этом примере вы пытаетесь выполнить три проверки:

  1. Адрес электронной почты должен быть в правильном формате;
  2. Адрес электронной почты должен быть уникальным (т. Е. Не существует пользователя с таким адресом электронной почты);
  3. Пароль должен соответствовать определенным ограничениям длины.

1 и 3, приведенные выше, являются простыми проверками, которые должны быть выполнены декларативно для свойств сущностей (например, с использованием пользовательских атрибутов и подходящей библиотеки проверки в .NET).

2 выше - хитрый бит, и именно здесь, на мой взгляд, существует внутренняя зависимость от репозитория User.

Вопрос заключается в следующем: «Ответственность за предотвращение создания User с тем же адресом электронной почты, что и у существующего User, лежит на сущности User?». Я полагаю, что ответом на этот вопрос является «Нет» ... «кажется», что эта ответственность должна лежать на службе или организации более высокого уровня, для которых естественно знать весь набор пользователей.

Итак, мой дубль:

  1. Поместите те проверки, которые находятся у пользователя, внутри объекта User (сильная сплоченность);
  2. Поместите ограничение уникальности в службу DDD, которая конкретно отвечает за поддержку инвариантов набора пользователей - это будет сделано путем обертывания проверки уникальности и сохранения нового User в транзакции.
2 голосов
/ 10 марта 2012

Можно подумать, что существует 2 вида проверки: проверка внутреннего состояния и проверка контекста.Вы можете выполнить внутреннюю проверку из этой сущности, а затем выполнить проверку контекста с помощью некоторого сервиса.

1 голос
/ 10 марта 2012

Markus

Его подход был неплохим, но я просто поступаю иначе.

По моему мнению, вы уважаете OCP, исключая правила проверки, которые были приняты разумно. Используя эти правила валидации в конструкторе классов, вы предполагаете, что правила неизменны, верно?

Я бы не стал так делать, просто создал бы диаду методов, устанавливающую правила в качестве этого конструктора. Для меня было неясно, что произойдет, если правила проверки были нарушены. Мне нравится бросать исключения в пользовательский интерфейс, который обрабатывает как более вездесущие предупреждения.

Еще одна вещь, которая мне не ясна, это событие, которое вызывает эту проверку. было бы, когда сущность User была добавлена ​​в хранилище или есть метод сущности, который бы это делал? Я возьму второй вариант, вызывающий метод isValidAuthentication (), выбрасывающий эти исключения.

Относительно зависимости сущности от хранилища, осмелюсь сказать, что это неправильно. Вы могли бы даже сделать сущность зависимой от него, потому что хранилище представляет собой набор объектов, что с этим не так? Тем не менее, на данный момент кажется очевидным, что проверка является службой. Поэтому, если мы поместим эти проверки в Службу, это устранит эту связь и снова применяет OCP. Вы согласны?

Большое объятие и успехов!

...