Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

DDD, CQRS et Event Sourcing : quand coder propre n'est plus suffisant

451 views

Published on

DDD, CQRS et Event Sourcing : quand coder propre n'est plus suffisant

Published in: Engineering
  • Be the first to comment

DDD, CQRS et Event Sourcing : quand coder propre n'est plus suffisant

  1. 1. DDD, CQRS et Event Sourcing : quand coder propre n'est pas sufsant Joseph Pachod https://twitter.com/joeclueless
  2. 2. Coder propre nécessaire mais... Coder propre : plein de règles applicables localement, bien moins à l'échelle d'une application.
  3. 3. Capture du métier ? Comment capturer le métier ? ● couches techniques souvent plus simples à organiser ● Conservation des connaissances métier de façon pérenne ?
  4. 4. DDD Domain-Driven Design (Conception dirigée par le domaine) Pas un framework ni une méthodo, plutôt une approche
  5. 5. Eric Evans Domain-Driven Design: Tackling Complexity in the Heart of Software – 2004 What I've learned about DDD since the book – 2009 Livre clé, aujourd'hui un peu dépassé sur certains points (dixit Evans lui même) Auteur a longuement pratiqué son approche avant que Martin Fowler ne vienne travailler avec lui et le convainque d'écrire un livre et communiquer sur celle ci, nommée Domain Driven Design à l'occasion.
  6. 6. Pré requis Travail itératif Accès direct aux experts du domaine Métier complexe
  7. 7. Ubiquitous Language (Langage omniprésent) Langage des experts du domaine, utilisé également par les développeurs et dans le modèle, c'est à dire le code. Nécessité de bien se comprendre et de reporter cela jusque dans le code. Le modèle doit communiquer comment fonctionne le domaine, afn de faciliter sa compréhension et sa mise en œuvre.
  8. 8. A utiliser tout le temps Rendre l'implicite explicite Dans le code et à l'oral ● Précision du langage ● Capacité à détecter les problèmes Si quelque chose sonne faux dans le langage omniprésent : revoir le vocabulaire et refactorer Rendre l'implicite explicite - faire ressortir les concepts - écouter le langage des utilisateurs experts (mots succincts pour des choses compliquées, correction du vocable des développeurs, éclairs de compréhension avec certains mots) - examiner les maladresses - réféchir sur les contradictions - apprendre le domaine fonctionnel
  9. 9. Hands on modelers (Concepteurs les mains dans le code) Le code est primordial pour valider le modèle et les refactoring, il faut que ceux qui modélisent touchent également au code. Ce dernier fait alors ofce de garde fou, rappelant les réalités du modèle, mais sert également à valider les changements. Garanti la pérennité du modèle, qui ne peut pas diverger du code s'il est directement dans le code.
  10. 10. Mise en œuvre "tactique" Eric Evans parle « tactique » Mise en œuvre reprise parfois au pied de la lettre, notamment en .Net
  11. 11. Modélisation "tactique" au choix de l'équipe Cf par exemple «  Functional and Reactive Domain Modeling » (voir le livre du même nom pour plus de détails).
  12. 12. Expliciter !
  13. 13. Code métier en un seul endroit
  14. 14. Refactoring continu Le refactoring continu assure que le code refète toujours bien le langage omniprésent. Qui plus est, le refactoring améliore la proximité avec le code, permettant de mieux en saisir le modèle et les nuances. Avec le temps, il arrive ce qu'Eric Evans nomme des percées : des éclairs de compréhension du domaine qui se répercutent par des changements signifcatifs du modèle. Bien souvent des aspects pénibles du modèle sont alors supprimés et d'anciennes incompréhensions ou incohérences s'expliquent.
  15. 15. Préserver l'intégrité du modèle quand la complexité croît Même termes, usages diférents, modélisation variant à terme Cohésion et unicité du langage omniprésent mis en péril dès que le nombre d'interlocuteurs augmente Coût de la coordination Un modèle unique pour tout le logiciel est difcile, voir utopique Quid de l'interfaçage avec du code tiers ?
  16. 16. Niveau stratégique
  17. 17. Bounded context (Contexte borné) Défnir les limites précises, quels concepts sont inclus, quels besoins. Le contexte borné doit protéger son modèle du reste du code, l'isolant afn de pouvoir le faire évoluer sans nécessairement impacter le reste du monde, sauf pour des contextes bien identifés. Une équipe peut travailler sur plusieurs contextes, un contexte ne peut être manipulé que par une équipe.
  18. 18. Anti corruption layer (Couche anti corruption)
  19. 19. Protéger le contexte de l’extérieur Refactoring toujours possible !
  20. 20. Shared kernel (Noyau partagé) Customer/supplier (Client-fournisseur) Anti corruption layer (Couche anti corruption) Conformist (Conformiste) Separate ways (Chemins séparés) Collaboration + -
  21. 21. Published langage (Langage publié) Open host service (Service hôte ouvert) Anti corruption layer (Couche anti corruption) Ouverture + -
  22. 22. Context map (Carte de contexte) Identife les diférents contextes bornés et leurs relations. Les noms des contextes font partie du langage omniprésent, facilitant grandement les discussions. Plusieurs types d'interactions entre contextes possibles, existence de pattern
  23. 23. Distiller pour aller à l'essentiel En introduisant des sous domaines génériques pour garder le domaine essentiel au coeur. Sortir des mécanismes cohérents en soi du domaine pour les mettre dans des librairies.
  24. 24. Core domain with a vision statement (Domaine central avec une vision) Il convient d’identifer le ou les domaines centraux de l’entreprise. Il s’agit généralement de ceux les plus proftables. Eric Evants préconise de leur associer une « vision claire », c’est à dire une phrase résumant leur nature et leur objectif, afn de s’assurer de ne pas en diverger par accident. Il faut également attribuer à ces domaines le plus de ressources notamment : - privilégier les domaines centraux dans les arbitrages, - y afecter les meilleurs développeurs.
  25. 25. Big Ball Of Mud (grosse balle de boue)
  26. 26. Mais… DDD non possible au milieu d'une Big Ball Of Mud
  27. 27. Cas des Frenchies (et autres non anglophones) Comment faire quand on code dans un langage informatique en anglais et que les utilisateurs parlent français, voir également allemand ? Choisir le langage de référence, celui utilisé par les experts du domaine
  28. 28. Avoir des domaines pérennes Les diférentes couches Domaine représentent le coeur de métier d’une entreprise. Leur durée de vie est souvent bien plus grande que celle des technologies utilisées. Il se peut même qu’il faille un jour porter ces règles métier sur une autre plateforme, par exemple dans une application mobile supportant un mode déconnecté. Aussi, il est important que l’adhérence des couches domaines au langage et aux outils utilisées soit contenue, afn de pouvoir aisément basculer sur de nouvelles technologies.
  29. 29. Lisez le livre !
  30. 30. Mais... tout le métier est dans un même processus Tout le métier peut appeler tout le métier  ● Tout peut dépendre de tout ● Complexité résultante importante ● Une erreur, même émanant d'une tâche sans importance, peut planter toute l'application (Out Of Memory en Java par exemple).
  31. 31. Event sourcing
  32. 32. The database is a subset of the logs (La base de données contient un sous ensemble des traces) Une base de données peut être utilisée de façon à mettre à jour les données. Autrement dit, si un utilisateur change de nom, on met à jour la ligne correspondante. On parle alors d'« update in place ». Ce faisant, toutefois, on perd l'ancien nom. Et peut être a t on plus d'informations dans les fchiers de logs : valeur du nouveau nom, de l'ancien, date de mise à jour... Au fnal, alors qu'on a une base de données avec plein de fonctionnalités, une bonne partie des infos se trouvent dans des fchiers textes plus durs à exploiter et souvent non conservés...
  33. 33. Quid du monde réel ? Pas de mise à jour, seulement des événements. Date et données d'un événement ne changent pas. Seuls de nouveaux événements s'ajoutent.
  34. 34. Evénement : date et données Idées : ● stocker les événements ● construire l'état courant à partir des événements
  35. 35. Evénements publiés et abonnements
  36. 36. Exemples d'événements UserAuthenticated(userId, date) ItemAdded(itemId, number, cartId, date) ItemRemoved(itemId, cartId, date) Verbe des événements toujours au passé : il s'agit de faits.
  37. 37. Etat courant dans des vues Une vue : événements agrégés Souscrire aux événements désirés et créer des vues.
  38. 38. Satisfaire exactement le besoin ! ● Duplication des données dans diférentes vues ● Données au format consommé
  39. 39. Snapshots (Instantanés) Besoin de reconstruire une vue ? Faire des instantanés (snapshots) : sauvegarde de l'état de la vue à un événement donné 
  40. 40. Event driven architecture (Architecture orientée événements)
  41. 41. L'espace disque n'est plus une limite
  42. 42. Asynchrone donc distribuable Publication/souscription : asynchrone ● Code construit avec possibilité de distribution => montée en charge
  43. 43. Découplage fort ● L'émetteur de l'événement ignore tout des souscripteurs, l'événement est le seul contrat à honorer => piles techniques diférentes possibles, ouverture sur le reste du monde
  44. 44. Events Log Conservation des événements suite à leur publication ● historique du système ● capacité à rejouer tout ou partie ● consommation décalée possible
  45. 45. En résumé : Événements, distribution (conservation) et vues ● Changements communiqués via publication d'événements ● Événements conservés ● Événements agrégés dans des vues
  46. 46. Retour au Domain Driven Design Événements pour échanger entre contextes bornés Vues pour mieux servir les lectures du domaine Code des contextes vraiment indépendant les uns des autres, voir même les piles techniques Historique
  47. 47. Domain Events On en reparle dans la suite : Eric Evans s'inspire des mêmes éléments pour recommander les Domain Events
  48. 48. Event Sourcing basé sur les faits, comment gérer les choses à faire ?
  49. 49. CQRS Command And Query Responsibility Segregation (Ségrégation des Responsabilités de Commande et de Requête)
  50. 50. Base de données  = goulet d'étranglement Constat : la base de données est un goulet d'étranglement des performances et de la modélisation
  51. 51. Une base de données peut consommer 80% du CPU pour la gestion des transactions.
  52. 52. Séparer lecture et écriture Écriture (Write side – Command) : une base de données Lecture (Read side - Request) : réplication de la base d'écriture vers une ou plusieurs bases de données On évoque généralement un facteur 100 en termes de gain de charge.
  53. 53. Pourquoi garder un même modèle ? Par exemple si présence d’une notion d’utilisateur. Lors de l’ajout d’un utilisateur, il faut : - s’assurer de l’unicité du login - s’assurer de la présence de certains champs Seule l’unicité du login nécessite un état en base, le reste ne nécessite pas des données persistentes pour pouvoir être contrôlé. A l’inverse un afchage d’utilisateurs requiert souvent des jointures mais pas le login… => les besoins en lecture et écriture sont très diférents : un même modèle implique des compromis
  54. 54. Write & Read Model (Modèles d'écriture et de lecture) Le Write model sera : ● Centré sur les invariants lors de l'écriture ● Granularité fne ● Charge limitée ● Besoin d'un support des transactions => bases relationnelles bonnes candidates Le Read model : ● Pas besoin de transactions ● Possibilité d’aggrégations ● Charge bien plus importante => nombreuses solutions possibles (NoSQL...)
  55. 55. Retour à l'Event Sourcing Les écritures partagent beaucoup avec les événements. Similitudes ● Ecriture à date donnée ● Contiennent des données exprimant une demande Diférences ● Peuvent échouer ● S'ils réussissent, déclenchent des événements
  56. 56. Commande Date, données, consommation unique Peut échouer Introduction de la notion de commande : ● Une date ● Une demande exprimée par les données ● Peut réussir ou non ● Consommation unique : un seul service doit décider de son succès ou non.
  57. 57. Granularité fne des changements Changements via des commandes, non des entités : on peut aisément ne changer qu'une valeur, pas besoin de tout transporter.
  58. 58. Ébauche d'une réponse au problème initial ● Capture du métier via le langage omniprésent ● Intégrité assurée via les contextes bornés ● Les contextes valident les commandes et émettent les événements ● Les vues agrègent les événements et permettent la lecture
  59. 59. Eventual consistency (Consistance à terme)
  60. 60. De quoi parle-t-on ? Données anciennes, pas fausses Performances meilleures que du synchrone
  61. 61. Améliorations aisées Vitesse de rafraîchissement Surveillance & ajout de nœuds
  62. 62. Consistance souvent illusoire Écrans non rafraîchis Transactions consécutives Cache divers Systèmes non entièrement transactionnels Niveau d'isolation des transactions baissé pour raisons de performances
  63. 63. Au niveau de l'interface utilisateur Bloquer en attendant les résultats Indiquer l'en cours Combiner les deux...
  64. 64. Initialement… un monolithe ! Tout dans un processus  ● Appels synchrones ● Quid de plusieurs nœuds (performance, redondance) ? Une couche métier ● Tout le code métier peut appeler tout le code métier ● Pas de séparation physique du code métier. ● Chaque entité ou concept est susceptible d'être utilisé dans n'importe quel autre bout de code, même pour des besoins divergeant. Une base de donnés ● Compromis entre les diférents besoin métier ● Goulet d'étranglement Framework  ● Quid si évolue dans un sens non désiré ? ● Quid s'il n'est plus maintenu ?
  65. 65. Monolithe  = coûts exponentiels avec le temps Montées en charge difcile ● Du nombre d'utilisateur ● Du nombre de fonctionnalités ● Du nombre de développeurs Utilisation de systèmes tiers non prévue
  66. 66. Système distribué Monolithe Application desktop/mobile Site promotionnel temporaire Web Scale, SaaS Application web ? Haute disponibilité, montée en charge, pérennité, ouverture technologique Facilité de mise en œuvre Court/moyen terme
  67. 67. Microservices ? Défnition exacte d’un microservices compliquée mais : - synchrone ou asynchrone - portée d’un microservice très limitée -- fait juste une chose (que le transport, que la transformation, que la …) Netfix : 1/3 du trafc internet, plus de 1000 microservices
  68. 68. SCS Self Contained Systems (Systèmes auto contenus)
  69. 69. Un système : - une IHM - un métier - des données
  70. 70. Communications asynchrones entre systèmes sinon un « Distributed Monolith »...
  71. 71. Event Sourcing to the rescue!
  72. 72. Enchainements d’Event Sources => Stream processing Reactive Streams - Akka Streams - Kafka Streams
  73. 73. Juste des fonctions entre les stream ? => Lambda architecture
  74. 74. Lambda architecture Des fonctions déclenchées au besoin => serverless !
  75. 75. Choisissez votre poison & amusez vous !
  76. 76. Pour approfondir ● Event Sourcing : Talks de Rich Hickey ● CQRS : Talks de Greg Young ● Stream Processing : The Log: What every software engineer should know about real-time data's unifying abstraction ● Documentation Kafka ● Analyses de systèmes distribués ● Fallacies of Distributed Computing Explained ● Domain-Driven Design Vite fait ● Clarifed CQRS ● Designing Data-Intensive Application Frameworks/librairies souvent trop générales Approfondir via des implémentations d'event bus (Kafka )
  77. 77. Remerciements Eric Evans, Rich Hickey, Greg Young : penseurs des concepts présentés  A tous ceux avec qui j’ai pu discuter et approfondir les concepts, dont - Uwe Schäfer (@codesmell) - Olivier Schneider (@Oli3dfx) A vous, pour être venu et avoir tenu si longtemps

×