Comment créer de nouvelles racines agrégées dans l'architecture CQRS? Dans cet exemple, je veux créer une nouvelle racine agrégée AR2 qui contient une référence à la première AR1.
Je crée AR2 en utilisant la méthode AR1 comme point de départ. Jusqu'à présent, je vois peu d'options:
- Dans la méthode AR1,
createAr2RootOpt1
je pourrais appelernew AR2()
et enregistrer cet objet dans db immédiatement en utilisant le service de domaine qui a accès au référentiel. Je pourrais émettre un événement dans la première racine agrégée, par exemple.
SholdCreateAR2Event
puis avoir une saga sans état qui réagit à ce sujet et émet une commandeCreateAR2Command
qui est ensuite gérée et crée réellement AR2 et émetAR2CreatedEvent
. En cas d'utilisation, le sourcing d'événementsSholdCreateAR2Event
ne serait pas conservé dans le magasin d'événements, car il n'affecte pas l'état de la première racine agrégée. (Ou devrions-nous toujours l'enregistrer dans le magasin d'événements?)class AR1{ Integer id; DomainService ds; //OPTION 1 void createAr2RootOpt1(){ AR2 ar2 = new AR2(); ds.saveToRepo(ar2); } //OPTION 2 void createAr2RootOpt2(){ publishEvent(new SholdCreateAR2Event()); //we don't need this event. Shoud it still be preserved in event store? } } class AR2{ Integer id; Integer ar1Id; void handle(CreateAR2Command command){ //init this AR with values and save publishEvent(AR2CreatedEvent()); //used for projections afterwards and saved inside AR2 event store } } class Saga{ void handle(SholdCreateAR2Event ev){ emitCommand(new CreateAR2Command()); } }
Quelle est la meilleure façon de procéder?
la source
AR1WasCreated
? Devrait-il en être ainsiAR2WasCreated
? De plus, si j'utilise votre logique, j'émets un événementAR2WasCreated
avant qu'il ne soit réellement créé? Et l'enregistrement de cet événement dans le journal des événements d'AR1 semble problématique, car je n'ai pas réellement besoin de ces données dans AR1 (cela ne modifie rien dans AR1).AR1WasCreated
-> SAGA (a la règle si A1 a été créé puis créez A2) ->CreateAR2Command
->AR2WasCreated
.Les modèles de création sont étranges .
Udi Dahan a des choses utiles à dire sur le problème général: ne pas créer de racines agrégées . Le point fondamental étant que les agrégats ne sortent pas de nulle part et qu'il existe un langage de domaine qui décrit leur apparence, qui devrait être capturé dans votre modèle de domaine.
Là où cela a tendance à se tordre, c'est que l'entité de votre modèle de domaine qui traite la commande n'est pas l'entité modifiée par la transaction. Ce n'est pas faux; c'est juste bizarre (par rapport aux cas où vous demandez à une entité de se modifier.
Votre deuxième approche est également OK. Les «événements que nous déclenchons sans les enregistrer réellement dans la base de données» sont parfois appelés «événements de domaine»
L'idée de base étant que, dans la même transaction, le gestionnaire de commandes déclenche l'événement, qui se déplace le long du bus vers un gestionnaire d'événements qui permet au deuxième agrégat de se créer lui-même. Vous obtenez peut-être une meilleure cohésion du code.
Remarque: dans les systèmes basés sur des événements, vous n'utilisez généralement pas les événements de cette façon.
Remarque: les noms d'événements sont généralement au passé - ShouldCrateAR2 a une mauvaise orthographe.
Oui, si vous lancez simplement un événement sur le bus synchrone pour exécuter le code à distance, vous ne devriez pas enregistrer cet événement dans le livre d'enregistrement. Ce n'est qu'un détail d'implémentation à cette échelle.
Évitez de modifier deux flux d'événements différents dans la même transaction. Si cette création représente également un changement pour AR1, alors la réponse habituelle serait de modifier AR1 dans cette transaction, avec un abonné asynchrone à ces événements qui est responsable du déclenchement de la commande pour créer AR2.
La gestion idempotente des commandes aide beaucoup ici.
la source
AR1.doSmthn(AR2 param)
car toute projection en lecture que je crée n'a pas de données complètes dont j'ai besoin (seul AR2 a des données complètes).