0
votes

Utiliser la valeur objet dans la commande et l'événement?

Pouvons-nous utiliser l'objet de valeur dans la commande?

Supposons que j'ai un magasin (agrégat) dans lequel il existe une adresse d'objet de valeur. Dans l'adresse du constructeur d'objet Value, j'ai été placé la logique de validation pour l'adresse. Donc, si j'utilise cet objet d'adresse dans la commande (CreateSehopMD), il est validé lors de la prise de commandement, mais ce que je veux ou lisez que la validation doit être présente dans le gestionnaire de commandement. P>

mais problème est que Je dois mettre cette validation à nouveau dans le gestionnaire de commandement (puisque la validation est déjà présente dans le constructeur d'adresse informatique) et si je ne le mettez pas dans le gestionnaire de commandes, la validation se produira lorsque je rendra l'objet d'adresse dans le gestionnaire d'événements et assigner Pour acheter des achats (ce qui est incorrect) p>

Alors, veuillez me guider. P>

ci-dessous est Exemple de code P>

   @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;

}


0 commentaires

5 Réponses :


4
votes

Il n'y a rien de tort conceptuellement avec l'utilisation d'objets de valeur dans les commandes ou les événements. Cependant, vous devez les utiliser avec prudence.

La structure d'un message peut changer avec le temps. Si vous avez utilisé des objets de valeur excessivement à l'intérieur de vos messages, il peut devenir moins clair la manière dont une modification de l'un des objets de valeur change la structure de différents messages.

Pour des objets de valeur qui représentent un concept "commun", tel qu'une adresse, ce n'est pas tant de problème. Mais dès que les objets de valeur deviennent plus spécifiques à un domaine, cela peut venir en tant que problème.


0 commentaires

2
votes

Je ne suggérerais pas d'utiliser des objets de valeur dans les commandes. Parce que vos commandes font partie de la couche d'application, mais les objets de valeur sont conservés dans la couche de domaine. Vous pouvez utiliser votre valeurObjects dans Domainevens. Parce que si le modèle de domaine change, la modification de votre événement de domaine ne sera pas aussi douloureuse, car la modification est effectuée dans le même contexte délimité. Vous ne devez jamais utiliser ValueObjects dans des événements d'intégration.


0 commentaires

3
votes

C'est une très bonne question et j'ai réfléchi à fond à l'intégration d'objets de valeur dans des commandes ou non. Je suis arrivé à la conclusion que vous devriez certainement utiliser des objets de valeur dans les commandes:

Les commandes font partie de la couche d'application, elles sont censées fonctionner aussi simple que possible, en évitant les objets dactylographiés et fonctionnent mieux à l'aide de la littérale (réfléchie sérialisement). . Ce qui se passe lorsqu'un système externe souhaite plugin sur votre hexagone (couche d'application) et envoyer des commandes à votre application, avez-ils besoin de votre bibliothèque de commandes pour pouvoir utiliser les objets et la structure définie? Sûrement pas ! Vous ne voulez pas cela, alors gardez la commande simple. P>

Une autre raison est, comme Dmitribodiu a dit, VO contient la logique et la validation des entreprises, elles appartiennent à la couche de domaine, ne les mettent jamais en commandes. Le service d'application fera la traduction et sera responsable de lancer une erreur de validation à toutes les commandes non conformes au client. P>

Il n'y a rien de mal dans votre conception, c'est en fait comment Vaughn Vernon (l'auteur de la mise en œuvre de Domaine a conduit Conception - Livre IDDD) a fait dans son référentiel, vous voudrez peut-être vérifier la couche d'application sur ce lien: p>

https://github.com/vaughnvernon/iddd_samples/Idlob/Master/iddd_IdentityCess/src/MaintityAccess/src/main /java /com/saasovation/identitintityaccess/application/identitinyApplicationservice.java p>

Remarquez comment il reconstruit chaque objet des commandes plats pour valoriser l'objet appartenant à la couche de domaine: P>

@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 commentaires

Yeh Vous avez raison, mais si vous voyez dans mon code le, je crée l'objet de valeur (logique de validation présente dans le constructeur d'objets de valeur) dans la méthode de manutention d'événement.SO La validation se produit après le gestionnaire de commande.Mais comme je sais validation devrait être fait dans le gestionnaire de commandement et non dans le gestionnaire d'événements. Comme une suggestion à ce sujet?


Rappelez-vous que les commandes peuvent être refusées, l'événement ne doit pas, événement est déjà arrivé dans le passé, vous avez donc raison lorsque vous dites que la validation ne peut pas être effectuée dans le gestionnaire d'événements. Vous devez mettre le VO dans l'événement afin que le gestionnaire de commande échoue quand il essaiera de construire et d'envoyer un événement valide.



1
votes

Réponse courte: Avez-vous déjà pensé à entier , string , booléen , etc.? Ce sont également des objets de valeur. La seule différence est que vous ne les avez pas créés vous-même. Maintenant, essayez de créer une commande sans objets de valeur ; -)

longue réponse: En général, je ne vois aucun problème avec des objets de valeur dans les commandes. Tant que vous suivez quelques directives simples:

Le code le plus important de votre application est votre modèle de domaine. Le modèle de domaine définit les structures de données qu'il attend pour la manipulation de la commande. Cela signifie: la seule raison de modifier votre modèle de commande est si votre modèle de domaine nécessite ce changement. Il en va de même pour vos objets de valeur: les objets de valeur ne modifient que si cette modification est requise par votre modèle de domaine. Aucune exception!

Les commandes peuvent en général échouer soit en raison de contraintes commerciales, soit en raison de données non valides (ou en raison d'un verrouillage optimiste, ou autre).

Comme indiqué ci-dessus: les entiers et les chaînes sont également des objets de valeur. Si vous n'utilisez que des types de base dans votre commande, il lancera déjà une exception si vous essayez Nouvelle SetAgecommand (AGGID, "FOO") , car String ne peut pas être attribué à int . Il en va de même si vous ne fournissez pas d'ID d'agrégat à votre updatepersonCommand . Ce sont des contraintes commerciales non , mais plutôt une validation de données et de type très élémentaires. Votre commande ne sera jamais créée si vous passez des données malformées.

Disons maintenant que vous avez un personnage objet de valeur. Je n'ai pas d'importance où vous construisez cet objet, car dans tous les cas, il doit lancer une exception si vous essayez de le construire avec un nombre négatif: -5 ne peut pas être attribué au personnage - semble familier? Tant que vous pouvez vous assurer que votre code crée ces instances d'objet de valeur, vous pouvez certainement savoir qu'ils sont valables.

Les règles commerciales doivent être vérifiées par le gestionnaire de commandes dans votre modèle de domaine. En général, les contraintes commerciales sont spécifiques à votre domaine et, le plus souvent, ils s'appuient sur les données de votre agrégat. Prenons par exemple sendmoneyCommand . Votre objet de valeur money peut valider s'il s'agit d'une devise valide, mais elle ne peut pas valider si le compte bancaire de l'utilisateur a suffisamment d'argent pour exécuter la transaction. Ceci est une validation commerciale et fait partie de votre modèle de domaine.

Et un mot concernant les événements: je suggérerais d'utiliser uniquement des objets de valeur très basiques à l'intérieur de vos événements. Par exemple: chaîne , integer , date , etc. Fondamentalement, tous types d'objet de valeur qui seront jamais changent. La raison derrière elle: les besoins professionnels peuvent changer. Par exemple: Peut-être que votre modèle de domaine nécessite votre adresse adresse à modifier, et c'est maintenant requis pour fournir des coordonnées géographiques. Ensuite, cela modifiera implicitement votre NewAdDressaddeDevent . Mais vos événements déjà persistés n'avaient pas cette exigence, bien que vous ne puissiez pas construire des objets d'adresse à partir de vos données d'événement passées, car la nouvelle adresse adresse une exception s'il n'y a pas de geo-coordonnées fournies.

Il y a (au moins) deux solutions pour ce problème:

  1. Événements vers les versions: Après avoir modifié votre adresse Objet de valeur , vous avez maintenant un NEWADDRESSADDEDEvent_version2 qui utilise le nouvel objet objet objet, et vous avez L'ancien NewAdressAddeDevent qui doit utiliser une copie de sauvegarde de l'ancienne adresse objet de valeur.
  2. Écrivez un script qui "réparait" votre base de données d'événement en ajoutant des coordonnées géographiques à chaque événement utilisant l'objet adresse . Donc, vous pouvez jeter l'ancien NewAdDressaddeDevent .

0 commentaires

0
votes

C'est bien tant que les objets de valeur conceptuellement une partie de votre contrat de messagerie et non utilisées dans des entités.

Et s'ils font partie de votre entité, ne les exposez pas comme propriétés publiques de votre message ou vous serez à SOOP.


0 commentaires