<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: craft Softwr &amp; Music</title>
    <description>The latest articles on DEV Community by craft Softwr &amp; Music (@guillaume_agile).</description>
    <link>https://dev.to/guillaume_agile</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F211510%2F5fcf8277-3773-4f24-bbe7-2bc1369e081b.jpg</url>
      <title>DEV Community: craft Softwr &amp; Music</title>
      <link>https://dev.to/guillaume_agile</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/guillaume_agile"/>
    <language>en</language>
    <item>
      <title>Le “Messager”: un projet pas comme les autres chez Primobox</title>
      <dc:creator>craft Softwr &amp; Music</dc:creator>
      <pubDate>Tue, 18 Jan 2022 14:41:48 +0000</pubDate>
      <link>https://dev.to/guillaume_agile/le-messager-un-projet-pas-comme-les-autres-chez-primobox-37f7</link>
      <guid>https://dev.to/guillaume_agile/le-messager-un-projet-pas-comme-les-autres-chez-primobox-37f7</guid>
      <description>&lt;p&gt;Trouver une entreprise dans laquelle on peut progresser, apprendre, innover, tout en forgeant un logiciel de qualité et des compétences partageables à tout le monde, n’est pas chose courante.&lt;/p&gt;

&lt;p&gt;Primobox est de cette trempe là.&lt;/p&gt;

&lt;p&gt;Laissez-moi vous raconter brièvement cette aventure que j’ai eu la chance de vivre.&lt;/p&gt;

&lt;h1&gt;
  
  
  Genèse
&lt;/h1&gt;

&lt;p&gt;Vous connaissez l’adage “Diviser pour mieux régner” ? C’est ce que nous invite à faire l’approche DDD (Domain Driven Design). Et c’est avec ce principe en tête (délimiter des Contextes Explicites et &lt;a href="https://fr.wikipedia.org/wiki/Topologie_discr%C3%A8te"&gt;Discrets&lt;/a&gt; &lt;sup id="fnref1"&gt;1&lt;/sup&gt;) qu’un projet de Messager autonome est né chez Primobox (pour faire simple, le Messager est celui chargé de remettre le courrier à ses destinataires).&lt;/p&gt;

&lt;p&gt;Doté d’une grande responsabilité, simple au premier abord mais qui permet d’envisager des options et des possibilités multiples, en toute autonomie.&lt;/p&gt;

&lt;p&gt;Une fois ce domaine (contexte) métier spécifique identifié , parmi les autres besoins clients que doivent satisfaire les solutions proposées par Primobox, il était plus facile de lancer un chantier ciblé de modernisation du code.&lt;/p&gt;

&lt;p&gt;Avec un périmètre et des relations bien définis, ce véritable “métier dans le métier” allait pouvoir prendre son envol.&lt;/p&gt;

&lt;h1&gt;
  
  
  Vision
&lt;/h1&gt;

&lt;p&gt;Un projet réussi commence par une vision. Alexandre Fillatre, CTO chez Primobox a su initier et nourrir cette vision. Basée sur une idée simple : les différentes phases qui composent l’activité de l’offre de service chez Primobox (dématérialisation de la relation entre employés et employeurs) ont chacune une raison d’exister propre, tout en étant capable d’interagir avec les autres parties et d’évoluer de manière autonome. Alexandre nous a partagé cette vision et nous a fait confiance pour la mettre en œuvre.&lt;/p&gt;

&lt;h1&gt;
  
  
  Utilisateurs
&lt;/h1&gt;

&lt;p&gt;En amont, un vrai travail pour comprendre le besoin utilisateur avait été initié et je l’ai traduit en éléments que nous allions mettre dans le cœur du “Messager”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stephaniewalter.design/fr/blog/introduction-aux-user-journey-maps-modeles-pdf-a-telecharger/"&gt;L'atelier de Wording et les User Journeys&lt;/a&gt; m’ont été très utiles pour cerner le domaine métier dans son ensemble et dans ses particularités.&lt;/p&gt;

&lt;h1&gt;
  
  
  Clarté
&lt;/h1&gt;

&lt;p&gt;La clarté se gagne par l’analyse. Grâce aux travaux préliminaires de l’équipe Produit et Ergonomie, j’ai pu coucher sur le papier une carte (à la Wardley) des interactions entre le Messager et les autres éléments qui constituent la solution globale dont nos clients ont besoin.&lt;/p&gt;

&lt;p&gt;Cela permet de savoir quelles fonctionnalités sont plus importantes, lesquelles sont annexes, lesquelles sont laissées à la responsabilité d’autres modules (existants ou à créer) voire externalisées.&lt;/p&gt;

&lt;p&gt;Des choix stratégiques importants sur le périmètre fonctionnel ont été faits afin de réduire la charge de travail et la complexité présente sur certains produits.&lt;/p&gt;

&lt;p&gt;Cela dessine une forme d’architecture, plus basée sur les besoins que la technique.&lt;/p&gt;

&lt;p&gt;Cela nous libère aussi des détails techniques, car sur un &lt;a href="https://github.com/ddd-crew/context-mapping"&gt;Context Mapping&lt;/a&gt; (toujours cette notion de cartographie) se dessinent les frontières entre les &lt;a href="https://martinfowler.com/bliki/BoundedContext.html"&gt;Bounded Contexts&lt;/a&gt;; et l’on voit facilement les choix contraints par l’existant (legacy), et par ailleurs les espaces où les contraintes changent de nature. Par exemple, là où la performance est plus importante que la compatibilité.&lt;/p&gt;

&lt;h1&gt;
  
  
  Audace
&lt;/h1&gt;

&lt;p&gt;Prendre des paris audacieux, après tout, pourquoi pas ? Pourquoi rester conforme à ce qui a été fait par le passé et se priver de progresser ?&lt;/p&gt;

&lt;p&gt;Parlons du langage de développement. Primobox a un historique Java solidement ancré.&lt;/p&gt;

&lt;p&gt;Moi j’arrivais du monde .Net.&lt;/p&gt;

&lt;p&gt;Alexandre Fillatre a su discerner qu’un bon développeur ne saurait s’arrêter à une syntaxe donnée, l’essentiel étant ce que l’on sait obtenir de tel ou tel langage de développement.&lt;/p&gt;

&lt;p&gt;La POO est une chose universelle mais les langages modernes évoluent pour être plus hydrides et flirtent plus facilement avec la Programmation Fonctionnelle. C’est le cas de C#, puis de Java qui lui a emboîté le pas.&lt;/p&gt;

&lt;p&gt;Quitte à s’éloigner de C# 9 pour aborder la JVM, autant opter pour un langage du même niveau.&lt;/p&gt;

&lt;p&gt;C’est là que nous avons pensé à ... Kotlin !&lt;/p&gt;

&lt;p&gt;Etant pour ma part un adepte précoce de C# et de l’écosystème .Net, je n'avais jamais eu à me frotter au monde Java ailleurs que dans mes études. Grâce à Kotlin, franchir le cap a été pour moi d’une facilité déconcertante.&lt;/p&gt;

&lt;p&gt;J’ai retrouvé tous mes réflexes acquis en C# avec une syntaxe encore plus élégante. Ayant l’habitude de Linq, Kotlin est naturellement provisionné pour faire la même chose. En mieux ! Et il est facile de trouver de &lt;a href="https://kotlinlang.org/docs/collection-operations.html#common-operations"&gt;l’aide&lt;/a&gt; et des &lt;a href="https://github.com/mythz/kotlin-linq-examples"&gt;exemples&lt;/a&gt;. Et des très bons &lt;a href="https://www.baeldung.com/kotlin/"&gt;tutos&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Arrière boutique
&lt;/h1&gt;

&lt;p&gt;Ah oui, si vous cherchez des ressources sur Kotlin dans les Internets, vous verrez que ce langage est la panacée pour les applications mobiles. Et pourtant ! C’est excessivement réducteur.&lt;/p&gt;

&lt;p&gt;Kotlin produit (aussi) du bytecode qui va tourner sur la JVM. Donc c’est un parfait candidat pour tout le code backend. C’est ce que nous avons fait pour cette application complexe, avec une architecture très évoluée, ce qui nous a permis d’être parfaitement intégré dans l’existant Java et surtout très performant.&lt;/p&gt;

&lt;h1&gt;
  
  
  Idiomes
&lt;/h1&gt;

&lt;p&gt;Quitte à choisir un langage qui nous était inconnu (à moi et mon coreligionnaire, pur Javaiste pour sa part) jusqu’ici, &lt;a href="https://kotlinlang.org/docs/idioms.html"&gt;autant le faire bien et complètement&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Kotlin a de multiples talents. Facile d’apprentissage, il emprunte un peu à Typescript, C#, Scala et bien sûr Java, puisqu’il produit du bytecode ciblé pour la JVM.&lt;/p&gt;

&lt;p&gt;Son éditeur (Jetbrains) a tout fait pour que les développeurs Java s’y retrouvent, et puissent même ré-utiliser n’importe quelle classe du JDK ou n’importe quelle lib Java. Et ça fonctionne très bien. On peut même écrire du code “façon Java” (utiliser des exceptions, mettre des if en pagaille, des null partout...). \&lt;br&gt;
Bref, si on n’y prenait garde, on écrirait presque du Kotlin qui ressemble à du “mauvais” Java (je veux dire par là du Java d’avant guerre, avant la version 8 si vous préférez...).&lt;/p&gt;

&lt;p&gt;Pourtant avec Kotlin, tout est fait pour écrire du code “élégant”. J’en veux pour preuve la non nullabilité des types par défaut, &lt;a href="https://medium.com/@johnmcclean/dysfunctional-programming-in-java-2-immutability-a2cff487c224"&gt;l’immutabilité&lt;/a&gt; par défaut, la présence des data classes (équivalent des Records de C# ou Java 16) parmi tant de choses qui m’ont enchantées.  \&lt;br&gt;
On notera aussi que Kotlin dispose nativement de structures de données avancées (Pair, Triple, Linked List, Tree, etc...) et de possibilités de &lt;a href="https://www.baeldung.com/kotlin/category/functions"&gt;manipulation de fonctions&lt;/a&gt; qui sont juste délicieuses.  &lt;/p&gt;

&lt;p&gt;Et j’allais oublier de mentionner les très &lt;a href="https://www.baeldung.com/kotlin/coroutines"&gt;puissantes co-routines&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Attention
&lt;/h1&gt;

&lt;p&gt;Tout au long de notre travail, une attention particulière a été portée aux autres membres de l’équipe. Nous avons communiqué régulièrement : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;sur l’avancée du projet, même si nous n’avions pas de revue de sprint (on en parle plus loin), sur les innovations ou techniques que nous avions choisi de mettre en œuvre, car celles-ci pouvaient aussi trouver leur place dans d’autres projets du groupe.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nous sommes aussi dans une démarche d’invitation permanente : tous les autres membres de la R&amp;amp;D peuvent venir collaborer au projet, apprendre Kotlin ou tout autre concept que nous avons mis en œuvre.&lt;/p&gt;

&lt;h1&gt;
  
  
  Langage Naturel
&lt;/h1&gt;

&lt;p&gt;Le langage des utilisateurs et des experts métier a été le nôtre tout le long de la réalisation.&lt;/p&gt;

&lt;p&gt;Pas de jargon de développeurs.&lt;/p&gt;

&lt;p&gt;Notre domaine métier est en français. Toute la modélisation et le codage du logiciel se sont donc faits dans cette belle langue.&lt;/p&gt;

&lt;p&gt;Nous avons réservé l’anglais pour les parties purement techniques (logées dans des composants isolés et accessibles via les Ports &amp;amp; Adaptateurs, conformément à l’architecture hexagonale exposée plus loin); par exemple la mécanique d’accès à la base de données ou au bus de message. &lt;/p&gt;

&lt;p&gt;C’est très pratique pour se rendre compte au premier coup d'œil si notre métier (en français) reste pur et ne se mélange pas avec des considérations techniques (en anglais).&lt;/p&gt;

&lt;h1&gt;
  
  
  Stratégie
&lt;/h1&gt;

&lt;p&gt;L'approche DDD est un guide dans la nuit. Ce n’est pas à proprement parler une méthode, et surtout pas un framework. C’est un ensemble d’outils et de bonnes pratiques, tout à fait compatible avec l’agilité et le software craftsmanship.&lt;/p&gt;

&lt;p&gt;Nous avons eu cette approche d’emblée, dès les premières heures du projet. C’est, il me semble, la condition sine qua non pour réussir.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--juAWKIC9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8o9r2etj2tth05ulw2f9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--juAWKIC9--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8o9r2etj2tth05ulw2f9.jpeg" alt="DDD starter" width="880" height="495"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comme dit précédemment, j’ai commencé par la mise en place d’une Wardley Map, puis avec Damien Boué nous avons travaillé sur des Bounded Contexts Maps. Cela nous a permis de nous synchroniser aussi avec les équipes Produit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tactique
&lt;/h1&gt;

&lt;p&gt;En DDD la stratégie s’accompagne toujours d’une tactique, je ne vais pas vous faire ici un cours de DDD, les ressources sur Internet ne manquent pas.&lt;/p&gt;

&lt;p&gt;Je ne vais pas vous parler ici des essentielles décompositions en agrégats, entités et value objects (chasser la Primitive Obsession). &lt;/p&gt;

&lt;p&gt;Je vous dirai seulement qu’une des leçons que nous avons apprises est de songer sérieusement à limiter la taille de nos agrégats ! (cf ces &lt;a href="https://www.dddcommunity.org/library/vernon_2011/"&gt;bons conseils peu connus de Vaughn Vernon&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Jusqu’à ce qu’ils ne contiennent qu’une entité. Cette idée peut vous paraître saugrenue mais vous lui direz merci quand vous verrez la complexité accidentelle poindre son nez.&lt;/p&gt;

&lt;p&gt;Bien sûr cela demande à réfléchir plus et surtout à ne pas se laisser entraîner par une conception basée sur le Mapping Objet Relationnel (ORM ou Objet Documents Mapping dans le cas des entrepôts NoSQL) qui, entre autres inconvénients, pousse notre modèle à être anémique. Mais aussi lorsque l'exécution de nos adapters devient concurrente (comme dans toutes les API Web), nous aurait obligé à poser des verrous transactionnels (et donc faire effondrer la performance). Cela est inévitable lorsque les agrégats sont trop gros et que l’on veut y accéder en écriture.&lt;/p&gt;

&lt;p&gt;Donc, gardons les atomiques !&lt;/p&gt;

&lt;h1&gt;
  
  
  Coeur
&lt;/h1&gt;

&lt;p&gt;L'une des (nombreuses) brillantes idées de ce projet a été de suivre le précepte de “&lt;a href="https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell"&gt;Functional Core/ Imperative Shell&lt;/a&gt;”, introduit en 2012 dans la communauté Ruby, puis repris plus récemment par &lt;a href="https://www.kennethlange.com/"&gt;Kenneth Lange&lt;/a&gt; et aussi par &lt;a href="https://www.slideshare.net/ThomasPierrain/hexagonal-architecture-vs-functional-core-iom"&gt;Thoman Pierrain &amp;amp; Bruno BOUCARD&lt;/a&gt; ;&lt;/p&gt;

&lt;p&gt;Cette approche a d’énormes avantages, citons-en 2 :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;d'abord repousser les effets de bord (les fameux, ceux qui rendent vos tests trop compliqués, plus du tout isolés, voire inconsistants et cachent de nombreux bugs) en dehors des considérations métier.&lt;/li&gt;
&lt;li&gt;corollaire : cela vous permet de vous concentrer sur la seule logique métier de manière fonctionnelle, c'est-à-dire en privilégiant &lt;a href="https://medium.com/@johnmcclean/dysfunctional-programming-in-java-2-immutability-a2cff487c224"&gt;l’immutabilité&lt;/a&gt; et la &lt;a href="https://sookocheff.com/post/fp/why-functional-programming/"&gt;transparence référentielle&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cette façon de penser le logiciel en y plaçant un cœur purement fonctionnel (dans les 2 sens du terme) permet d’isoler vraiment les tests métiers et donc &lt;a href="https://www.destroyallsoftware.com/blog/2014/test-isolation-is-about-avoiding-mocks"&gt;de se passer entièrement des mocks à cet endroit&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dans le cœur métier propre du Messager sont également apparues d’autres frontières, et donc d’autres Bounded Context pour des composants qui avaient besoin de pouvoir évoluer sans casser les autres. Tout ce travail d’&lt;em&gt;isolation&lt;/em&gt; (via des ACL, anti corruption layers) est primordial pour ne pas s’enfermer dans une complexité accidentelle et dans ce qui devient inexorablement, malgré toute bonne volonté, une “big ball of mud” (grosse boule de boue).&lt;/p&gt;

&lt;h1&gt;
  
  
  Hexagone
&lt;/h1&gt;

&lt;p&gt;Il y a le cœur fonctionnel, et il y a la coquille (shell en Anglais). C’est ce que l’on retrouve aussi dans les &lt;a href="https://alistair.cockburn.us/hexagonal-architecture/"&gt;architectures hexagonales&lt;/a&gt; (ou &lt;a href="https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html"&gt;Clean Architecture&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Dans la partie coquille (hors cœur métier donc) on va retrouver les ports et adaptateurs.&lt;/p&gt;

&lt;p&gt;C’est cette philosophie que nous avons appliquée fortement.&lt;/p&gt;

&lt;p&gt;Et nous avons fabriqué des adaptateurs techniques pour toute situation spécifique.&lt;/p&gt;

&lt;p&gt;L'absorption de commandes venues d’une API REST est un adaptateur indépendant. Il a une dépendance directe avec les objets métiers.  \&lt;br&gt;
Par contre pour toute opération en base de données (nous avons, en prévision d’un CQRS séparé les opérations de lecture et celles d’écriture), il y a des adaptateurs dédiés.&lt;/p&gt;

&lt;p&gt;Il en va de même pour les opérations d’envoi et de réception de messages dans un bus (afin de prévenir les agents dans d’autres Bounded Contexts qu’un événement important s’est passé dans notre domaine.&lt;/p&gt;

&lt;h1&gt;
  
  
  Qualité
&lt;/h1&gt;

&lt;p&gt;TDD offre ce double avantage d’être la méthode d’écriture du logiciel (et non de test) qui nous a permis de faire du design émergent guidé par le DDD tactique et de toujours se fixer des petits pas. Et bien sûr, on obtient une couverture de tests très satisfaisante, puisqu'aucune ligne de code ne devrait être écrite si elle n’est pas justifiée par un test.&lt;/p&gt;

&lt;p&gt;Kotlin (encore lui !) vient avec une géniale librairie : Kotest. Attention à ne pas faire comme moi au début, de faire la confusion entre KotlinTest et Kotest.&lt;/p&gt;

&lt;p&gt;C’est bien Kotest qui permet de choisir parmi moult styles de tests, il y en a vraiment pour tout le monde : style Behaviour Driven Development (celui que nous avons choisi), style Scala, Ruby, Cucumber ou JavaScript/TypeScript. Ou ce bon vieux JUnit.&lt;/p&gt;

&lt;p&gt;Écrire des tests, c’est bien joli, mais encore faut-il s'assurer qu’ils servent à quelque chose et qu’ils sont robustes. &lt;/p&gt;

&lt;p&gt;Les outils déjà en place pour les autres projets Java de l’entreprise (Jenkins, SonarQube,un scanner de vulnérabilité des dépendances) se sont parfaitement intégrés à notre nouveau projet Kotlin.&lt;/p&gt;

&lt;p&gt;La Couverture de code a pu donc être constamment mesurée, mais j’en dirai plus au prochain chapitre.&lt;/p&gt;

&lt;p&gt;D’autres outils sont venus renforcer cette recherche de qualité :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://www.archunit.org/getting-started"&gt;ArchUnit&lt;/a&gt;, pour vérifier en permanence le bon usage des dépendances et &lt;a href="https://blog.scottlogic.com/2019/12/05/unit-test-your-architecture-with-archunit.html"&gt;vérifier que nous ne cassions pas les principes de l’architecture hexagonale&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.baeldung.com/introduction-to-gatling"&gt;Gatling&lt;/a&gt; pour s’assurer que notre solution tient la charge en situation réelle&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Rigueur
&lt;/h1&gt;

&lt;p&gt;Un grand enjeu de la qualité logicielle semble être la couverture de code, mais cette mesure peut s’avérer erronée, comme je le prouve dans &lt;a href="https://www.linkedin.com/posts/guillaumese_des-mutants-dans-le-code-activity-6870318621411876864-RD_g"&gt;ma présentation sur les tests par mutation de code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Dans ce projet, il nous a paru opportun de consolider notre approche TDD, parce qu’après tout nous sommes tous faillibles, et qu’un outil qui nous montre que nous manquons de tests, que des bugs sont encore présents, est tout simplement une aubaine.&lt;/p&gt;

&lt;p&gt;Nous avons choisi la lib PiTest, qui fonctionne sur le ByteCode Java, et donc très bien avec Kotlin.&lt;/p&gt;

&lt;p&gt;Simple d’usage, facile à ajouter à un pipeline d’intégration continue, cet outil va nous aider à mieux coder et mieux tester (l’un ne va pas sans l’autre). Il nous a rappelé sans faillir aux règles du TDD (ne pas écrire une instruction qui ne soit justifiée par un test). &lt;/p&gt;

&lt;p&gt;Par contre, il est avisé d’utiliser ce genre d’outil sur du nouveau code plutôt que sur du legacy, et de cibler du code purement métier, c'est-à-dire au centre (functional core) de l'architecture hexagonale.&lt;/p&gt;

&lt;h1&gt;
  
  
  Paradigme (changement de)
&lt;/h1&gt;

&lt;p&gt;Ce n’est pas chose facile que de bousculer (un peu) les habitudes des développeurs. Alors que la programmation orientée objet est maîtrisée par tous mes collègues, je leur ai fait la proposition de parier sur l’immutabilité.&lt;/p&gt;

&lt;p&gt;L’immutabilité, c’est quoi ?  Une idée qui nous vient de la programmation fonctionnelle mais qui s’applique très bien à la POO. Le principe est simple : quand les objets ne “mutent” pas (comprendre : ne changent pas d’état) alors ils sont plus facile à maîtriser, à comprendre et surtout on évite beaucoup, beaucoup de bugs car on limite grandement les effets de bord dans les méthodes de ces objets immuables.&lt;/p&gt;

&lt;p&gt;Mieux encore, cette immutabilité est facile à obtenir avec des langages tels que Kotlin (celui que nous avons choisi pour ce projet) ou même Java (à partir de la version 8 le mot clé _final _est apparu, et il a été ensuite complété avec des librairies qui poussent une vraie immutabilité des objets, comme par exemple  &lt;a href="https://www.baeldung.com/immutables"&gt;https://www.baeldung.com/immutables&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Elle permet de transitionner naturellement vers une écriture de code plus “fonctionnelle” c'est -à -dire avec une meilleur répartition des responsabilités (voir chapitre suivant), et une plus grande intégrité référentielle.&lt;/p&gt;

&lt;h1&gt;
  
  
  Solide
&lt;/h1&gt;

&lt;p&gt;Notre attention s'est focalisée sur la production d' un code SOLID. Ce n’est pas facile de vous parler des principes d’un code SOLID, surtout que cela fait partie de la grande famille du code “propre” (Clean Code). Le premier principe est peut être le plus important et le plus simple à comprendre : Simple Responsibility. Et tous les autres en découlent. Nous avons toujours cherché dans ce projet à exprimer et répartir les responsabilités de façon très claire et très cohérente entre les différents modules.&lt;/p&gt;

&lt;p&gt;Que ce soit dans le découpage métier (Bounded Contexts, DDD Stratégique) ou dans l’approche technique (Archi Héxagonale DDD Tactique), notre objectif a tout le temps été de limiter la responsabilité à un niveau minimal et acceptable, afin de mieux séparer et isoler ces responsabilités. Les cartes CRC nous ont aussi beaucoup aidé à y voir plus clair dans notre design.  &lt;/p&gt;

&lt;h1&gt;
  
  
  Découplé
&lt;/h1&gt;

&lt;p&gt;Le découplage est un fondamental à la fois de l’architecture d’un logiciel mais aussi de la journée ordinaire d’un développeur. Il s’agit simplement de ne pas accumuler la complexité et les interactions douteuses qui peuvent se loger dans le code. Pour cela nous avons fait le choix d’abstractions pour définir et maîtriser ces fameuses dépendances.&lt;/p&gt;

&lt;p&gt;L’idée est d’exprimer simplement les choses en termes de “quoi” et non de “comment”.&lt;/p&gt;

&lt;p&gt;Exemple : au lieu de dire à notre code “je veux une base de données Mongo pour stocker des informations”, nous avons établi une abstraction (interface) qui dit “je veux pouvoir stocker cette information”. Le “comment” ne nous intéresse absolument pas.&lt;/p&gt;

&lt;p&gt;En se référant à cette abstraction ( “Je_veux_stocker_information_X” ), nous voilà libres de son implémentation. Et c’est double bénéfice.&lt;/p&gt;

&lt;p&gt;D’abord nous pouvons choisir librement l’implémentation et en changer à tout moment au cours de la vie du projet (nous avons choisi Mongo DB mais peut être que ce choix sera remis en cause).&lt;/p&gt;

&lt;p&gt;Et surtout, pendant les tests fonctionnels, nous n’avons pas l’obligation de mettre en route la fameuse base de données Mongo que nous avons choisie pour la production. Nous pouvons juste utiliser un fake, c'est-à-dire une implémentation naïve, simpliste.&lt;/p&gt;

&lt;h1&gt;
  
  
  Evenementiel
&lt;/h1&gt;

&lt;p&gt;Une autre grande force de ce projet est que nous avons d’emblée pris en compte la nature événementielle d’une application. Dans un logiciel, il se passe des choses. &lt;/p&gt;

&lt;p&gt;Il est plus important de capturer des évènements que d’enregistrer l’état des objets.&lt;/p&gt;

&lt;p&gt;Malheureusement, trop d’applications sont développées en mode CRUD (Create Read Update Delete), aidé (mais pas dans le bon sens) par les framework de mapping ORM. Ce mode de développement rend compliqué toute migration fonctionnelle, car justement il est difficile de placer des règles métiers quand on pense que tout se limite à des opérations d’ajout/modification/suppression/lecture en base de données.&lt;/p&gt;

&lt;p&gt;En pensant événements, on est au contraire ouvert à tout ce qui peut se passer comme vérifications, contraintes, évolution du métier. On est bien plus proche des actions des utilisateurs.&lt;/p&gt;

&lt;p&gt;On peut créer des programmes plus aptes à répondre au besoin métier, et moins coincé dans une solution technique. &lt;/p&gt;

&lt;p&gt;En pratique, nos agrégats métiers émettent des événements, en réaction à des commandes, après avoir opéré les vérifications métier qui s’imposent. Nous avons mis en place un mécanisme de remontée automatique des événements (event bubbling) depuis les entités filles qui composent un agrégat global (grâce à ReactiveX et ses &lt;a href="https://reactivex.io/documentation/observable.html"&gt;Observables&lt;/a&gt;).&lt;/p&gt;

&lt;h1&gt;
  
  
  Partage
&lt;/h1&gt;

&lt;p&gt;Cela a été une discussion intéressante (parmi tant d’autres) : Comment s’y prendre pour se partager le travail et le partager avec les autres ? Bien sûr il y a l’usage de l’attirail Jira, Git, Jenkins... Mais ce qui importe c’est surtout la façon dont on s’en sert.&lt;/p&gt;

&lt;p&gt;Nous avons opté pour des &lt;a href="https://adr.github.io/"&gt;ADR&lt;/a&gt; dans les points clé de notre repository, afin de garder trace de nos discussions et de remettre en contexte les choix tactiques opérés dans le code.&lt;/p&gt;

&lt;p&gt;Nous avons aussi mis l’accent sur le pair programming. Mais nous avions quand même voulu garder les &lt;a href="https://trunkbaseddevelopment.com/continuous-review/"&gt;Code Reviews&lt;/a&gt;, pour prendre de la hauteur sur le code produit (essentiellement par Damien Boué et moi même). Je suis plus partisan du &lt;a href="https://www.freecodecamp.org/news/why-you-should-not-use-feature-branches-a86950126124/"&gt;Trunk Based Development&lt;/a&gt;, mais en adoptant des tests plus longs à exécuter comme le Mutation Testing, il était intéressant d’isoler tout nouveau code dans une branche dédiée afin de voir s’exécuter correctement  toute la lignée de tests, sans compromettre la branche principale (on aurait pu faire du &lt;a href="https://blog.zenika.com/2018/12/03/tdd-est-mort-longue-vie-tcr/"&gt;TCR&lt;/a&gt; mais c’est un peu violent).&lt;/p&gt;

&lt;p&gt;Nous avons plutôt opté pour des &lt;a href="https://trunkbaseddevelopment.com/short-lived-feature-branches/"&gt;Short Lived Branch&lt;/a&gt; avec des règles du jeu : pas plus de 2 branches différentes en simultané et ne portant pas sur les mêmes "zones" du code.&lt;/p&gt;

&lt;p&gt;Au bout d’un moment, nous avions assez d’abstractions (&lt;a href="https://trunkbaseddevelopment.com/branch-by-abstraction/"&gt;branching by abstraction&lt;/a&gt;) pour éviter des “rebase” douloureux.&lt;/p&gt;

&lt;p&gt;Bien sûr, quand nous avions à faire des refactoring qui touchaient plusieurs endroits du code, il fallait d’abord solder toutes les branches en cours, avant de s’attaquer à des modifications qui auraient eu trop d’impacts sur l’architecture ou les interfaces fondatrices.&lt;/p&gt;

&lt;p&gt;Pour éviter que les refactoring ne durent trop longtemps et ne conduisent à des réconciliations de code houleuses, j’ai recommandé d’adopter la méthode &lt;a href="https://blog.engineering.publicissapient.fr/2020/03/20/domptez-vos-refactoring-avec-la-mikado-method/"&gt;Mikado&lt;/a&gt;, afin, une fois de plus, de progresser par petits pas, de merger très très souvent, de ne pas se lancer dans des travaux d’Hercule, et de se rendre compte des problèmes au plus tôt.&lt;/p&gt;

&lt;p&gt;Le refactoring devient également plus aisé en adoptant la méthode "&lt;a href="https://martinfowler.com/bliki/ParallelChange.html"&gt;parallel change&lt;/a&gt;” ou “&lt;a href="https://medium.com/dan-the-dev/refactoring-parallel-change-trunk-based-development-97f38bea86ae"&gt;expand and contract&lt;/a&gt;” : on ne casse pas l’existant; on implémente dans une nouvelle méthode ce qui doit être refactoré, et petit à petit on transite vers le nouveau code, avant d’effacer l’ancien quand il n’est plus utilisé nulle part.&lt;/p&gt;

&lt;p&gt;Encore une fois, l’architecture hexagonale, avec son découplage maximum, nous a permis de minimiser la casse.&lt;/p&gt;

&lt;p&gt;Je suis très content d’avoir travaillé comme cela, car les revues de code nous ont permis de se poser la question “est ce que notre design reste cohérent” à chaque étape de la construction du logiciel.&lt;/p&gt;

&lt;h1&gt;
  
  
  Agilité
&lt;/h1&gt;

&lt;p&gt;Il était important d’avoir du feedback rapide même sur un produit qui n’est pas encore mis en exploitation. Nous avons opté pour un travail en flux type Kanban, avec des jalons variables qui étaient matérialisés par des Minor Releases, selon nos désidérata et contraintes.&lt;/p&gt;

&lt;p&gt;Nous avons pu compter sur une Intégration Continue (CI/CD) super efficace grâce au soutien de l’équipe DevOps en place.&lt;/p&gt;

&lt;h1&gt;
  
  
  Résultat
&lt;/h1&gt;

&lt;p&gt;Le projet n’est pas encore terminé, et vous n’en verrez pas une démonstration graphique, car ce n’est qu’un composant au milieu de tant d’autres. Mais comme il va devenir un maillon fort de l’édifice logiciel de Primobox, c’est la fiabilité, la rapidité et la performance de produits qui vont s’en trouver renforcées. Ainsi que la maîtrise technique des équipes R&amp;amp;D.&lt;/p&gt;

&lt;h1&gt;
  
  
  Exemplaire
&lt;/h1&gt;

&lt;p&gt;Ce qui est d’emblée visible ce sont les métriques d’un code de qualité, tel que peut nous les montrer Sonarqube. Et pour moi c’est une grande fierté d’avoir contribué à ce projet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DSG0h5q0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k30y78firzt2xl93svso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DSG0h5q0--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k30y78firzt2xl93svso.png" alt="Image description" width="880" height="155"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Notes
&lt;/h2&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Discret au sens mathématique du terme : qui est clairement délimité, séparé, isolé. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Pourquoi les tests End to End sont réellement un enfer (et ne sont qu'illusion)</title>
      <dc:creator>craft Softwr &amp; Music</dc:creator>
      <pubDate>Fri, 05 Feb 2021 21:49:44 +0000</pubDate>
      <link>https://dev.to/guillaume_agile/pourquoi-les-tests-end-to-end-sont-reellement-un-enfer-et-ne-sont-qu-illusion-b9a</link>
      <guid>https://dev.to/guillaume_agile/pourquoi-les-tests-end-to-end-sont-reellement-un-enfer-et-ne-sont-qu-illusion-b9a</guid>
      <description>&lt;p&gt;C'est un peu mon dada depuis des lustres cette affaire; et la source de discussions très animées avec mes pairs. La pomme de la discorde?  A vous de me dire...&lt;/p&gt;

&lt;p&gt;Je ne peux cesser de l'affirmer pour l'avoir vécu de l'intérieur:&lt;br&gt;
les &lt;a href="https://levelup.gitconnected.com/the-problem-with-end-to-end-tests-65509df4bc7a" rel="noopener noreferrer"&gt;tests End 2 End&lt;/a&gt;, E2E pour les intimes, sont &lt;a href="https://www.stevesmith.tech/blog/end-to-end-testing-considered-harmful/" rel="noopener noreferrer"&gt;un véritable enfer&lt;/a&gt;.&lt;br&gt;
Un enfer pavé de bonnes intentions.&lt;br&gt;
Une facilité qui se transforme très vite en &lt;a href="https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html" rel="noopener noreferrer"&gt;handicap&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Une solution vers laquelle on plonge d'autant plus facilement quand on fait du quick &amp;amp; dirty, croyant que les tests bout en bout sont assez pour s'assurer du bon fonctionnement de ce qu'on livre.&lt;/p&gt;

&lt;p&gt;Une solution trompeuse, pour ceux qui ne veulent pas faire du test unitaire et du TDD. &lt;br&gt;
Un mirage pour ceux qui pensent que développeurs et testeurs ne font pas le même métier et doivent être dans des équipes distinctes (quoi que, quel est le vrai métier du tester agile? c'est une question qui fait débat également).&lt;/p&gt;

&lt;p&gt;C'est pareil que le sucre dans l'alimentation: bon, pas cher, se trouve partout, et procure du plaisir.&lt;br&gt;
Mais ca rend obèse et diabétique!&lt;br&gt;
Et quand vous y avez goûté, le piège se referme sur vous.&lt;/p&gt;

&lt;h1&gt;
  
  
  Pourquoi?
&lt;/h1&gt;

&lt;p&gt;D'abord, pourquoi en écrire, de ces fameux tests de bout en bout?&lt;br&gt;
Plusieurs arguments en leur faveur:&lt;/p&gt;

&lt;h2&gt;
  
  
  Parce que je pense tout vérifier pour pas cher
&lt;/h2&gt;

&lt;p&gt;Un test qui vérifie en une seule passe ma base de données, mon code métier, mon IHM, les services tiers, mon broker de message, mon infrastructure... Plus on est de fous, plus on rit. Mais viendra ensuite le temps de la grimace!&lt;/p&gt;

&lt;h2&gt;
  
  
  Parce que je ne sais pas faire autrement
&lt;/h2&gt;

&lt;p&gt;Ah oui, quand on a enfin la maîtrise de Selenium, qu'on y a passé tellement de temps: on se dit qu'on a plus le temps de faire du TDD. Donc on arrête d'investir et d'apprendre.&lt;/p&gt;

&lt;h2&gt;
  
  
  Parce que tout le monde fait ça
&lt;/h2&gt;

&lt;p&gt;C'est un peu comme dire que, puisqu'il y a autant de gens qui croient que la terre est plate, alors c'est que forcément elle l'est.&lt;br&gt;
Ca fonctionne aussi pour faire croire que les résultats d'une élection ont été volés. Bref 🤨&lt;br&gt;
Ca ressemble étrangement à un biais de confirmation, voir à un effet de foule.&lt;/p&gt;

&lt;p&gt;Allons un peu plus loin, pour voir...&lt;/p&gt;

&lt;h1&gt;
  
  
  Que dit la littérature sur le sujet?
&lt;/h1&gt;

&lt;p&gt;Il y a plusieurs pistes, dont une fait référence absolue:&lt;br&gt;
&lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html" rel="noopener noreferrer"&gt;La fameuse pyramide des tests&lt;/a&gt;.&lt;br&gt;
Tout le monde la connait, mais en pratique très peu la respectent.&lt;br&gt;
Pourquoi? Je ne sais pas et j'avoue que les bras m'en tombent encore et toujours...&lt;br&gt;
On sait, mais on ne veut pas voir. Probablement.&lt;br&gt;
Parce qu'aussi, il y a un manque de courage avéré.&lt;/p&gt;

&lt;p&gt;Pourtant, il suffit de regarder: la pyramide est inversée. La base représente la partie la plus large. Là où tout repose. Donc elle se doit d'être solide. Et c'est là que les tests unitaires se logent.&lt;br&gt;
Et par tests unitaires, je parle bien de ceux écrits dans une démarche TDD. Red, green, refactor. Pas moins. Et qui se jouent en isolation.&lt;/p&gt;

&lt;p&gt;Le haut de la pyramide, c'est un peu la cerise sur le gâteau. Là où beaucoup trop de gens y voient écrit "End 2 End", il aurait mieux fallu marquer: Exploratory ou Smoke tests.&lt;/p&gt;

&lt;p&gt;J'entends encore (et toujours) dire que les tests unitaires c'est compliqué à faire, et que le TDD, bah, ca prend du temps (&lt;a href="https://blog.kotlin-academy.com/tdd-in-practice-f914d36b7d66" rel="noopener noreferrer"&gt;ce qui est totalement faux&lt;/a&gt;). Et surtout ça demande des compétences, donc "on verra plus tard".&lt;/p&gt;

&lt;p&gt;Et le "plus tard", c'est justement le test E2E. Celui qui vient à la fin. Et qui fini par prendre une place prépondérante dans une intégration continue. A tort.&lt;/p&gt;

&lt;p&gt;Si Uncle Bob, Martin Fowler, Kent Beck ne manquent pas d'avoir proféré toutes les injonctions à l'endroit du TDD et à l'encontre du E2E; d'autres auteurs n'ont pas toujours été aussi clair.&lt;/p&gt;

&lt;p&gt;Dans un livre pourtant bien écrit (&lt;a href="https://www.manning.com/books/unit-testing" rel="noopener noreferrer"&gt;Unit Testing Principles, Practices, and Patterns &lt;/a&gt; ), Vladimir Khorikov est revenu tout récemment sur la mésinterprétation croissante de son propos sur les tests E2E; il en a fait plusieurs billets dans sa &lt;a href="https://enterprisecraftsmanship.com/?" rel="noopener noreferrer"&gt;newsletter&lt;/a&gt; et je reprends quelques un de ses arguments ici.&lt;/p&gt;

&lt;p&gt;Et puis il y a les ultra convaincus, qui n'y vont pas par quatre chemins: les tests E2E sont une arnaque! (pour rester polis).&lt;/p&gt;

&lt;h1&gt;
  
  
  Combien ca coûte en vrai?
&lt;/h1&gt;

&lt;blockquote&gt;
&lt;p&gt;Très cher! Trop cher!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Un test E2E parait facile quand on regarde les 2 tutos et les 3 bouts d'exemples qui trainent partout.&lt;/p&gt;

&lt;p&gt;Un test E2E ça va, 10 tests bonjour les dégâts.&lt;br&gt;
Ils prennent du temps pour s'exécuter. La boucle de feedback est beaucoup trop longue!&lt;br&gt;
J'ai travaillé avec des éditeurs logiciels chez qui il fallait lancer les testes E2E (tous piloté par Selenium svp) le vendredi après midi et prier le weekend pour espérer voir un résultat viable le lundi matin. &lt;br&gt;
Car ces tests pouvaient échouer lamentablement, non pas à cause d'un vrai bug dans le code, mais parce que toute la machinerie mise en branle était fragile et cassait souvent toute seule. &lt;br&gt;
Un naufrage.&lt;br&gt;
D'ailleurs ce sont des sociétés (que j'ai connues) qui ont plié boutique depuis.&lt;/p&gt;

&lt;p&gt;Donc je vous parle en termes purement économiques. Financiers. Money!!!&lt;/p&gt;

&lt;h1&gt;
  
  
  Sont-ils fiables ?
&lt;/h1&gt;

&lt;p&gt;NON!&lt;br&gt;
 Les tests E2E ont comme principales caractéristiques de vouloir tout tester, donc de tirer toutes les dépendances du monde; cela peut être (liste non exhaustive):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;des APIs tierces&lt;/li&gt;
&lt;li&gt;des bases de données / système de fichiers&lt;/li&gt;
&lt;li&gt;des ressources externes&lt;/li&gt;
&lt;li&gt;des systèmes de communication (vulgairement des Entrées/Sorties) &lt;/li&gt;
&lt;li&gt;des librairies tierces&lt;/li&gt;
&lt;li&gt;le temps! (indéterminisme)&lt;/li&gt;
&lt;li&gt;la génération de nombres aléatoires, et tout ce qui se base dessus: numéros de séquence unique (Guid), Cryptographie...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Et pour ajouter de la difficulté dont on se passerait bien, certaines de ces dépendances peuvent présenter des comportements asynchrones et/ou indéterministes.&lt;/p&gt;

&lt;p&gt;Beaucoup se risquent à régler les 2 derniers problèmes avec des exceptions, ce qui ne règle rien, alourdit votre code (en temps d'exécution et pire en lisibilité) et rend l'ensemble encore plus sujets aux bugs. Bref, rien ne va!&lt;/p&gt;

&lt;p&gt;Deux symptômes apparaissent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F75ls5nl39ziee1hn4ozw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F75ls5nl39ziee1hn4ozw.jpg" alt="Beware of tests"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Les faux négatifs
&lt;/h2&gt;

&lt;p&gt;Quand un test E2E plante c'est souvent parce qu'une de ses dépendances a planté. &lt;br&gt;
La base de données ne répond plus ou n'a pas le bon jeu de données initiales par exemple. Ou -horreur suprême- les tests doivent être joués dans un ordre donné, cad on a un test qui dépendrait d'un autre (là, on frise le mental breakdown).&lt;br&gt;
Hors ce n'est pas le comportement du système tiers que vous voulez tester, car celui-ci est déjà testé par ailleurs (ou devrait l'être par son fournisseur si celui était un minimum sérieux).&lt;br&gt;
Ce que vous voulez savoir c'est comment vos composants, un ^par un - en particulier celui qui fait l'interface (ou mieux l'adaptation) avec le dit système externe, se comporte en cas de problème. Point.&lt;sup id="fnref1"&gt;1&lt;/sup&gt;&lt;/p&gt;

&lt;p&gt;Un faux négatif reflète un test coûteux à maintenir, car il vous faudra pas mal de temps (surtout pour chercher d'où vient le problème puisque vous faites jouer toutes les dépendances en même temps avec des effets de bord de partout) pour le debugger et lui redonner un comportement normal. Ou bien il aura tendance à revenir instable assez souvent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les faux positifs
&lt;/h2&gt;

&lt;p&gt;Ce sont les tests qui restent verts alors que vous venez de changer le comportement d'un bout de code quelque part. Difficile de les identifier dans les End 2 End.&lt;br&gt;
Toutes les dépendances traversées vous amènent à écrire des tests qui ne testent pas vraiment ou pas entièrement votre code, in fine.&lt;/p&gt;

&lt;p&gt;Il arrive que supprimer des lignes de notre code n'impacte aucun test E2E, car cela tombe hors des radars des dépendances.&lt;br&gt;
Du coup, vous livrez un bug mais vous ne voyez rien passer.&lt;br&gt;
Par contre, vos utilisateurs ne manqueront pas de tomber dessus très rapidement.&lt;/p&gt;

&lt;h1&gt;
  
  
  Alors, c'est quoi un bon test?
&lt;/h1&gt;

&lt;p&gt;Il doit avoir 4 grandes propriétés:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Protéger contre les  régressions &lt;br&gt;
Une modification de code entrainant un retour en arrière sur un comportement attendu devrait faire passer au moins un test au rouge.&lt;br&gt;
Pour éviter cela, vous pouvez vous doter d'un outil pour faire du test de mutation (mutation testing).&lt;br&gt;
Donc absence de faux positifs (des tests qui resteraient verts alors qu'ils devraient être rouges).&lt;br&gt;
Donc détection de bugs efficace.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Résistant au refactoring &lt;br&gt;
Le refactoring de code (changer du code sans changer son comportement) ne doit pas faire passer vos tests existants au rouge.&lt;br&gt;
Donc absence de fausses erreurs (faux test rouge).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Donner un feedback très rapide&lt;br&gt;
Un test ne devrait pas prendre plus de quelques dixième de secondes pour donner son résultat.&lt;br&gt;
Donc pas d'attente, pas de boucles, pas de sleep ou wait (sérieusement? vous pensiez tester comme ça du code asynchrone??? 🤯). Personne ne devrait accepter attendre plus d'une demi-heure pour avoir les résultats d'une campagne de tests.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Maintenable&lt;br&gt;
Des journées à écrire un test, à le faire passer au vert puis à le modifier ou le consolider?&lt;br&gt;
Allons, allons. Il est temps de faire table rase de tout cela.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Il faut qu'il soit &lt;a href="https://martinfowler.com/testing/" rel="noopener noreferrer"&gt;facile à écrire&lt;/a&gt;, et facile à lire bien entendu.&lt;br&gt;
Plus il y a de lignes de code dans un test, moins solide il sera.&lt;br&gt;
Et attention au code caché (par exemple derrière de la configuration et donc des dépendances).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://maksimivanov.com/posts/dont-mock-what-you-dont-own/" rel="noopener noreferrer"&gt;Ne pas mocker ce qui ne nous appartient pas&lt;/a&gt; (je reviendrai là dessus).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fydryqolcuk3eq4r8akpe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fydryqolcuk3eq4r8akpe.png" alt="Warning: impersonation"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Plus le test est dur à faire tourner: reboot un serveur, restaurer une base de données, résoudre des problèmes de config ou de réseau... plus ce sont des dépendances dont il vous faut vous défaire. Par plus d'abstractions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Push tests as &lt;em&gt;low&lt;/em&gt; as they can go for the highest return in investment and quickest feedback” Janet Gregory and Lisa Crispin&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Payez vous une cure de désintox des tests E2E
&lt;/h1&gt;

&lt;p&gt;Les tests End To End sont une facilité, pas une fatalité.&lt;br&gt;
Avec de la pratique et de la rigueur, on peut les limiter à un très très petit nombre et les remplacer avec une meilleure efficacité (couverture technique ET fonctionnelle améliorée) à condition de bien s'y prendre.&lt;/p&gt;

&lt;p&gt;Il vous faut procéder par petit pas:&lt;/p&gt;

&lt;h2&gt;
  
  
  1er pas: débranchez tout! (vers des tests hermétiques)
&lt;/h2&gt;

&lt;p&gt;On teste en isolation. Il y a des milliers de lectures à ce sujet, je m'y étendrais pas cette fois ci;&lt;br&gt;
&lt;a href="https://docs.google.com/presentation/d/15gNk21rjer3xo-b1ZqyQVGebOp_aPvHU3YH7YnOMxtE/edit?usp=sharing" rel="noopener noreferrer"&gt;Voici ce qu'en pensait un ingénieur de chez Google en 2014&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;On peut dire qu'un bon test devrait pouvoir tourner sur n'importe quelle machine sans connexion réseau. &lt;br&gt;
Oui, oui. Vous avez bien lu.&lt;/p&gt;

&lt;p&gt;Surtout, surtout, faites tout pour éviter le coup: "mais ca marche sur ma machine, je ne comprends pas!".&lt;br&gt;
Et ne comptez pas sur le DevOps pour vous sauver, au contraire ^^&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffuz1lcfz83hpgad7rphb.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffuz1lcfz83hpgad7rphb.jpeg" alt="it works on..."&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2e pas: une conception objet "test oriented"
&lt;/h2&gt;

&lt;p&gt;Si vous faites du TDD&lt;sup id="fnref2"&gt;2&lt;/sup&gt;, et suivez les heuristiques &lt;a href="https://medium.com/backticks-tildes/the-s-o-l-i-d-principles-in-pictures-b34ce2f1e898" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt; intelligemment, alors vous devriez automatiquement vous sentir légitimes pour dire: "les tests E2E sont une complète aberration, car ils mettent à mal toutes les règles que je tente d'appliquer":&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Single Responsibility&lt;/li&gt;
&lt;li&gt;Open for extension / Closed for modification&lt;/li&gt;
&lt;li&gt;Liskov Substitution &lt;/li&gt;
&lt;li&gt;Interface Segregration &lt;/li&gt;
&lt;li&gt;Dependency Injection &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Appliquez ces heuristiques à tous vos tests, et effectivement vous verrez, les tests E2E sont à coté de la plaque! &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Le code de VOS tests est aussi VOTRE code. Il obéit aux même lois.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3e pas: vers une architecture "test oriented"
&lt;/h2&gt;

&lt;p&gt;Et pour cela, l'architecture hexagonale a fait ses preuves. J'y reviendrai sûrement dans un prochain article.&lt;br&gt;
Cet architecture préconise de mettre en place des Ports et des Adapteurs, qui permettent justement de ne pas tout tester en même temps, d'éviter les tests E2E. Si on a les bons niveaux d'abstraction bien sûr.&lt;/p&gt;

&lt;h2&gt;
  
  
  4e pas: le métier est vérifié et codé dans des Bounded Contexts
&lt;/h2&gt;

&lt;p&gt;Je reprends ici les termes du Domain Driven Design, car même sans faire d'Event Sourcing, DDD nous propose de découper, délimiter, responsabiliser le domaine métier et ses règles; et évidement de le découpler de tout ce qui est &lt;em&gt;autour&lt;/em&gt; (UI, persistance, services externes, sous domaines, domaines génériques, domaines support).&lt;/p&gt;

&lt;p&gt;Ce qui va découper, découpler votre système et donc rendre redondant (voir impossible) du test de bout en bout. Et tant mieux.&lt;/p&gt;

&lt;h1&gt;
  
  
  Mais comment peux tu être sûr ?
&lt;/h1&gt;

&lt;p&gt;C'est à peu près du même niveau que de me dire: "comment peux-tu être certain que la terre est ronde, &lt;a href="https://youtu.be/j90zyS8xvOM" rel="noopener noreferrer"&gt;parce qu'à l'œil nu elle apparait plate&lt;/a&gt;". &lt;/p&gt;

&lt;p&gt;Il y a toujours eu des gens pour me dire: "mais tu ne peux pas avoir de certitude à 100%" sans les tests de bout en bout. &lt;/p&gt;

&lt;p&gt;Je ne dis pas pour autant qu'un test E2E est inutile. Parce que la vraie question est "que teste-t-on"?&lt;br&gt;
Ou plutôt :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Que peut-on tester?"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Si on ne dispose d'aucun outillage de tests efficace, alors oui, il ne reste (hélas) que le test E2E.&lt;br&gt;
Mais vouloir tout tester avec un E2E est une perte d'argent et de temps comme je ne cesse de le répéter ici.&lt;/p&gt;

&lt;p&gt;C'est là où &lt;a href="https://martinfowler.com/articles/practical-test-pyramid.html#TheConfusionAboutTestingTerminology" rel="noopener noreferrer"&gt;tout le monde s'embrouille sur la pyramide de tests&lt;/a&gt; quand on lit: "&lt;em&gt;integration tests&lt;/em&gt;".&lt;br&gt;
Pour beaucoup, tester en intégration c'est tester tout ce qui peut s'intégrer, ensemble, en même temps. Et bim!&lt;br&gt;
&lt;a href="https://blog.thecodewhisperer.com/permalink/integrated-tests-are-a-scam" rel="noopener noreferrer"&gt;On revient sur du E2E&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Tout comme ceux qui ont confondu les tests E2E avec les tests de l'Interface Graphique.&lt;br&gt;
Parce que c'est tellement facile (en apparence) à coder avec des outils comme Selenium ou Cypress.&lt;br&gt;
Parce que justement leur architecture spaghetti, ou N-tiers ( = plat de lasagne), ou maintenant Micro Services ( = plat de raviolis) ne permet plus de séparer la UI (User Interface) d'un monstre monolithique où tout est collé bout à bout.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fge6um4ijjpb4r6yr2atv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fge6um4ijjpb4r6yr2atv.png" alt="Italian recipes"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pourtant, le but est de tester si les composants qui ont, par ailleurs, été testés de manière isolée, s'intègrent bien entre eux.&lt;br&gt;
Une fois cela vérifié, pourquoi l'ensemble ne serait-il pas stable?&lt;/p&gt;

&lt;h2&gt;
  
  
  Integration ou Contrat ?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://www.youtube.com/watch?v=PE_1nh0DdbY" rel="noopener noreferrer"&gt;Une intégration fiable se joue autour d'un contrat fiable&lt;/a&gt;.&lt;br&gt;
S'assurer que le contrat est respecté, DES DEUX COTES, c'est faire une intégration qui tient la route.&lt;br&gt;
Il faut vérifier (automatiquement de préférence) l'équivalence du contrat des 2 cotés d'un composant: fournisseur (provider) ET consommateur (consumer).&lt;/p&gt;

&lt;p&gt;Quand on fake (parlons de doubler, comme au cinéma), le test n'est valide que si la doublure est ressemblante. &lt;br&gt;
Il faut s'en assurer constamment (à chaque build, à chaque intégration continue), le contrat ne doit pas être rompu &lt;sup id="fnref3"&gt;3&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;La bonne idée pour éviter des vérifications superflues, c'est de laisser le compilateur les faire par le typage. Un typage très fort et un respect des règles SOLID. Et ne pas utiliser les exceptions. Et suivre toute la démarche DDD, cela aide beaucoup.&lt;/p&gt;

&lt;h1&gt;
  
  
  Les bénéfices de l'abstinence
&lt;/h1&gt;

&lt;p&gt;Les gens qui mettent (perdent) tout leur argent dans le E2E testing, sont hélas ceux qui n'ont pas pris soin d'explorer d'autres pistes.&lt;/p&gt;

&lt;p&gt;Et pourtant, il y a des choses bien plus profitables (rentables, messieurs les financiers) comme &lt;a href="https://www.softwaretestinghelp.com/smoke-testing-and-sanity-testing-difference/" rel="noopener noreferrer"&gt;le Smoke Testing, le Sanity Testing et le Regression Testing&lt;/a&gt;. &lt;/p&gt;

&lt;h1&gt;
  
  
  Et s'il ne devait en rester qu'un
&lt;/h1&gt;

&lt;p&gt;Et bien, un test "End to End" , de bout en bout, pourrait bien s'avérer utile pour tester ce qu'on ne sait vraiment plus tester autrement, et c'est peut être justement l'intégration de l'intégration.&lt;br&gt;
L'articulation ultime.&lt;br&gt;
Mais je suis sûr qu'on peut le remplacer par un autre test d'intégration, si on cherche bien ;)&lt;/p&gt;

&lt;p&gt;Et à ce moment là, que dois je vérifier?&lt;br&gt;
Que mon système démarre bien. C'est tout.&lt;/p&gt;

&lt;p&gt;Derrière cela veut dire que ma config est juste et que mes systèmes sont opérationnels. Mais cela aussi je peux le surveiller ("monitorer") par d'autres tests plus unitaires.&lt;/p&gt;

&lt;p&gt;Juste un test, un happy path. Un seul. Pour convaincre le dernier des incrédules.&lt;/p&gt;

&lt;p&gt;Je ne me laisserai même pas tenter par une liste de "High Value Paths" comme on peut le lire &lt;a href="https://www.testim.io/blog/e2e-testing/" rel="noopener noreferrer"&gt;par ici&lt;/a&gt; ou là; parce que si vous entrez dans cette logique, vous allez en écrire autant que de Use Cases de votre métier (c'est à dire: pléthore).&lt;br&gt;
Alors que toute la logique devrait être dans le Domaine Métier et les agrégats qui le constituent tel que nous l'apprend DDD.&lt;/p&gt;

&lt;p&gt;C'est l'objet du prochain article que je suis en train de peaufiner.&lt;br&gt;
Merci de m'avoir lu jusqu'ici.&lt;/p&gt;




&lt;p&gt;Références&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.stevesmith.tech/blog/end-to-end-testing-considered-harmful/" rel="noopener noreferrer"&gt;https://www.stevesmith.tech/blog/end-to-end-testing-considered-harmful/&lt;/a&gt;&lt;/p&gt;




&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Analyser/prouver comment ensuite l'éventuel problème (déclenché par un système tiers) se propage à l'intérieur de votre ensemble de composants, devrait être réglé par une programmation propre (principes SOLIDES encore, mais aussi ne pas utiliser les exceptions, utiliser des monades de type Result ou MayBe ou Optional). Finalement se résoudre en un problème de typage et donc de compilation, pas de tests à proprement parler. Ca serait tellement plus rapide à vérifier! ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;J'ai cité TDD cinq fois à ce stade, laissez moi vous recommander &lt;a href="https://www.softwaretestingnews.co.uk/adopting-the-test-pyramid-model-approach/" rel="noopener noreferrer"&gt;un peu de lecture sur le sujet&lt;/a&gt;. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Le bon outil, me semble-t-il, c'est le Contract Based Programming/Testing. Oui c'est un travail supplémentaire. Mais je ne vois pas comment l'éviter pour ne pas retomber dans le piège du E2E qui finalement est un pis-aller pour ceux qui ne prennent pas le temps de faire soit du typage fort, soit du Contract Testing (&lt;a href="https://medium.com/typeforms-engineering-blog/contract-testing-i-e2e-testing-is-so-last-season-1142fa63c740" rel="noopener noreferrer"&gt;Consumer-driven contract testing (CDC) expliqué ici&lt;/a&gt; ) ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Que vaut le travail que l'on ne fait pas?</title>
      <dc:creator>craft Softwr &amp; Music</dc:creator>
      <pubDate>Tue, 26 Jan 2021 09:59:21 +0000</pubDate>
      <link>https://dev.to/guillaume_agile/que-vaut-le-travail-que-l-on-ne-fait-pas-5878</link>
      <guid>https://dev.to/guillaume_agile/que-vaut-le-travail-que-l-on-ne-fait-pas-5878</guid>
      <description>&lt;p&gt;Je me suis posé cette question dans le prolongement de l’excellent article de mon confrère &lt;a href="https://blog.nicolas.brondin-bernard.com/lettre-ouverte-pourquoi-le-travail-d-un-developpeur-vaut-cher/"&gt;Nicolas Brondin&lt;/a&gt; où il explique bien que le travail de développeur ne se résume pas qu’à produire du code.&lt;/p&gt;

&lt;p&gt;Étonnant d’en venir à justifier que l’on travaille quand on ne travaille pas. Je pense même que cela peut choquer hors du cercle des informaticiens.&lt;/p&gt;

&lt;p&gt;Cela révèle que développer (coder) est un métier vraiment pas comme les autres. &lt;br&gt;
C’est le mien, j’en suis très fier et il ne s’agit ni d’une passade ou d’une erreur de trajectoire. Ni je pense d’un hasard.&lt;br&gt;
En tout cas, ce n’est pas une honte de rester développeur jusqu’au bout et de ne pas vouloir être super chef ou commercial comme aboutissement d’une carrière. &lt;br&gt;
Savoir coder n’est pas (forcément) une transition vers quelque chose de soit disant plus honorable &lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;Ce n’est qu’au fur et à mesure de ma progression dans ce métier que je m’aperçu que ce n'était pas un simple travail d’ingénieur au sens commun du terme. Ni de scientifique d’ailleurs. &lt;br&gt;
Nous (les développeurs) utilisons des outils de la science, mais nos productions ne sont pas des découvertes. Nous ne démontrons pas de théorèmes. Nous ne découvrons rien que nous ne sachions déjà (sur les théories de l’informatique et le travail de nos pairs avant nous).&lt;br&gt;
Nous explorons simplement. &lt;br&gt;
Et surtout nous créons des choses qui n'existaient pas dans leur tout (le nouveau logiciel, la nouvelle fonctionnalité) sous une forme auparavant donnée. &lt;br&gt;
Nous créons. Nous ne découvrons pas.&lt;br&gt;
Et chaque logiciel est unique.&lt;br&gt;
En découle qu’il n’y a pas d'usine logicielle, au sens où notre travail n’est pas industriel.&lt;br&gt;
Ce qui sort d’une industrie, d’une chaîne de montage, ce sont des séries, des copies.&lt;br&gt;
Exactement ce que le logiciel n’est pas.&lt;/p&gt;

&lt;h1&gt;
  
  
  On ne peut pas changer 1000 personnes 1000 fois...
&lt;/h1&gt;

&lt;p&gt;Pour preuve: donnez le même problème à résoudre à 1000 informaticiens différents, et vous aurez 1000 code sources différents.&lt;br&gt;
Ne serait-ce que par l’existence de plus de 800 (parmi ceux recensés) langages de développement connus à ce jour (&lt;a href="http://www.rosettacode.org/wiki/Rosetta_Code"&gt;http://www.rosettacode.org/wiki/Rosetta_Code&lt;/a&gt;).&lt;br&gt;
Combinez cela au fait que, dans un même langage de programmation X &lt;sup id="fnref2"&gt;2&lt;/sup&gt;, 10 développeurs vous produiront 10 codes sources différents, du fait même qu’émergent des styles d’écritures différents, propre à l’expérience de chacun, mais aussi à leur vécu, leur formation, et quelque chose d’impalpable qui est de l’ordre de l’intuition et la sensibilité, c’est à dire bien en dehors des domaines de la rationalité et de la science.&lt;/p&gt;

&lt;p&gt;Oui, le travail de produire un logiciel est complexe et échappe à la science au bout d’un moment.&lt;br&gt;
Alors, comment voulez-vous que nous puissions prédire “combien de temps cela va prendre à développer ???”.&lt;br&gt;
Impossible avec certitude. Ne cherchez pas et passez plutôt du temps à coder!&lt;/p&gt;

&lt;p&gt;Mais il y a autre chose, sur les “styles” de programmation.&lt;/p&gt;

&lt;p&gt;Regardez 2 réponses (sous forme de code) au même problème (le très célèbre &lt;a href="https://codingdojo.org/kata/RomanNumerals/"&gt;kata&lt;/a&gt; qui consiste à transformer en chiffres romains un nombre entier positif inférieur à 4000):&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--AnNy6PBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g6lo7evs48cl9d0bsr8l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--AnNy6PBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/g6lo7evs48cl9d0bsr8l.png" alt="code long"&gt;&lt;/a&gt;&lt;br&gt;
2e code, qui fait exactement la même chose:&lt;br&gt;
&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--hjJqfFk_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d7cku6jasfevvw0pdxpv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--hjJqfFk_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/d7cku6jasfevvw0pdxpv.png" alt="code court"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Les 2 versions du code donnent le même résultat au moment de l’exécution.&lt;br&gt;
Alors, pouvez-vous encore honnêtement penser que le travail de développeur se résume à la ligne de code que l’on a écrit?&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Les lignes de code n’ont aucune valeur juste par leur nombre. Au contraire.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Montre moi ton code, je te dirai combien tu vaux
&lt;/h1&gt;

&lt;p&gt;Si l’on me demandait de payer le développeur à la ligne, je n'hésiterai pas à attribuer à 80% des lignes de code une valeur négative.&lt;br&gt;
Pourquoi?&lt;br&gt;&lt;br&gt;
Une raison parmi tant d’autres est la lisibilité du code. Il est plus facile de lire quelque chose de concis; à condition que cela soit explicite évidemment. &lt;br&gt;
Par contre, comment mesure-t-on l’expressivité du code?&lt;/p&gt;

&lt;p&gt;L’autre valeur négative qui se cache derrière une ligne de code en trop est le bug qu’elle va induire. Moins de code = moins de bug. Là pour le coup, c’est juste mathématique.&lt;/p&gt;

&lt;p&gt;Autre valeur négative: la complexité du code rend difficile voir impossible sa maintenance et son évolution. Quand un nouveau cas (use case) se présente; ou bien un comportement non prévu (bug) vous devez fouiller dans beaucoup de lignes de code pour corriger. Perte de temps et d’argent.&lt;/p&gt;

&lt;p&gt;Viens le point littéraire de l’article, merci Saint Exupéry, mais il est toujours pertinent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Il semble que la perfection soit atteinte non quand il n'y a plus rien à ajouter, mais quand il n'y a plus rien à retrancher.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Au passage, vous avez noté qu’il était romancier, non pas informaticien.&lt;/p&gt;

&lt;h1&gt;
  
  
  De la mesure du code
&lt;/h1&gt;

&lt;p&gt;Pour revenir à la valeur d’une ligne de code, nous avons des heuristiques, des guidelines, qui nous permettent de juger des qualités ou des défauts (selon un certain nombre de conventions, adaptables) du code, et qui nous poussent à l’améliorer (refactoring).&lt;br&gt;
Pour moi, ce sont avant tout les principes DRY, YAGNI et SOLID, mais aussi la &lt;a href="https://connascence.io/"&gt;Connascence&lt;/a&gt; ou couplage  .&lt;/p&gt;

&lt;p&gt;Ce travail autour de la qualité du code est plutôt abstrait.&lt;br&gt;
Qui sait réellement la mesurer sans équivoque? &lt;br&gt;
Ce n’est pas Sonarqube qui va vous dire si vous avez fait du copier coller, ou si vous ne respectez pas les principes SOLID. Encore plus pour du &lt;a href="https://en.wikipedia.org/wiki/You_aren%27t_gonna_need_it"&gt;YAGNI&lt;/a&gt; ou une &lt;a href="https://refactoring.guru/smells/feature-envy"&gt;Feature Envy&lt;/a&gt;.&lt;br&gt;
Rien ne remplacera une expérience/expertise humaine. &lt;/p&gt;

&lt;p&gt;Je vois quand même 2 bonnes mesures de qualité du code à commencer à appliquer:  la &lt;a href="https://en.wikipedia.org/wiki/Cyclomatic_complexity"&gt;complexité cyclomatique&lt;/a&gt;  et les graphes de dépendance (je pense à NDepend pour .Net).&lt;br&gt;
Ceux-là devraient être intégrés comme règle dans Sonar (ou équivalent). &lt;br&gt;
On attribuerait des valeurs négatives aux lignes de code qui augmentent la complexité cyclomatique et les dépendances. &lt;br&gt;
Tout comme il faut pénaliser celles qui ne sont pas couvertes par les tests.&lt;br&gt;
Mais là encore, c’est une mesure qui peut être &lt;a href="https://blogs.infosupport.com/thinking-about-test-coverage/"&gt;déformée&lt;/a&gt;. Voir &lt;a href="https://medium.com/better-programming/is-code-coverage-a-useless-metric-bc76e0fde9e"&gt;contournée&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Quantité vs Qualité
&lt;/h1&gt;

&lt;p&gt;C’est donc un travail intellectuel  &lt;em&gt;énorme&lt;/em&gt; que de se retenir d’écrire une ligne de code.&lt;br&gt;
 Toute ligne en trop, ou de mauvaise qualité, rentre dans la catégorie de la fameuse “dette technique”.&lt;br&gt;
Et d’ailleurs, qui pourrait évaluer la valeur (négative) de la dette technique que l’on s’efforce de supprimer? Comment la chiffrer?&lt;/p&gt;

&lt;p&gt;En tout cas, le travail de frugalité intelligente, de parcimonie éclairée, ne se joue pas qu’au niveau du développeur mais aussi sur celui des architectes.&lt;br&gt;
Combien de choix d’architecture logicielle, de frameworks, de librairies à la mode, qui ont conduit des projets au désastre.&lt;br&gt;
Combien de frameworks (je pense aux affreux JavaBeans et autres horreurs type Corba à l’époque) qui vous impose d’écrire des tonnes de lignes de code overkill ? Imbitables ...&lt;br&gt;
Ou bien si un framework n’est pas si mal pensé, combien de fois est-il vraiment bien utilisé?&lt;/p&gt;

&lt;p&gt;Il est si facile de transformer un bon pattern en un anti pattern, juste par un mauvais usage.&lt;/p&gt;

&lt;p&gt;Un mot pour conclure:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Uncle Bob (Robert C. Martin): "A good architect maximizes the number of decisions not made."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;em&gt;Not made&lt;/em&gt;. La meilleure décision est celle que l'on ne prend pas...&lt;/p&gt;

&lt;p&gt;Difficile là aussi de donner une valeur à l’absence. Et pourtant.&lt;/p&gt;

&lt;h1&gt;
  
  
  Finalement, peut-on évaluer le travail du codeur?
&lt;/h1&gt;

&lt;p&gt;Comme on l'a vu ce travail qui n’est ni science, ni industrie, que vaut-il? Quel est il? Peut-être une forme d’art? Et comme dans tout art, il cache une grande part d’intangible.&lt;br&gt;
N’en déplaise à ceux qui veulent tout monnayer et tout transformer en chiffres.&lt;/p&gt;

&lt;p&gt;Heureusement, il restera la valeur ajoutée délivrée aux utilisateurs. Mais encore faut-il y ajouter le calcul de la dette technique, la vraie valeur du code. Cela s'appelle le &lt;a href="https://www.enterpriseirregulars.com/31274/the-marginal-cost-of-software/"&gt;coût marginal&lt;/a&gt; de la prochaine User Story, pour reprendre les propos d'&lt;a href="https://www.youtube.com/watch?v=itGmiTS_IPw"&gt;Arnaud Lemaire&lt;/a&gt;.&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;Pour moi, il y a d’abord eu la fascination pour les machines, et surtout la possibilité -rendue simple- de prendre le contrôle de la machine. De parler à l’oreille des machines pourrait-on dire. Pourtant, je n’ai eu que relativement tardivement (par rapport aux 1ères lignes de code que j’ai écrites) accès aux travaux d’Alan Turing , Alonzo Church et Noam Chomsky, 3 des pères de la programmation (et je dois humblement admettre que, n’ayant pas poursuivi dans le domaine de la recherche, je n’ai acquis que des bouts de leur savoir)&lt;sup id="fnref3"&gt;3&lt;/sup&gt;. Je n’avais pas une vraie vision de mon métier alors. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;j’aurais bien aimé dire Z, mais Zed est déjà le nom d’un langage de programmation ^^ ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn3"&gt;
&lt;p&gt;Et quand bien même, qui peut dire qu’il comprend parfaitement tout ce que ces génies ont voulu nous transmettre? ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
    </item>
    <item>
      <title>Modèle anémique ou modèle métier? Comment la modélisation objet a su évoluer .</title>
      <dc:creator>craft Softwr &amp; Music</dc:creator>
      <pubDate>Fri, 18 Dec 2020 10:29:24 +0000</pubDate>
      <link>https://dev.to/guillaume_agile/modele-metier-ou-modele-anemique-comment-les-distinguer-1kij</link>
      <guid>https://dev.to/guillaume_agile/modele-metier-ou-modele-anemique-comment-les-distinguer-1kij</guid>
      <description>&lt;h1&gt;
  
  
  Constat
&lt;/h1&gt;

&lt;p&gt;J'ai la chance de pratiquer la modélisation d'objets dans le cadre d'applications variées, utilisant pour la peine un mix entre diagrammes UML, diagrammes C4 plus récemment et beaucoup de Design Emergeant en codant directement les classes d'objets au fur et à mesure avec la sécurité du TDD (Test Driven Development).&lt;/p&gt;

&lt;p&gt;Et immanquablement se pose la question de : "comment organiser les classes?" et surtout "quelles sont leur responsabilités?". Cela abouti toujours à de grands débats qui animent les séances de code; en cela le Pair Programming, et encore plus le Mob Programming ouvrent les discussions.&lt;/p&gt;

&lt;p&gt;Donnant actuellement des cours UML et conception objet à des universitaires, il est toujours délicat d'expliquer comment poser les bases d'un "bon" design objet.&lt;/p&gt;

&lt;p&gt;L'apprentissage classique et le nombre de tutos qui ont emboité le pas dans la catégorie "auto formation" se délectent d'exemples simplistes et -hélas- peu en phase avec le quotidien du développeur: le cercle, le carré, le rectangle, la forme géométrique (shape) sont les modèles usés et usuels pour illustrer  aux étudiants un 'bon' modèle d'objets. Objets auxquels on colle les opérations fadasses: calculer aire et je ne sais quoi de trop scolaire.&lt;/p&gt;

&lt;p&gt;Avec cela, beaucoup de développeurs se font une très mauvaise idée de ce que devrait être un vrai modèle objets dans une application d'entreprise qui se verra mise en production avec des milliers d'utilisateurs (ou plus j'espère) et des années de durée de vie, entrainant une nécessaire maintenance et évolution.&lt;br&gt;
Sans parler des bugs qui apparaitront inévitablement.&lt;/p&gt;

&lt;h1&gt;
  
  
  L'héritage lancinant de Merise
&lt;/h1&gt;

&lt;p&gt;Je trouve que la méthode Merise a causé énormément de tort et de retard à l'ingénierie logicielle en France (pour ce que j'en connais).&lt;br&gt;
Très en vogue dans les années 80, elle est assez rigide et s'accorde bien du cycle de développement en V. Elle impose tout un tas de diagrammes que je qualifie d'emblée de Big Design Upfront. Ce qui a tendance à rassurer les chefs de projets et les développeurs quand il faut s'attaquer à développer un système sans trop savoir où cela va nous mener.&lt;/p&gt;

&lt;p&gt;Cette méthode de modélisation ne prône pas vraiment l'agilité, et, pour moi, mène à des architectures d'applications trop rigides et fortement couplées, avec une qualité de design assez pauvre.&lt;/p&gt;

&lt;p&gt;Elle se base aussi sur un postulat bien encombrant: tout doit reposer sur une base de données, relationnelle qui plus est!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw8ucp4qyvefu809bednl.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw8ucp4qyvefu809bednl.jpg" alt="and in the darkness bind them"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Cette omniprésence de la base de données (et des gens qui en sont les gardiens, à savoir les concepteurs et les administrateurs, les fameux DBA longtemps très recherchés et considérés comme des demi-dieux) nous avait amené à ériger en modèle de programmation parfait l'architecture N-tiers, dans laquelle la couche de persistance (l'accès à la base de données) était la fondation de tout et dictait son modèle aux autres couches. D'horribles dépendances se créaient. Mais après tout c'était du Merise à la lettre.&lt;/p&gt;

&lt;p&gt;Evidemment cette dépendance au choix d'un SGBDR et un tel couplage était rapidement source d'un coût de maintenance insupportable. Un changement de solution SGBDR demandait quasiment la ré-écriture du tout.&lt;/p&gt;

&lt;p&gt;Si malgré tout, on pouvait obtenir l'assurance que l'on allait rester fidèle à son moteur SQL préféré pour la vie, se posait le problème de la responsabilité attribuée: la base allait même jusqu'à gérer les règles métiers complexes;&lt;br&gt;
 avec l'échouage ultime qu'était l'utilisation de triggers, où le comportement était mêlé de manière inextricable au simple stockage. Dur à tester, couteux à maintenir, horrible à faire évoluer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Poussée du design objet
&lt;/h1&gt;

&lt;p&gt;Heureusement les librairies et les frameworks (🤔) nous ont poussé vers d'autres design d'architecture.&lt;/p&gt;

&lt;p&gt;Le problème étant: comment faire vivre des objets à coté d'une base de données. Et comment y accéder depuis différentes Interfaces Homme-Machine; ces dernière se multipliant à la faveur du déploiement des Internets et des clients (programmes client/navigateurs/plug-ins) de plus en plus universels et versatiles (pour ordis, tablettes, mobiles, interface vocale, objets connectés).&lt;/p&gt;

&lt;p&gt;Cela a donné le genre de modélisation objet où l'on fait émerger les classes parce qu'il y a des tables dans une base de données et on les affubles de toutes les opérations possibles et imaginables:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Friiucxllh4h59k3bqor2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Friiucxllh4h59k3bqor2.png" alt="ugly design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On avait envie, par principe DRY (Don't Repeat Yourself) d'avoir des objets omnipotents, qui encapsulent tout, le savoir être (l'état) et le savoir faire (les opérations). Des objets avec des tonnes de méthodes. Et des objets qui se promèneraient (les mêmes) de couches en couches du système,  de l'interface graphique à la base de données. &lt;br&gt;
Des initiatives ultra-monolithiques furent légion, telles que des bases de données orientées objets (je pense à un vieux système français aujourd'hui disparu: O2) ou des frameworks tout en un, type WinDev (encore hélas en vie) ou FoxPro ou Delphi. Cela pouvait bien fonctionner sur des applis Client Lourd. Mais au prix d'un couplage immense.&lt;/p&gt;

&lt;p&gt;Heureusement les interfaces Web et la multiplicité des solutions de stockage (sans parler des services et de la virtualisation extrême de tout cela) rend impossible de trimbaler des objets aussi lourds et chargés de tant de responsabilité.&lt;/p&gt;

&lt;p&gt;Et tant mieux, il nous fallait un code plus simple.&lt;/p&gt;

&lt;h1&gt;
  
  
  Epurer, jusqu'à l'anémie
&lt;/h1&gt;

&lt;p&gt;C'est comme cela qu'on en est arrivé à des modèles d'objets anémiques.&lt;br&gt;
On s'est mis à concevoir des classes qui représentent des entités mais qui ne contiennent aucune logique métier, car elles étaient bien souvent une émanation des DAO (Data Access Objets) dans une architecture 3-tiers ou dans un design MVC/MVVM.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwbbz17lvu6opfmde30eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fwbbz17lvu6opfmde30eb.png" alt="anemic model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;C'était pour "simplifier". Seulement, on n'a fait que mettre la poussière sous le tapis. &lt;br&gt;
Soit la logique métier remontait dans d'énormes classes de "service" ou "business layers" qui finissaient par devenir énormes parce que le métier n'était pas mieux découpé. &lt;/p&gt;

&lt;p&gt;Ce qui, au final, n'a rien simplifié car on s'est retrouvé pieds et points liés à la couche d'accès aux données &lt;sup id="fnref1"&gt;1&lt;/sup&gt;.&lt;br&gt;
Avec derrière tout cela, l'idée qu'une bonne couche de liaison à la base de données allait une fois de plus nous dicter tout ce qu'il fallait: fais ton MCD (ou plutôt obéit à celui que le DBA a fait pour toi) et adapte ton code à cela. &lt;/p&gt;

&lt;p&gt;Les ORM (Object-relational Mappers) continuaient de nous laisser croire que la méthode Merise était la bonne et que jamais nous ne nous serions capable de nous délivrer de ce fichu MCD.&lt;/p&gt;

&lt;p&gt;Ou alors, ces objets orientés "données", non contents d'être anémiques en eux même, pouvaient cacher des règles métiers dans la couche DAO sous jacente: il fallait alors que l'exécution du code traverse la partie DAO pour voir apparaitre les contraintes sur les relations, les formats de données, et une partie des règles métiers que l'on savait traduire en ordre SQL: clés uniques, ou pire: triggers.&lt;/p&gt;

&lt;p&gt;Et d'un autre coté, on en venait à coder dans la business layer (et parfois même coté client avec de beaux validateurs 🤢) les même règles.&lt;/p&gt;

&lt;p&gt;Dès qu'on multipliait les services, on multipliait les règles, même si plusieurs services pouvaient finalement modifier la même entité (ou agrégat tant qu'on y est) avec chacun ses vérifications pour ses propres besoins, laissant la persistance finale se débrouiller plus ou moins bien avec des injonctions paradoxales. Bugs en pagaille assurés.&lt;/p&gt;

&lt;p&gt;Une fois de plus, la base de données avait le dernier mot. Et les DBA jouaient le rôle d'arbitres entre équipes de devs qui se déchiraient sur la compréhension du besoin du client.&lt;/p&gt;

&lt;p&gt;C'est du vécu!&lt;/p&gt;

&lt;h2&gt;
  
  
  Un peu de code ...
&lt;/h2&gt;

&lt;p&gt;Je me suis remis dans la peau du codeur qui chasse les objets anémiés avec un petit Kata pour illustrer le principe &lt;em&gt;Tell Don't Ask&lt;/em&gt; avec un TyrePressure Monitor ou un Cpu Monitor (en bref, un moniteur de ce que l'on veut, ca marche très bien).&lt;/p&gt;

&lt;p&gt;La règle métier va se loger, non pas dans le service, mais dans la classe moniteur qui est utilisée par le service, afin que cette dernière 'affirme' (tell) la règle au lieu que ce soit le service qui demande (ask) des valeurs internes au moniteur pour satisfaire la règle. &lt;br&gt;
Il faut que toute logique (fonction) qui a besoin d'une donnée doit se trouver dans la même classe qui contient cette donnée (encapsulation et Loi de Demeter).&lt;/p&gt;

&lt;p&gt;Le résultat est &lt;a href="https://github.com/guillaumeagile/seed-TS-promises/tree/7059a8d93a249a1260fa06da25429828413de994" rel="noopener noreferrer"&gt;ici&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Things that change together should be together. (Fowler)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Et si on parlait de DDD ?
&lt;/h1&gt;

&lt;p&gt;Mais comment éviter un domaine objet anémique sans retourner aux erreurs du modèle objet old school, des objets obèses ?&lt;br&gt;
C'est à la lecture de &lt;a href="https://blog.pragmatists.com/domain-driven-design-vs-anemic-model-how-do-they-differ-ffdee9371a86" rel="noopener noreferrer"&gt;cet article&lt;/a&gt; que j'ai eu envie d'écrire ces lignes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6za1otrucwmt82qitzbc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6za1otrucwmt82qitzbc.png" alt="DDD model"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;L'idée étant de pouvoir décrire un modèle riche mais affranchi des contraintes qui ne sont pas les siennes:&lt;br&gt;
se sauvegarder dans une base de données untel ou s'afficher à l'utilisateur sur un interface Z (il existe des milliers de frameworks pour faire le beau sur le Web&lt;sup id="fnref2"&gt;2&lt;/sup&gt;)) ne concerne en rien, absolument en rien le Modèle du Domaine d'une App ou d'un SI.&lt;/p&gt;

&lt;h1&gt;
  
  
  Au début était le verbe
&lt;/h1&gt;

&lt;p&gt;La motivation d'Eric Evans, avec son livre bleu &lt;a href="https://www.dddcommunity.org/books/" rel="noopener noreferrer"&gt;Domain Driven Design&lt;/a&gt;, n'était pas tant de parler architecture logicielle mais de représentation.&lt;/p&gt;

&lt;p&gt;Plutôt que le mot objet/classe, il choisit le mot entité.&lt;br&gt;
Et le plus important des principes qu'il a voulu mettre en avant est celui du langage parlé par les humains impliqués dans un projet.&lt;br&gt;
Pas le langage de développement mais bien le vocabulaire partagé, le nommage des choses, la sémantique commune, la conversation que les développeurs doivent avoir avec les experts métiers.&lt;/p&gt;

&lt;p&gt;Cette approche appelée "Ubiquitous Language" nous oblige à poser plusieurs choses.&lt;br&gt;
D'abord séparer les Domaines métiers, car plusieurs se cachent forcément dans tout système d'informations (mot valise que je vais utiliser pour parler d'une App, d'un SaaS, d'un site, d'un prog, bref... du code en production).&lt;br&gt;
Ensuite établir des Entités regroupées en Agrégats afin d'obtenir un Modèle à l'intérieur d'un Domaine Délimité (Bounded Context).&lt;/p&gt;

&lt;h1&gt;
  
  
  Ce qui émerge petit à petit
&lt;/h1&gt;

&lt;p&gt;Un atelier tel que l'&lt;a href="https://www.eventstorming.com/" rel="noopener noreferrer"&gt;Event Storming&lt;/a&gt; ou l'&lt;a href="https://eventmodeling.org/" rel="noopener noreferrer"&gt;Event Modeling&lt;/a&gt;, nous aide à mieux savoir quoi modéliser (et comment) en partant de zéro et sans connaissance technique particulière (des posts its , des stylos et de grands murs suffisent).&lt;/p&gt;

&lt;p&gt;Traditionnellement, il y a plusieurs choses qui émergent de ces ateliers: les évènements en premier, les commandes (ou actions en second) et très vite derrière les agrégats et leur "policies".&lt;/p&gt;

&lt;p&gt;Cette distinction entre évènements et agrégats n'est pas anodine. Bien que les évènements aient des effets sur les agrégats, les agrégats existent pour eux même. Ils décrivent ce qui reste une fois les évènements passés. Et leur "policies" est leur profession de foi, ce qui est toujours vrai pour eux (et leur entourage proche).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Voila pourquoi une bonne modélisation du Domaine en Agrégats (Entités + Value Objects) va pouvoir nous enrichir en "règles métier", tout en traitant par ailleurs les évènements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;(Pour en savoir plus sur l'Event Storming il y a foule d'articles et bien sûr de publications à ce sujet, mais peu en &lt;a href="https://cleandojo.com/2019/06/event-storming-modelisez-votre-domaine-metier-en-equipe/" rel="noopener noreferrer"&gt;français&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Les évènements sont transients. Parfois contingents. Mais ils passent. On ne peut les arrêter. L'Event Sourcing tente de capturer ces évènements, comme on tenterait de capturer le temps. &lt;br&gt;
Ce qui n'est pas sans risque!&lt;br&gt;
On peut avec un certains nombres d'outils, remonter le temps et le cours des évènements; c'est la force de l'Event Sourcing. Au regard d'un certain prix à payer pour y arriver correctement.&lt;/p&gt;

&lt;p&gt;Le Domain Model , quant à lui, survit aux évènements; c'est lui que l'on présente à l'utilisateur final (sous une forme adaptée, dite View Model ou &lt;a href="http://gorodinski.com/blog/2012/04/25/read-models-as-a-tactical-pattern-in-domain-driven-design-ddd/" rel="noopener noreferrer"&gt;Read Model&lt;/a&gt; ), lequel se moque pas mal des journaux de logs.&lt;br&gt;
 Les éléments du modèle montrent l'état (partiel et à un instant t) du monde (tel que manipulé dans un contexte donné) et sa cohésion.&lt;/p&gt;

&lt;p&gt;L'intérêt d'un Modèle bien fait est d'imposer une cohérence qui s'affranchit des évènements (et également de se laisser facilement parcourir, découvrir).&lt;/p&gt;

&lt;p&gt;J'aurai le plaisir de vous parler des évènements dans une autre article.&lt;br&gt;
Et avant cela, d'aller plus loin dans les détails de la modélisation objet d'un domaine avec la suite de cet article.&lt;/p&gt;







&lt;ol&gt;

&lt;li id="fn1"&gt;
&lt;p&gt;On peut encore trouver du code assez horrible comme celui ci (projet Jigsaw), où on vous impose des trucs du genre: As you can see, the Java Beans are strictly equivalent to the table they represents. The name of the bean properties MUST be strictly equals to the column names in the SQL table. ↩&lt;/p&gt;
&lt;/li&gt;

&lt;li id="fn2"&gt;
&lt;p&gt;Si un framework de présentation (je pense à tous ceux basés sur les patterns MMVM ou MVP ou MVC) vous demande de placer dans sa couche à lui (son environnement si vous préférez) le modèle, je pense que vous pouvez le jeter par la fenêtre. Le modèle métier n'appartient pas à la couche de présentation. La couche de présentation manipule un View Model seulement. Les dépendances viennent du centre (core) de l'architecture, pas des bords (UI ou Storage). ↩&lt;/p&gt;
&lt;/li&gt;

&lt;/ol&gt;

</description>
      <category>eventdriven</category>
      <category>architecture</category>
      <category>programming</category>
      <category>ddd</category>
    </item>
    <item>
      <title>La DoD en question</title>
      <dc:creator>craft Softwr &amp; Music</dc:creator>
      <pubDate>Tue, 03 Nov 2020 15:48:13 +0000</pubDate>
      <link>https://dev.to/guillaume_agile/la-dod-en-question-1dih</link>
      <guid>https://dev.to/guillaume_agile/la-dod-en-question-1dih</guid>
      <description>&lt;p&gt;On m'a récemment posé la question : qu'est ce qu'une bonne DoD? Definition of Done. En Français: définition de fini.&lt;br&gt;
Difficile à dire. Est-ce une liste à la Prévert? Ou un contrat implicite (0)?&lt;br&gt;
Elle se doit en tous cas d'être unique à chaque équipe et à sa stack technique; elle dépend bien évidemment de son niveau de maturité.&lt;/p&gt;

&lt;p&gt;Néanmoins il m'apparait clair qu'elle devrait être source de discussions et d'un accord clair entre toute l'équipe!&lt;br&gt;
Car quand c'est fini, c'est fini. On ne revient plus dessus. Sinon on est "hors contrat".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://jp-lambert.me/%C3%AAtre-agile-avoir-un-dod-qui-se-focalise-sur-les-probl%C3%A8mes-%C3%A0-r%C3%A9soudre-76ef47284359"&gt;On peut commencer par lire l'avis de JP Lambert sur le sujet:&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--8nGL2C1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cpxfhpau6qsy43fzvrez.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--8nGL2C1---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/cpxfhpau6qsy43fzvrez.jpg" alt="example DoD par Jean Pierre Lambert"&gt;&lt;/a&gt;&lt;br&gt;
On y apprend avant tout que "sa" DoD a été établie par &lt;em&gt;Les&lt;/em&gt; équipes web du Player qu'il a accompagnées. Et que celle-ci a évolué avec le temps. C'est un des aspects cruciaux d'une DoD: c'est un objet vivant!&lt;/p&gt;

&lt;p&gt;D'abord la DoD, c’est du sérieux, cela devrait être une revue que toute l’équipe fait à chaque fin de Sprint. Ce n’est pas une unique personne qui valide la DoD dans son coin! Il faut donc lui consacrer du temps et de l'attention.&lt;br&gt;
Il me semble que les cérémoniaux Scrum ne prennent pas (assez) de temps pour passer en revue la DoD (à mon goût).&lt;/p&gt;

&lt;p&gt;Une DoD est néanmoins quelque chose de très personnel à une équipe; et doit être le fruit d'une réflexion de groupe et de compromis. Elle peut éviter qu'un groupe au travail ne se perde au milieu de ses propres objectifs ou ne soit plus aligné avec les valeurs qu'il partage. En cela, elle est aussi un contrat social du "bien travailler ensemble".&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Alors, que met-on dedans?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Je me permet de vous livrer des pistes, issues de ma propre expérience et d'équipes que j'ai pu accompagner. Ce ne sont que des exemples, à adapter à vos besoins.&lt;/p&gt;

&lt;h2&gt;
  
  
  Les basiques :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Toute l’intégration continue a tourné depuis le dernier commit et tous les tests sont verts.&lt;/li&gt;
&lt;li&gt;Aucune user story ne reste ouverte d’un sprint à l’autre (si une reste ouverte, il faut la re-découper en deux, fermer ce qui est vraiment fait et préparer ce qu’il manque à faire en une nouvelle US en restant focus sur la valeur livrée) (1)&lt;/li&gt;
&lt;li&gt;Avoir des tests qui soient alignés avec les user stories et qui s'exécutent en permanence (soit par des Executable Acceptance Tests, soit par des matrices de traçabilités que l'on peut générer en taguant les tests unitaires et faire correspondre ces tags avec les exigences émergeant des U.S.) (2)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Documentation :
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;  Réclamer des fichiers d’enregistrement des choix techniques/d’architecture (ADR)   &lt;a href="https://github.com/joelparkerhenderson/architecture_decision_record"&gt;https://github.com/joelparkerhenderson/architecture_decision_record&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;pour le reste, il n'existe pas de "bonne documentation" (&lt;a href="https://medium.com/@thorbjorn.sigberg/sigbergs-laws-of-documentation-fab155b2415b"&gt;lisez les 6 lois&lt;/a&gt;); un crafter comme moi vous dira que la seule documentation qui vaille réside dans les tests (à condition qu'ils soient lisibles) et le code.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Pour le code propre
&lt;/h2&gt;

&lt;p&gt;je mets personnellement des règles assez strictes, mais surtout des choses à vérifier manuellement. Les SonarQube et autres Linters / scanneurs de code me gonflent, même s'ils sont une aide utile pour les équipes qui cherchent l'uniformité ou qui n'arrivent pas à prendre assez de temps pour discuter de leur code entre eux; c'est un mal nécessaire et j'espère que ce n'est qu'une phase transitoire (3).&lt;br&gt;
Quelques idées de règles possibles:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Tout a été écrit en mode TDD (le test écrit avant le code : il compile et il est rouge. On écrit le code : le test devient vert. Cela oblige à écrire de tout petits tests, on refactore avant d'écrire un nouveau test).
Ce n’est pas parce qu’on fait de l’infra/devOps qu’on ne peut pas faire de TDD ; la preuve : &lt;a href="https://www.hashicorp.com/resources/test-driven-development-tdd-for-infrastructure"&gt;https://www.hashicorp.com/resources/test-driven-development-tdd-for-infrastructure&lt;/a&gt; &lt;/li&gt;
&lt;li&gt;  Refactoring effectué // par exemple: Commentaires supprimés (les commentaires sont un bon indicateur de la faiblesse du code. Cf &lt;a href="https://refactoring.guru/smells/comments"&gt;https://refactoring.guru/smells/comments&lt;/a&gt; )&lt;/li&gt;
&lt;li&gt;  Pas de code dupliqué&lt;/li&gt;
&lt;li&gt;  Limiter la complexité cyclomatique (peut se vérifier avec une règle Sonar, contraignant mais si on est un bon programmeur, on doit trouver les solutions)&lt;/li&gt;
&lt;li&gt;  Pleins d’autres règles sur le Clean Code ont été posées partout sur les internets, personnellement j'adhère à &lt;a href="https://refactoring.guru"&gt;https://refactoring.guru&lt;/a&gt; qui nous dit:&lt;/li&gt;
&lt;li&gt;  Couplage trop fort : chercher les heuristiques 

&lt;ul&gt;
&lt;li&gt; Trop de clauses imports en-tête de classe/module&lt;/li&gt;
&lt;li&gt; Présence de « new » dans un constructeur d’une classe/module (couplage fort entre le code qui fait le new et la classe instanciée)&lt;/li&gt;
&lt;li&gt; Usage d'un outil de calcul des dépendances, &lt;/li&gt;
&lt;li&gt; et plein d'autres bonnes pratiques comme l'Injection de Dépendances et l'Inversion de Contrôle (DI et IoC).&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Le souci c'est que cette liste va vite devenir longue et plus personne ne va la lire.&lt;br&gt;
Et se pose toujours la question: est ce que tel bout de code en vaut la peine? Sera-t-il toujours là ou sera-t-il amené à disparaitre? Jusqu'où aller dans le refactoring?&lt;br&gt;
Bien malin qui peut le dire. Le problème est que nous sommes tous à un moment donné sujet à l'amnésie. Le refactoring nous aidera juste à moins hurler "mais qui a écrit cette m**de" dans le futur (et bien souvent, celui qui avait écrit de la m, c'était moi!!!).&lt;/p&gt;

&lt;p&gt;Le mieux à ce niveau étant peut-être d'admettre que l'équipe se doit d'être au meilleur niveau technique qui lui est possible et qu'elle doit sans cesse se former à cela (par le biais de Kata, de Mob Programming, de révisions régulière de tous les principe de Refactoring et Clean Code).&lt;/p&gt;

&lt;p&gt;Le DoD pourrait dire: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nous sommes satisfait de notre code (sachant tout ce que j'ai évoqué ci dessus), et nous avons fait en sorte d'être meilleurs à cette itération qu'à la précédente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;J'ai vu des équipes très tendues sur ces points là et la notion de qualité de code vraiment appréciée à des degrés très divers entre les développeurs. La qualité voulu par les uns constamment remise en question par les autres ou par le PO ("on n'a pas le temps"). C'est pourquoi la DoD devrait être écrite en dehors du cadre des Sprints, comme une volonté farouche d'arrêter de coder de la merde. Et d'en payer le prix plus tard. Et surtout d'être tous d'accord là dessus.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tests
&lt;/h2&gt;

&lt;p&gt;Ma conviction: ce ne sont pas les tests E2E qui garantissent que tout est ok; vraiment pas!&lt;br&gt;
Utilisez du Contract Based Testing pour faire des intégrations propres entre vos différents services (je reviendrai là dessus). &lt;/p&gt;

&lt;p&gt;Pour les équipes devOps, c’est également abordé dans cette vidéo de 30mn: &lt;a href="https://www.hashicorp.com/resources/test-driven-development-tdd-for-infrastructure"&gt;https://www.hashicorp.com/resources/test-driven-development-tdd-for-infrastructure&lt;/a&gt;&lt;br&gt;
Il y a plein d'Outils:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;a href="https://www.openpolicyagent.org/docs/latest/policy-testing/"&gt;open-policy-agent&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;  Goss&lt;/li&gt;
&lt;li&gt;  Inspec&lt;/li&gt;
&lt;li&gt;  Test-Kitchen

&lt;ul&gt;
&lt;li&gt; Plus de détails utiles sur &lt;a href="https://github.com/joatmon08/tdd-infrastructure"&gt;https://github.com/joatmon08/tdd-infrastructure&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Elements non fonctionnel
&lt;/h1&gt;

&lt;p&gt;Quid de la performance du code? De la montée en charge? Des accès concurrentiels? Des failles de sécurité? &lt;br&gt;
Mais là aussi, tout dépend de votre seuil de tolérance, et encore une fois d'une vision de l'avenir de votre produit.&lt;/p&gt;

&lt;p&gt;La DoD est là pour nous dire combien est-on prêt à investir dans le futur.&lt;/p&gt;

&lt;h1&gt;
  
  
  Autres catégories
&lt;/h1&gt;

&lt;p&gt;On peut aussi rajouter dans la catégorie Pérenne ou dans une autre catégorie, ce qu’on peut appeler : « Synchro » &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Etre sûr d'avoir dispensé, auprès des autres équipes concernées par les modifications résultantes de ce sprint, toutes les informations utiles (versionning, modèles communs, contrats, APIs et autres).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;On s'aperçoit que c'est déjà, avec ces quelques bases, beaucoup de travail. Et que cet article est déjà beaucoup trop long ;)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.aubryconseil.com/post/2008/d%C3%A9finition-de-fini-%C3%A0-la-fin-dun-sprint/"&gt;Claude Aubry a depuis longtemps planché sur le sujet de la DoD&lt;/a&gt;, et il va au fond des choses, &lt;a href="https://www.aubryconseil.com/post/2015/d%C3%A9finition-de-fini-multi-niveaux/"&gt;en proposant des niveaux dans les éléments de la DOD et cela a beaucoup de sens.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Les premières fois vous allez vous rater, forcément.&lt;br&gt;
Ne vous découragez pas, et surtout ne laissez jamais tomber votre DoD.&lt;br&gt;
Pour les POs zélés, ou les chefs de projets en mode "quand est-ce que vous aurez fini???", il faut vraiment miser sur la DoD dès le 1er jour du Sprint. Pour éviter qu'une dérive sur la qualité et la maintenabilité ne s'installe dès les premières itérations.&lt;br&gt;
Il est très difficile de revenir en arrière ou perdre ses habitudes, tous agiles que nous soyons.&lt;/p&gt;

&lt;p&gt;"Comment vais-je faire pour finir?", "Et si je commençais par finir?" devraient être les premières pensées qui animent votre travail.&lt;/p&gt;

&lt;p&gt;Pour ne pas se laisser surprendre par la livraison et éviter l'effet panique, il vaut mieux commencer par la fin justement.&lt;br&gt;
La vérification et la stabilisation de votre travail est la valeur ajoutée qu'il manquera toujours à celle du métier que l'on vous demande d'honorer.&lt;/p&gt;

&lt;p&gt;Pour conclure, il semblerait que la meilleure DoD soit le consentement, éclairé et discuté, de l'équipe tout entière. La coucher par écrit permet d'abord la discussion et peut aussi rassurer vos parties prenantes.&lt;/p&gt;




&lt;p&gt;(0) Evidemment je ne penche pas pour l'implicite à moins que l'équipe ne soit excessivement mûre et stable. "Making the implicit explicit" devrait s'appliquer aussi à la DoD.&lt;/p&gt;

&lt;p&gt;(1) Si une telle situation se produit plusieurs fois, il faut réellement re questionner l’équipe sur son approche de l’agilité : est-on assez mûr pour faire des Sprints? Pourquoi laisser filer les US ouvertes ou ré-ouvertes ? Est-on sûr de la qualité de ce que nous produisons ? Savons-nous finir ce que nous commençons ? Savons nous en calculer la valeur ? Savons-nous garder les choses simples? Savons nous limiter notre WIP (Work In Progress)?&lt;/p&gt;

&lt;p&gt;(2) C'est une immense problème que la vérification automatique d'une User Story. Le BDD pour écrire des tests End To End est une idiotie sans pareille sur laquelle je reviendrai dans un long article. Le BDD pour écrire des tests d'intégration ou de vérification métier est très utile. En fait, je ne fais pas de distinction entre BDD / TDD et TU. &lt;br&gt;
Rien n'est facile en la matière mais la Vérification et Validation vaut toute documentation. Lire à ce sujet Cyrille Martaire &lt;a href="https://leanpub.com/livingdocumentation"&gt;https://leanpub.com/livingdocumentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;(3) Ce genre de pratique trop courante, car cédant à la facilité, est souvent corollaire de la présence d'un architecte tout puissant, qui dicte des règles à ces associés à travers un outil froid et des règles bétonnées. Rien ne vaut la pédagogie et la discussion, mais c'est plus long ;)&lt;/p&gt;

</description>
      <category>agile</category>
      <category>devops</category>
      <category>development</category>
      <category>craftsmanship</category>
    </item>
  </channel>
</rss>
