Реализация, управляемая доменом - обновление одного свойства в Aggregate Root - PullRequest
0 голосов
/ 20 октября 2019

Я новичок в DDD, и я хотел бы получить несколько советов по нескольким проблемам, с которыми я сталкиваюсь при его реализации.

Я использую Typescript для разработки приложения. Данные сохраняются в реляционной базе данных. Мы не следуем шаблону CQRS, и наши операции чтения и записи происходят в одной и той же базе данных.

Предположим, у меня есть агрегат User примерно как ниже,

class User extends AggregateRoot {

id: number;
phone: Phone;
email: Email;
address: Address;

private constructor(id, phone, email, address){
    //setting the values
}

public static create(props) {

    return new User({...props});
}

public static update(props) {

    return new User({...props});
}

}

Здесь, Phoneи Email являются ValueObjects, а Address является Entity.

class Phone extends ValueObject {

phNumber: string;

private constructor( ph ) {

    phNumber = ph;
}

public static create(ph){

    //do validations
    return new Phone(ph);
}
}

Класс Email также похож на Phone.

Теперь, как только запрос на обновление телефона получен в контроллере, запрос перенаправляется на User Serviceслой и служба будут выглядеть примерно так:

public updatePhone( updatePhNoDto ) {

const userEntity = userRepository.getUser(updatePhNoDto.userId);

const userModel = User.update({
    id: updatePhNoDto.userId,
    phone: Phone.create(userEntity.phone),
    email: Email.create(userEntity.email),
    address: Address.create(userEntity.address)
});

userRepository.updateUser(userModel)
}

Здесь каждый раз, когда пользователь запрашивает обновление номера телефона, я выбираю пользовательские данные из СУБД и выполняю все проверки для всех полей, которыеуже проверены и затем вызывают метод User.update(). Итак, вот мои вопросы:

  1. Не уверен, что вышеприведенное является правильным способом, так как я проверяю материалы, которые я уже проверял и, возможно, ненужный вызов БД. Поэтому, пожалуйста, предложите мне рекомендации по работе с такими ситуациями, когда требуется обновить одно или только несколько полей.
  2. Пользователь может обновить свой адрес независимо от своей другой информации. Так должна ли сущность Address быть Aggregate Root сама по себе? Если да, как это должно быть обработано, если и UserInfo, и Address запрашиваются для обновления в одном http-запросе?
  3. Какова роль Aggregate Root в удалении? Как это должно быть смоделировано внутри него?

Пожалуйста, дайте мне знать, если вы обнаружите какие-либо другие недостатки в дизайне.

Спасибо!

1 Ответ

1 голос
/ 21 октября 2019

Так же, как контроллер имеет конечную точку UpdatePhone, у пользователя будет метод UpdatePhone, который только проверяет и обновляет номер телефона. Пользовательский AR также будет иметь UpdateEmail, UpdateAddress и т. Д.

Если пользователь может одновременно изменять несколько свойств пользователя во внешнем интерфейсе, вы используете Controller для выяснения этого. У вас будет конечная точка UpdateUser на контроллере, которая решит, что изменилось, а что нет, а затем вызовет все необходимые методы для пользователя. Некоторый псевдокод:

If (PhoneInfoUpdated) User.UpdatePhone ({поля, отправленные пользователем)};If (EmailInfoUpdated) User.UpdateEmail ({поле, отправленное пользователем)};If (AddressInfoUpdated) User.UdateAddress ({предоставленная пользователем информация об адресе});

(Вы, вероятно, просто удалили это для краткости в сообщении, но помните, что здесь есть два уровня проверки данных. Контроллер проверяет типы дат, например, если вы ожидаете целые числа, вы на самом деле получаете целые числа, даты - это даты, номера телефонов и электронные письма - в правильном формате и т. д. Затем внутри User.Update - каким бы методом вы ни проверяли, удовлетворяются ли бизнес-правила, например, адрес электронной почты недубликат существующего и т. д.)

Я не понимаю, как адрес может прожить собственную жизнь, не будучи владельцем пользователя, но если это ваш бизнес-кейс, то это должен бытьAR. Поэтому для изменения адреса у вас должна быть отдельная конечная точка API адреса, которая выполняет правильные манипуляции, а не пытается отправить ее через конечную точку пользователя. Внешний интерфейс должен принять решение о правильной конечной точке для вызова, если он вызывает API-интерфейсы напрямую, или если вы используете MVC, контроллер получает обратную передачу и затем может либо вызвать надлежащие API-интерфейсы, либо соответствующие методы на AR.

Что касается удалений, я никогда не был фанатом фактического удаления, поэтому я бы порекомендовал добавить флаг Active (или флаг Deleted в зависимости от того, на какой стороне этого бесконечного обсуждения вы находитесь). Независимо от того, действительно ли вы удаляете или просто устанавливаете флаг, у вас должен быть метод User.Delete. Если вы действительно удаляете строку, я предпочитаю, чтобы это был статический метод класса User, поэтому вам не нужно извлекать пользователя, чтобы просто удалить его. Если вы используете флаг, метод Delete должен быть общедоступным в классе, потому что в действительности он просто устанавливает свойство, как любое другое свойство.

...