Использовать значение объекта в команде и событии? - PullRequest
0 голосов
/ 09 мая 2019

Можем ли мы использовать значение объекта в команде?

Предположим, у меня есть магазин (агрегат), в котором есть один объект значения Address. В конструкторе объекта значения Address я поместил некоторую логику проверки для адреса. Поэтому, если я использую этот объект Address в команде (CreateShopCmd), то он проверяется при создании команды, но что я хочу или читаю, что проверка должна присутствовать в обработчике команд.

Но проблема в том, что я должен снова поместить эту проверку в обработчик команд (поскольку проверка уже присутствует в этом конструкторе адресов), и если я не добавлю это в обработчик команд, то проверка произойдет, когда я выполняю Обращаться к объекту в обработчике событий и назначать агрегату магазина (что неверно)

Итак, пожалуйста, ведите меня.

Ниже приведен пример кода

   @Aggregate
   @AggregateRoot
   public class Shop {

   @AggregateIdentifier
   private ShopId shopId;
   private String shopName;
   private Address address;

   @CommandHandler
   public Shop(CreateShopCmd cmd){

     //Validation Logic here , if not using the Address in 
     // in cmd

         //Fire an event after validation
         ShopRegistredEvt shopRegistredEvt = new ShopRegistredEvt();
         AggregateLifecycle.apply(shopRegistredEvt);
     }

     @EventSourcingHandler
     public void on(ShopRegistredEvt evt) {

     this.shopName = evt.getShopName();

     //Validation happend here if not put in cmd at the time of making 
     //Address object - this is wrong
     this.address = new Address(evt.getCity(),evt.getCountry(),evt.getZipCode())

     }


   }

  public class CreateShopCmd{

    private String shopId;
    private String shopName;
    private String city;
    private String zipCode;
    private String country;

   }

 public ShopCreatedEvent{

    private String shopId;
    private String shopName;
    private String city;
    private String zipCode;
    private String country;

}

Ответы [ 3 ]

2 голосов
/ 14 мая 2019

Это очень хороший вопрос, и я тщательно обдумывал, встраивать объекты значений в команды или нет.Я пришел к выводу, что вам определенно не следует использовать объекты Value в командах:

Команды являются частью прикладного уровня, они должны работать как можно проще, избегая любых типизированных объектов, и лучше всего работать с использованием литерала (думаю сериализация).Что происходит, когда внешняя система хочет подключиться к вашему шестиугольнику (прикладному уровню) и отправить команды в ваше приложение, нужна ли им ваша библиотека команд, чтобы иметь возможность использовать объекты и определенную структуру?Конечно нет !Вы не хотите этого, поэтому сохраняйте команду простой.

Другая причина, по словам Дмитрия Бодю, VO содержит бизнес-логику и проверку, они принадлежат слою домена, никогда не помещают их в команды.Служба приложений выполнит перевод и будет отвечать за выдачу ошибки проверки любым несоответствующим командам на клиенте.

В вашем дизайне нет ничего плохого, на самом деле это как Вон Вернон (автор книги «Реализация доменного управления»)- Книга IDDD) сделал в своем хранилище, вы можете проверить прикладной уровень по этой ссылке:

https://github.com/VaughnVernon/IDDD_Samples/blob/master/iddd_identityaccess/src/main/java/com/saasovation/identityaccess/application/IdentityApplicationService.java

Обратите внимание, как он восстанавливает каждый объект из плоских команд, чтобы оценить объект, принадлежащийслой домена:

@Transactional
public void changeUserContactInformation(ChangeContactInfoCommand aCommand) {
    User user = this.existingUser(aCommand.getTenantId(), aCommand.getUsername());

    this.internalChangeUserContactInformation(
            user,
            new ContactInformation(
                    new EmailAddress(aCommand.getEmailAddress()),
                    new PostalAddress(
                            aCommand.getAddressStreetAddress(),
                            aCommand.getAddressCity(),
                            aCommand.getAddressStateProvince(),
                            aCommand.getAddressPostalCode(),
                            aCommand.getAddressCountryCode()),
                    new Telephone(aCommand.getPrimaryTelephone()),
                    new Telephone(aCommand.getSecondaryTelephone())));
}

Команды не должны содержать бизнес-логику, поэтому они не могут содержать объект значения.

2 голосов
/ 10 мая 2019

Нет ничего концептуального в использовании объектов-значений в командах или событиях.Однако вы должны использовать их с осторожностью.

Структура сообщения может со временем меняться.Если вы чрезмерно использовали Value Object в своих сообщениях, может стать менее понятно, как изменение одного из объектов Value меняет структуру различных сообщений.

Для объектов Value, которые представляют «общую» концепцию, например,как адрес, это не такая большая проблема.Но как только объекты Value становятся более специфичными для домена, это может стать проблемой.

1 голос
/ 10 мая 2019

Я бы не советовал использовать объекты Value в командах. Потому что ваши команды являются частью прикладного уровня, но объекты значений хранятся в доменном слое. Вы можете использовать ваши ValueObjects в DomainEvens, хотя. Потому что, если модель домена изменится, модификация вашего доменного события не будет такой болезненной, потому что модификация выполняется в том же ограниченном контексте. Вы никогда не должны использовать ValueObjects в событиях интеграции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...