Comment les dépôts correspondent-ils au CQRS?

selon Fowler ( ici ), un dépôt " sert d'intermédiaire entre les couches de cartographie de domaine et de données, agissant comme une collection d'objets de domaine en mémoire."Ainsi, par exemple, dans l'application de mon service de messagerie, lorsqu'une nouvelle exécution est soumise, mon service d'application crée un nouvel objet root agrégé D'exécution, le remplit avec les valeurs de la requête puis l'ajoute au répertoire D'exécution avant d'appeler l'Unité de travail pour enregistrer les modifications dans la base de données. Lorsqu'un utilisateur veut pour voir la liste des lancements en cours, j'interroge le même dépôt et je renvoie un DTO dénormalisé représentant l'information.

Cependant, en regardant CQRS, la requête n'aurait pas frappé le même dépôt. Au lieu de cela, il irait peut-être directement à l'encontre de la base de données et serait toujours dénormalisé. Et mon côté commande évoluerait vers un NewRunCommand et Handler qui créerait et peuplerait un newrun domain object puis persisterait l'information dans le data store.

la première question est donc de savoir où se situent les dépôts dans le modèle CQRS si nous ne maintenons pas une collection en mémoire (cache, si vous voulez) d'objets de domaine?

considérer le cas où les informations soumises à mon service d'application ne contient rien mais une série de valeurs D'ID que le service doit résoudre afin de construire l'objet de domaine. Par exemple, la requête contient le numéro D'identification du coursier assigné à l'exécution. Le le service doit rechercher l'objet Courier réel en fonction de la valeur D'ID et attribuer l'objet au NewRun en utilisant la méthode AssignCourier (qui valide le courier et exécute d'autres logiques d'affaires).

l'autre question Est, étant donné la séparation pour les requêtes et l'absence potentielle de dépôts, comment le service d'application effectue la recherche pour trouver l'objet de domaine Courier?

mise à JOUR

sur la base de quelques lectures et réflexions supplémentaires après le commentaire de Dennis, je reformule mes questions.

il me semble que le CQRS encourage les dépôts qui ne sont que des façades sur les mécanismes d'accès et de stockage des données. Ils donnent "l'apparence" d'une collection (comme le décrit Fowler) mais ne gèrent pas les entités en mémoire (comme Dennis l'a souligné). Cela signifie que toutes les opérations sur le dépôt sont de passage, n'est-ce pas?

comment une unité de travail s'inscrit-elle dans cette approche? En général, un UoW est utilisé pour propager les modifications apportées à un dépôt (n'est-ce pas?) mais si le dépôt ne maintient pas les entités en mémoire, quel rôle joue un UoW?

en ce qui concerne une opération d'écriture, le gestionnaire de commandes aurait-il une référence au même dépôt, un dépôt différent ou peut-être un UoW au lieu d'un dépôt?

29
demandé sur SonOfPirate 2012-04-07 16:43:01
la source

2 ответов

j'ai lu au sujet des systèmes CQRS qui maintiennent un simple stock de valeur clé du côté de la commande pour représenter l'état d'une application, et d'autres qui simplement corrélent des messages (en utilisant une sorte de saga) et utilisent le stock de requête pour représenter un État d'applications à la place. Dans un cas comme dans l'autre, il y aura sans doute une technologie de persistance impliquée dans ces approches, mais le modèle de dépôt dans ces cas serait une abstraction inutile au-dessus de lui.

My l'expérience avec CQRS a seulement jamais été avec l'approvisionnement d'événement cependant, où nous avons rejoué des événements passés pour reconstruire des agrégats qui encapsulent et imposent la logique d'affaires et invariants. Dans ce cas, le modèle de dépôt est une abstraction familière qui peut fournir un moyen plus simple de récupérer n'importe lequel de ces agrégats.

en ce qui concerne le côté requête, je recommande de s'approcher le plus possible du magasin de données, c'est-à-dire d'éviter les dépôts, les services ou les façades, etc. entre votre INTERFACE utilisateur (quel qu'il soit) et votre magasin de données.

il pourrait être utile de voir un exemple de ces approches utilisées. Peut-être jeter un coup d'oeil aux projets suivants:

dans le cas de la NES, le référentiel fournit simplement une interface familière pour ajouter et lire des agrégats directement à l'Unité de travail et à partir de celle-ci.

D'autres liens qui pourraient aider:

7
répondu Elliot Ritchie 2017-05-23 13:30:47
la source

Je ne suis pas sûr à quel point cela est orthodoxe - mais dans un projet actuel, j'ai un dépôt pour ma racine d'entité agrégée. Ce dépôt n'a que deux méthodes, Get et ApplyEvents.

tous les événements implémentent une interface commune pour leur type - pour les commandes il y a OrderEvents, etc. J'ai personnellement mis la logique commerciale de chaque événement dans une méthode polymorphe, de sorte que l'ajout de nouveaux types d'événements devient très facile.

Pour Obtenir, le référentiel va à l'event store, et obtient tous les événements dans la portée pour le type (par exemple, un emplacement de magasin unique commande). Il fait ensuite une relecture des événements pour arriver à l'état actuel de l'entité pour tous les événements, il est donné. Il peut également fonctionner à partir d'un instantané, de sorte que vous n'êtes pas recréer chaque événement à chaque fois que vous chargez. Vous pouvez également avoir un dépôt D'événements généraux pour même abstraire sur la façon dont vous stockez des événements, et les récupérer sur la base de spécifications.

ApplyEvents prend dans un liste des événements et des changements de l'état de l'entité sur la base de ces, et le renvoie. Notez que vous donnez au dépôt l'option de recréer l'entité, pas seulement de la modifier! Cela fonctionne bien avec un type fonctionnel de programmation, mais signifie qu'il est préférable d'éviter l'égalité des objets (obj1 == obj2) en C# ou Java. Je dirais que seuls les objets de valeur, et pas les entités, devraient avoir l'égalité de toute façon.

Voici comment cela fonctionne dans la pratique( C#) - j'ai des ordres, et je veux pour ajouter un élément. currentOrder.Les éléments retourne une liste vide. Alors je fais

Assert.IsFalse(newEvent.Items.Any())
IOrderEvent newEvent = eventFactory.CreateOrderItemEvent(myItemID);
currentOrder = orderRepository.ApplyEvents(currentOrder, newEvent);
Assert.IsTrue(newEvent.Items.Any())

je devrais maintenant voir currentOrder.Les articles ont une entrée.

Les inconvénients sont ici que tout mon traitement est fait à travers les événements, plutôt que d'avoir ma logique métier dans l'Entité. Toutefois, dans mon cas, où presque tous mes objets doivent être sérialisables (essentiellement POCOs) et de travailler sur plusieurs systèmes, cela fonctionne vraiment bien.

1
répondu Mathieson 2014-06-13 21:57:54
la source