Le titre fait le plein de buzzwords, mais c'est pas pour cela que je l'ai choisi. Non j'ai la conviction et l'expérience que l'architecture basé sur CQRS - le principe de séparation de commande et de query et le EventSourcing - le fait de calculer l'état de l'application basé sur les évènements passés, facilite les tests automatiques tout comme il facilite l'expression du domaine métier dans le code - le DDD. Je vais essayer d'expliquer pourquoi de manière visuelle. Mais tout d'abord une petite explication sur ce que je veux dire par "mieux" dans le titre de ce billet. Ici mieux veut simplement dire "plus métier", c'est pas toujours "mieux" mais "mieux" fait mieux dans un titre ;)
Bon revenons aux choses sérieuses, en commençant par un diagramme basique de CQRS implémenté de façon EventSourcing
CQRS et EventSourcing
Lorsqu'une commande arrive, elle se fait valider par le CommandHandler qui la transforme en 0 à n évènements. Par exemple une demande de réservation hotel, peut se solder par une réservation ou non. Les évènements, s'il y en a, se font ajouter à la log des events et servent aussi à entretenir des "projections". Les projections servent avant-tout à répondre rapidement à une question (query), car avec ces projections pré-calculées pas besoin de parser l'ensemble des évènements pour chaque question. A noter tout de même qu'on peut faire sans projection pour les cas qui ne nécessitent que peu de performance.
Code orienté métier
Mais qu'est-ce qu'il y ait de si fantastique pour les tests et en quoi cela permet de mieux exprimer le domaine? Pour y répondre regardons de plus près les 3 éléments principaux :
- CommandHandler
- ProjectionHandler
- QueryHandler
Fonctions pures
Tel des satellites la logique est extraite et il ne reste que le travail de coordonneer appel à la BDD et appel à la logique pure. Presque l'ensemble de la logique métier se trouve alors dans des fonctions pures, toutes bien orientée métier.
Les tests
Mais alors en quoi cela aide pour les tests? Ben c'est le doux rêve de tout écrivain de test d'avoir des fonctions pures. Pas de dépendances hard-codés, pas de dépendances à injecter, pas de mocks à initialiser. En gros cela donne des tests faciles à écrire et surtout faciles à lire. De plus ces tests ne sont pas trop sensibles à des refactorings, car plus le code est orienté métier et haut niveau plus son API est stable.
Attention ici je ne décris que les avantages de cette architecture, il y a bien-sur des inconvénients, mais ce sera le sujet d'un autre billet. Peut-être :)