[{"data":1,"prerenderedAt":19929},["ShallowReactive",2],{"search-api":-1,"listing-page-1":3},[4,482,1269,2116,4105,4570,5081,9904,10571,11763,12561,13183,14772,15334,16204,16655,17143,17831,18502,19483],{"_path":5,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":9,"description":10,"id":11,"date":12,"listed":13,"nocomments":7,"hidden":7,"categories":14,"tags":15,"--cover":19,"readingTime":20,"body":25,"_type":476,"_id":477,"_source":478,"_file":479,"_stem":480,"_extension":481},"/fr/dette-technique/ingenierie-logicielle-avantage-concurrentiel","dette-technique",false,"","L'ingénierie logicielle comme avantage concurrentiel durable","Dans un monde où l'IA accélère tout le monde, la qualité d'engineering devient le différenciateur durable. Ce que les CTOs qui l'ont compris font différemment.",36,"2026-03-27",true,[6],[16,17,18],"Engineering Excellence","Avantage Compétitif","Leadership","covers/articles/ingenierie-avantage-concurrentiel.jpg",{"text":21,"minutes":22,"time":23,"words":24},"9 min read",8.605,516300,1721,{"type":26,"children":27,"toc":462},"root",[28,36,42,56,61,70,75,79,86,91,96,106,109,115,122,127,132,138,143,148,154,159,172,175,188,191,197,202,212,222,232,242,252,255,261,266,276,286,296,301,304,310,315,325,343,361,371,374,380,395,408,421,434,447,450],{"type":29,"tag":30,"props":31,"children":33},"element","h1",{"id":32},"lingénierie-logicielle-comme-avantage-concurrentiel-durable",[34],{"type":35,"value":9},"text",{"type":29,"tag":37,"props":38,"children":39},"p",{},[40],{"type":35,"value":41},"J'ai accompagné un éditeur santé, 35 développeurs, sur douze mois. Le déclencheur n'était pas une vision technique du CTO ni un grand programme de transformation : deux seniors venaient de partir en pointant \"un environnement technique trop dégradé\", un troisième hésitait, et la roadmap produit que le COMEX avait validée six mois plus tôt commençait visiblement à déraper. Les engagements pris en interne ne tenaient plus, et les recrutements engagés pour compenser n'inversaient pas la tendance.",{"type":29,"tag":37,"props":43,"children":44},{},[45,47,54],{"type":35,"value":46},"À l'arrivée, le constat était cohérent avec ces signaux : un ",{"type":29,"tag":48,"props":49,"children":51},"a",{"href":50},"/fr/pratiques-agiles/reduire-work-in-progress-velocite",[52],{"type":35,"value":53},"lead time",{"type":35,"value":55}," d'environ six mois entre la décision produit et la mise en production, un taux d'incidents en prod que l'équipe n'arrivait plus à tenir, et une part importante de la capacité absorbée par la maintenance corrective. Aucun de ces points n'a bougé pendant les premiers mois. Les six premiers, justement, ont surtout servi à poser les fondations qu'on ne voyait pas dans les métriques : CI/CD remise d'aplomb, découpage des stories, stratégie de tests, gouvernance de la dette, rituels de delivery. Les premiers résultats mesurables sont arrivés à partir de là.",{"type":29,"tag":37,"props":57,"children":58},{},[59],{"type":35,"value":60},"Au terme des douze mois, le lead time tournait autour de 4 à 8 semaines (2 à 3 sprints). Ce n'est pas le standard DORA \"elite\", mais c'est l'écart qui change le quotidien : l'équipe redevient capable d'absorber un cycle d'itération produit dans la même release, le COMEX retrouve une visibilité réaliste sur les engagements, et deux seniors ont rejoint l'équipe sur la deuxième moitié de l'accompagnement en citant explicitement la qualité de l'environnement technique comme raison principale. Ce n'est pas une transformation spectaculaire, c'est un retour de capacité.",{"type":29,"tag":37,"props":62,"children":63},{},[64],{"type":29,"tag":65,"props":66,"children":67},"strong",{},[68],{"type":35,"value":69},"L'IA a rendu le code accessible à tout le monde. Elle n'a pas rendu la qualité d'engineering accessible à tout le monde. Et c'est là que se creuse le prochain écart concurrentiel.",{"type":29,"tag":37,"props":71,"children":72},{},[73],{"type":35,"value":74},"En 2024-2025, les outils de génération de code ont nivelé la vitesse de production du code. Une startup de 5 personnes peut générer autant de code qu'une équipe de 50 il y a 3 ans. Ce nivellement a changé les règles du jeu : la compétition ne se joue plus sur qui écrit le code le plus vite, mais sur qui le maintient, l'améliore, et le gouverne le mieux.",{"type":29,"tag":76,"props":77,"children":78},"hr",{},[],{"type":29,"tag":80,"props":81,"children":83},"h2",{"id":82},"lia-comme-égalisateur-et-révélateur",[84],{"type":35,"value":85},"L'IA comme égalisateur et révélateur",{"type":29,"tag":37,"props":87,"children":88},{},[89],{"type":35,"value":90},"L'IA a réduit le coût marginal de production de code à presque zéro. Un développeur augmenté par Copilot produit 20 à 40% de code supplémentaire selon les études GitHub. C'est un gain réel.",{"type":29,"tag":37,"props":92,"children":93},{},[94],{"type":35,"value":95},"Mais ce gain amplifie ce qui existe déjà. Une équipe avec de bonnes pratiques d'architecture, de test, et de revue de code bénéficie pleinement de l'IA : le code généré est bien intégré, testé, et maintenu. Une équipe avec de mauvaises pratiques produit plus de dette technique plus rapidement. L'IA amplifie les équipes solides et fragilise les équipes fragiles.",{"type":29,"tag":37,"props":97,"children":98},{},[99,104],{"type":29,"tag":65,"props":100,"children":101},{},[102],{"type":35,"value":103},"La donnée qui change tout",{"type":35,"value":105}," : le State of DevOps Report 2023 (DORA) montre que les équipes \"elite\" ont un deployment frequency 973 fois supérieur aux équipes \"low performers\", et un lead time 6 570 fois inférieur. L'IA n'a pas réduit cet écart. Elle l'a amplifié. Ce n'est pas de la théorie : c'est le résultat de 10 ans de données sur des milliers d'équipes.",{"type":29,"tag":76,"props":107,"children":108},{},[],{"type":29,"tag":80,"props":110,"children":112},{"id":111},"les-3-dimensions-de-lavantage-engineering",[113],{"type":35,"value":114},"Les 3 dimensions de l'avantage engineering",{"type":29,"tag":116,"props":117,"children":119},"h3",{"id":118},"dimension-1-la-vitesse-de-livraison-time-to-market",[120],{"type":35,"value":121},"Dimension 1 : La vitesse de livraison (time-to-market)",{"type":29,"tag":37,"props":123,"children":124},{},[125],{"type":35,"value":126},"La capacité à livrer des fonctionnalités en semaines plutôt qu'en mois est un avantage concurrentiel direct. Sur les marchés où les cycles d'innovation sont courts, une équipe qui déploie en production plusieurs fois par semaine peut itérer sur le feedback utilisateur 10 fois plus vite qu'une équipe qui déploie une fois par mois.",{"type":29,"tag":37,"props":128,"children":129},{},[130],{"type":35,"value":131},"Ce n'est pas une métrique technique, c'est une métrique business. Chaque semaine gagnée sur le lead time est une semaine d'avance sur le concurrent qui a eu la même idée.",{"type":29,"tag":116,"props":133,"children":135},{"id":134},"dimension-2-la-qualité-comme-réducteur-de-risque",[136],{"type":35,"value":137},"Dimension 2 : La qualité comme réducteur de risque",{"type":29,"tag":37,"props":139,"children":140},{},[141],{"type":35,"value":142},"Dans les secteurs régulés (finance, assurance, santé), la qualité d'engineering est une condition de survie réglementaire. Un incident lié à un code de mauvaise qualité peut déclencher une enquête de l'autorité de tutelle, une amende significative, et un dommage réputationnel durable. J'ai vu cela chez des clients dans le secteur bancaire, Canal+, BNP Paribas, Agirc-Arrco, où un incident technique mal géré avait des conséquences réglementaires immédiates.",{"type":29,"tag":37,"props":144,"children":145},{},[146],{"type":35,"value":147},"Mais dans tous les secteurs, la qualité réduit le coût opérationnel. Une équipe avec une absorption de dette technique à 20% (vs 40%) a 20% de capacité supplémentaire disponible pour l'innovation. Sur une équipe de 50 développeurs, c'est 10 développeurs-équivalents récupérés sans recrutement.",{"type":29,"tag":116,"props":149,"children":151},{"id":150},"dimension-3-lattractivité-des-talents",[152],{"type":35,"value":153},"Dimension 3 : L'attractivité des talents",{"type":29,"tag":37,"props":155,"children":156},{},[157],{"type":35,"value":158},"Les meilleurs développeurs choisissent leurs employeurs sur les pratiques techniques, pas seulement sur la rémunération. Une enquête Stack Overflow 2023 montre que 62% des développeurs considèrent la qualité technique de l'environnement de travail comme un critère de choix primaire.",{"type":29,"tag":37,"props":160,"children":161},{},[162,164,170],{"type":35,"value":163},"Une équipe avec un ",{"type":29,"tag":48,"props":165,"children":167},{"href":166},"/fr/dette-technique/introduction-maturite-engineering-5-niveaux",[168],{"type":35,"value":169},"niveau 4-5 de maturité engineering",{"type":35,"value":171}," attire et retient les développeurs seniors. Une équipe au niveau 1-2 a un turnover plus élevé et un coût de recrutement proportionnel. Le cercle vicieux : les bons développeurs partent à cause de la dette, les remplaçants sont moins expérimentés, la dette augmente.",{"type":29,"tag":76,"props":173,"children":174},{},[],{"type":29,"tag":176,"props":177,"children":182},"cta",{"cta":178,"href":179,"title":180,"type":181},"Réserver mon diagnostic gratuit →","https://app.kamanga.fr/forms/discovery-call","Votre engineering est-il un avantage concurrentiel ou un frein à la croissance ?","call",[183],{"type":29,"tag":37,"props":184,"children":185},{},[186],{"type":35,"value":187},"Vous sentez que votre engineering ne vous donne pas l'avantage qu'il devrait donner : le lead time est trop long, les bugs reviennent, les bons développeurs hésitent à rejoindre l'équipe. Un diagnostic de maturité engineering prend 2 jours. Il produit une vue claire de votre position et un plan d'action concret pour transformer votre engineering en levier de croissance.",{"type":29,"tag":76,"props":189,"children":190},{},[],{"type":29,"tag":80,"props":192,"children":194},{"id":193},"ce-que-les-équipes-délite-font-différemment",[195],{"type":35,"value":196},"Ce que les équipes d'élite font différemment",{"type":29,"tag":37,"props":198,"children":199},{},[200],{"type":35,"value":201},"La recherche DORA identifie 5 pratiques qui distinguent les équipes \"elite\" des autres, indépendamment de la taille ou du secteur :",{"type":29,"tag":37,"props":203,"children":204},{},[205,210],{"type":29,"tag":65,"props":206,"children":207},{},[208],{"type":35,"value":209},"1. Le trunk-based development",{"type":35,"value":211}," : intégration sur la branche principale au moins une fois par jour, feature flags pour isoler le code non-terminé. Réduit le coût de merge et les conflits d'intégration.",{"type":29,"tag":37,"props":213,"children":214},{},[215,220],{"type":29,"tag":65,"props":216,"children":217},{},[218],{"type":35,"value":219},"2. La suite de tests automatisés",{"type":35,"value":221}," : tests qui s'exécutent en moins de 10 minutes sur chaque commit, avec un objectif de non-régression garanti. Conditionne la confiance pour déployer fréquemment.",{"type":29,"tag":37,"props":223,"children":224},{},[225,230],{"type":29,"tag":65,"props":226,"children":227},{},[228],{"type":35,"value":229},"3. Le continuous deployment",{"type":35,"value":231}," : automatisation complète du pipeline de déploiement. Aucune intervention manuelle entre le commit et la prod. Réduit le risque humain et le lead time.",{"type":29,"tag":37,"props":233,"children":234},{},[235,240],{"type":29,"tag":65,"props":236,"children":237},{},[238],{"type":35,"value":239},"4. Le monitoring et l'observabilité",{"type":35,"value":241}," : visibilité temps réel sur les métriques de performance et d'erreur. MTTR \u003C 1 heure pour les incidents P1.",{"type":29,"tag":37,"props":243,"children":244},{},[245,250],{"type":29,"tag":65,"props":246,"children":247},{},[248],{"type":35,"value":249},"5. La culture du learning",{"type":35,"value":251}," : blameless post-mortems, partage de knowledge structuré, temps dédié à l'apprentissage. Les équipes qui apprennent progressent ; les autres stagnent. C'est ce que les travaux de Nicole Forsgren sur la culture DevOps démontrent de façon rigoureuse.",{"type":29,"tag":76,"props":253,"children":254},{},[],{"type":29,"tag":80,"props":256,"children":258},{"id":257},"comment-traduire-la-qualité-engineering-en-langage-board",[259],{"type":35,"value":260},"Comment traduire la qualité engineering en langage board",{"type":29,"tag":37,"props":262,"children":263},{},[264],{"type":35,"value":265},"Le board ne comprend pas \"maturité engineering\" ou \"dette technique\". Il comprend :",{"type":29,"tag":37,"props":267,"children":268},{},[269,274],{"type":29,"tag":65,"props":270,"children":271},{},[272],{"type":35,"value":273},"Risque opérationnel",{"type":35,"value":275}," : \"Notre taux d'incidents de prod génère X€ de coût direct et Y€ de risque réglementaire par an. Un investissement de Z€ en qualité technique réduit ce risque de 70% en 12 mois.\"",{"type":29,"tag":37,"props":277,"children":278},{},[279,284],{"type":29,"tag":65,"props":280,"children":281},{},[282],{"type":35,"value":283},"Efficacité du capital",{"type":35,"value":285}," : \"Nous investissons 40% de notre capacité engineering à maintenir l'existant. Un programme de 6 mois ramène ce chiffre à 20%, soit l'équivalent de 8 développeurs à plein temps récupérés pour l'innovation.\"",{"type":29,"tag":37,"props":287,"children":288},{},[289,294],{"type":29,"tag":65,"props":290,"children":291},{},[292],{"type":35,"value":293},"Avantage compétitif",{"type":35,"value":295}," : \"Notre lead time actuel de 6 semaines signifie que nous mettons 6 semaines à répondre aux opportunités de marché. Nos principaux concurrents sont à 2 semaines. Le delta nous coûte X% de chiffre d'affaires sur les opportunités time-sensitive.\"",{"type":29,"tag":37,"props":297,"children":298},{},[299],{"type":35,"value":300},"Ces trois angles permettent à un board de comprendre que l'investissement en qualité engineering n'est pas une dépense technique, c'est un levier de performance business. Ce changement de cadrage est souvent ce qui débloque les budgets que les CTOs n'arrivaient pas à obtenir en présentant le sujet dans sa version technique.",{"type":29,"tag":76,"props":302,"children":303},{},[],{"type":29,"tag":80,"props":305,"children":307},{"id":306},"le-plan-daction-pour-les-12-prochains-mois",[308],{"type":35,"value":309},"Le plan d'action pour les 12 prochains mois",{"type":29,"tag":37,"props":311,"children":312},{},[313],{"type":35,"value":314},"Si vous êtes au niveau 2-3 aujourd'hui et souhaitez faire de l'engineering un avantage concurrentiel, voici la séquence :",{"type":29,"tag":37,"props":316,"children":317},{},[318,323],{"type":29,"tag":65,"props":319,"children":320},{},[321],{"type":35,"value":322},"Trimestre 1",{"type":35,"value":324}," : Mesurer. Implémenter les 4 métriques DORA, quantifier l'absorption de la dette technique, identifier les 2-3 modules critiques qui génèrent le plus de coûts.",{"type":29,"tag":37,"props":326,"children":327},{},[328,333,335,341],{"type":29,"tag":65,"props":329,"children":330},{},[331],{"type":35,"value":332},"Trimestre 2",{"type":35,"value":334}," : Stabiliser. Programme de réduction de la dette sur les modules critiques, stabilisation de la CI/CD, installation des ",{"type":29,"tag":48,"props":336,"children":338},{"href":337},"/fr/dette-technique/outils-analyse-statique-2026",[339],{"type":35,"value":340},"outils d'analyse statique",{"type":35,"value":342},".",{"type":29,"tag":37,"props":344,"children":345},{},[346,351,353,359],{"type":29,"tag":65,"props":347,"children":348},{},[349],{"type":35,"value":350},"Trimestre 3",{"type":35,"value":352}," : Accélérer. Réduction du lead time sur un flux de delivery cible, introduction du continuous deployment, formation sur les pratiques avancées (TDD, ",{"type":29,"tag":48,"props":354,"children":356},{"href":355},"/fr/dette-technique/pair-programming-roi-conditions",[357],{"type":35,"value":358},"pair programming ciblé",{"type":35,"value":360},").",{"type":29,"tag":37,"props":362,"children":363},{},[364,369],{"type":29,"tag":65,"props":365,"children":366},{},[367],{"type":35,"value":368},"Trimestre 4",{"type":35,"value":370}," : Consolider et mesurer le ROI. Comparer les métriques de T4 vs T1. Préparer le business case pour le prochain cycle d'investissement.",{"type":29,"tag":76,"props":372,"children":373},{},[],{"type":29,"tag":80,"props":375,"children":377},{"id":376},"faq-sur-lengineering-comme-avantage-concurrentiel",[378],{"type":35,"value":379},"FAQ sur l'engineering comme avantage concurrentiel",{"type":29,"tag":381,"props":382,"children":383},"details",{},[384,390],{"type":29,"tag":385,"props":386,"children":387},"summary",{},[388],{"type":35,"value":389},"1. L'IA ne va-t-elle pas rendre ces investissements obsolètes en quelques années ?",{"type":29,"tag":37,"props":391,"children":392},{},[393],{"type":35,"value":394},"Non, et c'est précisément l'inverse. L'IA rend les pratiques d'engineering solides plus importantes, pas moins. Le code généré par l'IA doit être testé, reviewé, maintenu et gouverné. Une équipe sans bonnes pratiques génère de la dette technique à la vitesse de l'IA. Une équipe avec de bonnes pratiques bénéficie pleinement de la productivité de l'IA tout en maintenant la qualité.",{"type":29,"tag":381,"props":396,"children":397},{},[398,403],{"type":29,"tag":385,"props":399,"children":400},{},[401],{"type":35,"value":402},"2. Ces pratiques sont-elles accessibles aux petites équipes (\u003C 10 développeurs) ?",{"type":29,"tag":37,"props":404,"children":405},{},[406],{"type":35,"value":407},"Oui, et souvent plus rapidement. Une équipe de 8 développeurs peut atteindre le niveau 4 en 6 mois : la coordination est simple, les standards s'adoptent vite, et l'impact de chaque amélioration est immédiatement visible. Les pratiques DORA (CI/CD, trunk-based development, monitoring) s'appliquent quelle que soit la taille de l'équipe.",{"type":29,"tag":381,"props":409,"children":410},{},[411,416],{"type":29,"tag":385,"props":412,"children":413},{},[414],{"type":35,"value":415},"3. Comment prouver la valeur de l'investissement engineering à un investisseur lors d'une due diligence ?",{"type":29,"tag":37,"props":417,"children":418},{},[419],{"type":35,"value":420},"Quatre métriques convaincantes pour une due diligence : deployment frequency (> 1/semaine), lead time (\u003C 1 semaine), change failure rate (\u003C 5%), MTTR (\u003C 1 heure). Ces chiffres montrent la capacité à itérer rapidement et à maintenir la stabilité. Je recommande de préparer un \"engineering health report\" avant toute due diligence : un document court (5 à 10 pages) qui présente ces métriques sur 12 mois glissants, l'évolution de la dette absorbée, et les pratiques DORA en place. C'est ce qui transforme l'engineering d'un risque à expliquer en argument à valoriser.",{"type":29,"tag":381,"props":422,"children":423},{},[424,429],{"type":29,"tag":385,"props":425,"children":426},{},[427],{"type":35,"value":428},"4. Par où commencer si le board ne voit pas encore la valeur de l'engineering ?",{"type":29,"tag":37,"props":430,"children":431},{},[432],{"type":35,"value":433},"Commencer par un incident et le transformer en business case. La prochaine fois qu'un incident de prod a un impact business mesurable, calculer le coût total : temps de résolution, impact sur le revenu, coût réputationnel. Montrer que des pratiques standard auraient prévenu cet incident. Un seul incident bien documenté vaut mieux que dix slides de théorie.",{"type":29,"tag":381,"props":435,"children":436},{},[437,442],{"type":29,"tag":385,"props":438,"children":439},{},[440],{"type":35,"value":441},"5. Comment maintenir les standards de qualité quand la croissance crée une pression intense sur la livraison ?",{"type":29,"tag":37,"props":443,"children":444},{},[445],{"type":35,"value":446},"La croissance augmente la pression et teste les standards. Les équipes qui maintiennent la qualité pendant la croissance ont toutes une chose en commun : le \"budget technique\" est non-négociable. 20% de la capacité de l'équipe est protégée pour la qualité, les tests, et la réduction de la dette, quelles que soient les pressions externes. Sans ce budget explicite et défendu par le CTO, la qualité se dégrade invariablement sous la pression.",{"type":29,"tag":76,"props":448,"children":449},{},[],{"type":29,"tag":176,"props":451,"children":456},{"cta":452,"href":453,"title":454,"type":455},"Accéder à l'assessment gratuit →","/mes-ressources","Ressource gratuite : Engineering Maturity Self-Assessment","resource",[457],{"type":29,"tag":37,"props":458,"children":459},{},[460],{"type":35,"value":461},"30 questions pour évaluer votre maturité engineering sur 5 dimensions. Score automatique, positionnement sur les 5 niveaux, et les 3 actions prioritaires pour transformer votre engineering en avantage concurrentiel mesurable.",{"title":8,"searchDepth":463,"depth":463,"links":464},2,[465,466,472,473,474,475],{"id":82,"depth":463,"text":85},{"id":111,"depth":463,"text":114,"children":467},[468,470,471],{"id":118,"depth":469,"text":121},3,{"id":134,"depth":469,"text":137},{"id":150,"depth":469,"text":153},{"id":193,"depth":463,"text":196},{"id":257,"depth":463,"text":260},{"id":306,"depth":463,"text":309},{"id":376,"depth":463,"text":379},"markdown","content:fr:dette-technique:ingenierie-logicielle-avantage-concurrentiel.md","content","fr/dette-technique/ingenierie-logicielle-avantage-concurrentiel.md","fr/dette-technique/ingenierie-logicielle-avantage-concurrentiel","md",{"_path":483,"_dir":484,"_draft":7,"_partial":7,"_locale":8,"title":485,"description":486,"id":487,"date":488,"listed":13,"nocomments":7,"hidden":7,"categories":489,"tags":490,"--cover":495,"readingTime":496,"body":501,"_type":476,"_id":1266,"_source":478,"_file":1267,"_stem":1268,"_extension":481},"/fr/architecture-craft/database-per-service-microservices","architecture-craft","Database per Service : quand ça vaut vraiment la complexité","Le pattern Database per Service est présenté comme obligatoire en microservices. Il ne l'est pas. Le critère objectif pour décider — et les alternatives ignorées.",35,"2026-03-25",[484],[491,492,493,494],"Microservices","Database per Service","Architecture Distribuée","Base de Données","covers/articles/database-per-service-microservices.jpg",{"text":497,"minutes":498,"time":499,"words":500},"8 min read",7.61,456600,1522,{"type":26,"children":502,"toc":1257},[503,508,520,525,530,535,538,544,549,554,573,583,593,603,616,619,625,635,645,650,659,672,690,699,702,708,713,854,864,867,873,878,886,891,1031,1036,1044,1049,1057,1062,1065,1071,1079,1104,1114,1122,1125,1131,1136,1141,1164,1167,1173,1186,1199,1212,1225,1238,1241,1251],{"type":29,"tag":30,"props":504,"children":506},{"id":505},"database-per-service-quand-ça-vaut-vraiment-la-complexité",[507],{"type":35,"value":485},{"type":29,"tag":37,"props":509,"children":510},{},[511,513,518],{"type":35,"value":512},"J'ai accompagné un client dans le secteur du commerce en ligne qui avait adopté Database per Service dès le début, par principe, avant même d'avoir 5 développeurs. 18 mois plus tard, l'équipe de 6 développeurs backend passait ",{"type":29,"tag":65,"props":514,"children":515},{},[516],{"type":35,"value":517},"30% de son temps",{"type":35,"value":519}," à gérer l'infrastructure de 20 bases de données, les sagas qui échouaient partiellement, et les incohérences de données entre services.",{"type":29,"tag":37,"props":521,"children":522},{},[523],{"type":35,"value":524},"La décision que nous avons prise ensemble : migrer 15 des 20 services vers un schéma-per-service dans une base partagée. Seuls les 5 services critiques (ceux qui avaient vraiment des besoins différents de performance, d'isolation, ou de moteur) ont conservé leur base dédiée.",{"type":29,"tag":37,"props":526,"children":527},{},[528],{"type":35,"value":529},"Résultat : le temps passé à l'infrastructure est passé de 30% à 8%. L'équipe a pu réinvestir ces heures dans de la valeur produit.",{"type":29,"tag":37,"props":531,"children":532},{},[533],{"type":35,"value":534},"Database per Service n'est pas un impératif des microservices. C'est un trade-off. Et comme tout trade-off, il se décide selon le contexte, pas selon un dogme.",{"type":29,"tag":76,"props":536,"children":537},{},[],{"type":29,"tag":80,"props":539,"children":541},{"id":540},"le-problème-réel-que-database-per-service-résout",[542],{"type":35,"value":543},"Le problème réel que Database per Service résout",{"type":29,"tag":37,"props":545,"children":546},{},[547],{"type":35,"value":548},"Sam Newman dans \"Building Microservices\" (2014) a popularisé l'idée que chaque microservice devrait posséder ses données. L'intention était valide : éviter le couplage de base de données partagée qui crée des dépendances implicites entre services.",{"type":29,"tag":37,"props":550,"children":551},{},[552],{"type":35,"value":553},"Ces couplages sont réels :",{"type":29,"tag":37,"props":555,"children":556},{},[557,562,564,571],{"type":29,"tag":65,"props":558,"children":559},{},[560],{"type":35,"value":561},"Couplage de schéma :",{"type":35,"value":563}," si le service A modifie la table ",{"type":29,"tag":565,"props":566,"children":568},"code",{"className":567},[],[569],{"type":35,"value":570},"orders",{"type":35,"value":572},", le service B qui lit cette table peut casser sans que l'équipe A s'en rende compte.",{"type":29,"tag":37,"props":574,"children":575},{},[576,581],{"type":29,"tag":65,"props":577,"children":578},{},[579],{"type":35,"value":580},"Couplage de déploiement :",{"type":35,"value":582}," une migration de base de données doit être coordonnée avec tous les services qui lisent ou écrivent les tables concernées.",{"type":29,"tag":37,"props":584,"children":585},{},[586,591],{"type":29,"tag":65,"props":587,"children":588},{},[589],{"type":35,"value":590},"Couplage de performance :",{"type":35,"value":592}," une requête lente du service A consomme des ressources de connexion qui dégradent les performances du service B.",{"type":29,"tag":37,"props":594,"children":595},{},[596,601],{"type":29,"tag":65,"props":597,"children":598},{},[599],{"type":35,"value":600},"Couplage de technologie :",{"type":35,"value":602}," tous les services sont contraints d'utiliser le même moteur de base de données, même si certains auraient besoin d'un graph database et d'autres d'un document store.",{"type":29,"tag":37,"props":604,"children":605},{},[606,608,614],{"type":35,"value":607},"Ces couplages valent la peine d'être éliminés, mais la question est : à quel coût, et avec quelle alternative ? Et la décision de les éliminer (ou de les tolérer) mérite d'être consignée dans un ",{"type":29,"tag":48,"props":609,"children":611},{"href":610},"/fr/architecture-craft/adr-architecture-decision-record",[612],{"type":35,"value":613},"Architecture Decision Record",{"type":35,"value":615}," pour que le contexte reste accessible à toute l'équipe.",{"type":29,"tag":76,"props":617,"children":618},{},[],{"type":29,"tag":80,"props":620,"children":622},{"id":621},"le-coût-réel-de-database-per-service",[623],{"type":35,"value":624},"Le coût réel de Database per Service",{"type":29,"tag":37,"props":626,"children":627},{},[628,633],{"type":29,"tag":65,"props":629,"children":630},{},[631],{"type":35,"value":632},"Complexité opérationnelle :",{"type":35,"value":634}," 10 services = 10 bases de données à provisionner, monitorer, sauvegarder, mettre à jour, et maintenir en haute disponibilité. Sur AWS, 10 instances RDS PostgreSQL coûtent entre 500 et 2 000€ par mois selon la taille, avant les coûts d'ingénierie pour les gérer.",{"type":29,"tag":37,"props":636,"children":637},{},[638,643],{"type":29,"tag":65,"props":639,"children":640},{},[641],{"type":35,"value":642},"Transactions distribuées :",{"type":35,"value":644}," sans base de données partagée, une opération qui modifie des données dans plusieurs services (créer une commande ET décrémenter le stock ET enregistrer le paiement) ne peut plus être traitée dans une transaction ACID.",{"type":29,"tag":37,"props":646,"children":647},{},[648],{"type":35,"value":649},"Il faut implémenter le pattern Saga, décrit en détail par Vernon Vaughn dans \"Implementing Domain-Driven Design\" :",{"type":29,"tag":651,"props":652,"children":654},"pre",{"code":653},"Saga chorégraphie pour la création d'une commande :\nOrderService.createOrder() → publie OrderCreated\n→ InventoryService réserve le stock → publie InventoryReserved\n→ PaymentService charge le paiement → publie PaymentProcessed\n→ OrderService confirme la commande\n\nEn cas d'échec du paiement :\n→ PaymentService publie PaymentFailed\n→ InventoryService libère la réservation\n→ OrderService annule la commande\n",[655],{"type":29,"tag":565,"props":656,"children":657},{"__ignoreMap":8},[658],{"type":35,"value":653},{"type":29,"tag":37,"props":660,"children":661},{},[662,664,670],{"type":35,"value":663},"Chaque étape peut échouer, les messages peuvent être perdus ou dupliqués, et les états intermédiaires sont difficiles à debugger. Pour renforcer la robustesse de ces flux, les ",{"type":29,"tag":48,"props":665,"children":667},{"href":666},"/fr/architecture-craft/patterns-resilience-circuit-breaker-retry",[668],{"type":35,"value":669},"patterns de résilience : circuit breaker, retry, timeout",{"type":35,"value":671}," sont indispensables dès lors que les services communiquent de manière asynchrone.",{"type":29,"tag":37,"props":673,"children":674},{},[675,680,682,688],{"type":29,"tag":65,"props":676,"children":677},{},[678],{"type":35,"value":679},"Requêtes cross-services :",{"type":35,"value":681}," une requête qui joint des données de plusieurs services (liste des commandes avec le nom du client et le stock disponible) devient une API composition : plusieurs appels HTTP en séquence ou en parallèle, avec de la logique d'agrégation en mémoire. Cette communication asynchrone entre services introduit un ",{"type":29,"tag":48,"props":683,"children":685},{"href":684},"/fr/architecture-craft/couplage-temporel-code-asynchrone",[686],{"type":35,"value":687},"couplage temporel",{"type":35,"value":689}," qu'il faut gérer explicitement, notamment avec des garanties d'idempotence et d'ordre sur les événements.",{"type":29,"tag":176,"props":691,"children":693},{"cta":178,"href":179,"title":692,"type":181},"Vous migrez vers les microservices et vous hésitez sur la stratégie de base de données ?",[694],{"type":29,"tag":37,"props":695,"children":696},{},[697],{"type":35,"value":698},"Choisir la bonne stratégie de base de données pour une architecture distribuée dépend de nombreux facteurs contextuels que j'ai appris à évaluer sur le terrain, dans la finance, les médias, la logistique. En 30 minutes, on peut évaluer les trade-offs et définir l'approche adaptée à votre situation réelle.",{"type":29,"tag":76,"props":700,"children":701},{},[],{"type":29,"tag":80,"props":703,"children":705},{"id":704},"le-cadre-de-décision-objectif",[706],{"type":35,"value":707},"Le cadre de décision objectif",{"type":29,"tag":37,"props":709,"children":710},{},[711],{"type":35,"value":712},"La question n'est pas \"devrions-nous faire Database per Service ?\", c'est \"quel niveau de couplage de base de données est acceptable dans notre contexte ?\"",{"type":29,"tag":714,"props":715,"children":716},"table",{},[717,741],{"type":29,"tag":718,"props":719,"children":720},"thead",{},[721],{"type":29,"tag":722,"props":723,"children":724},"tr",{},[725,731,736],{"type":29,"tag":726,"props":727,"children":728},"th",{},[729],{"type":35,"value":730},"Critère",{"type":29,"tag":726,"props":732,"children":733},{},[734],{"type":35,"value":735},"Favorise Database per Service",{"type":29,"tag":726,"props":737,"children":738},{},[739],{"type":35,"value":740},"Favorise Base partagée",{"type":29,"tag":742,"props":743,"children":744},"tbody",{},[745,764,782,800,818,836],{"type":29,"tag":722,"props":746,"children":747},{},[748,754,759],{"type":29,"tag":749,"props":750,"children":751},"td",{},[752],{"type":35,"value":753},"Taille de l'équipe",{"type":29,"tag":749,"props":755,"children":756},{},[757],{"type":35,"value":758},"> 15 développeurs, équipes indépendantes",{"type":29,"tag":749,"props":760,"children":761},{},[762],{"type":35,"value":763},"\u003C 15 développeurs, une seule équipe",{"type":29,"tag":722,"props":765,"children":766},{},[767,772,777],{"type":29,"tag":749,"props":768,"children":769},{},[770],{"type":35,"value":771},"Fréquence de changement de schéma",{"type":29,"tag":749,"props":773,"children":774},{},[775],{"type":35,"value":776},"Fréquente (plusieurs fois par semaine)",{"type":29,"tag":749,"props":778,"children":779},{},[780],{"type":35,"value":781},"Rare (quelques fois par mois)",{"type":29,"tag":722,"props":783,"children":784},{},[785,790,795],{"type":29,"tag":749,"props":786,"children":787},{},[788],{"type":35,"value":789},"Exigences de performance",{"type":29,"tag":749,"props":791,"children":792},{},[793],{"type":35,"value":794},"Services avec des profils d'usage très différents",{"type":29,"tag":749,"props":796,"children":797},{},[798],{"type":35,"value":799},"Profils d'usage similaires",{"type":29,"tag":722,"props":801,"children":802},{},[803,808,813],{"type":29,"tag":749,"props":804,"children":805},{},[806],{"type":35,"value":807},"Exigences de disponibilité",{"type":29,"tag":749,"props":809,"children":810},{},[811],{"type":35,"value":812},"SLAs différents par service",{"type":29,"tag":749,"props":814,"children":815},{},[816],{"type":35,"value":817},"SLA uniforme",{"type":29,"tag":722,"props":819,"children":820},{},[821,826,831],{"type":29,"tag":749,"props":822,"children":823},{},[824],{"type":35,"value":825},"Transactions cross-services",{"type":29,"tag":749,"props":827,"children":828},{},[829],{"type":35,"value":830},"Rares",{"type":29,"tag":749,"props":832,"children":833},{},[834],{"type":35,"value":835},"Fréquentes et critiques",{"type":29,"tag":722,"props":837,"children":838},{},[839,844,849],{"type":29,"tag":749,"props":840,"children":841},{},[842],{"type":35,"value":843},"Maturité opérationnelle",{"type":29,"tag":749,"props":845,"children":846},{},[847],{"type":35,"value":848},"SRE dédié, infrastructure mature",{"type":29,"tag":749,"props":850,"children":851},{},[852],{"type":35,"value":853},"Pas d'équipe infra dédiée",{"type":29,"tag":37,"props":855,"children":856},{},[857,862],{"type":29,"tag":65,"props":858,"children":859},{},[860],{"type":35,"value":861},"La règle empirique :",{"type":35,"value":863}," si les équipes qui développent les services peuvent déployer indépendamment et que les transactions cross-services sont rares, Database per Service a du sens. Sinon, le coût dépasse la valeur.",{"type":29,"tag":76,"props":865,"children":866},{},[],{"type":29,"tag":80,"props":868,"children":870},{"id":869},"les-alternatives-ignorées",[871],{"type":35,"value":872},"Les alternatives ignorées",{"type":29,"tag":37,"props":874,"children":875},{},[876],{"type":35,"value":877},"Avant de sauter à \"une base de données par service\", il existe des options intermédiaires qui réduisent le couplage sans la complexité complète.",{"type":29,"tag":37,"props":879,"children":880},{},[881],{"type":29,"tag":65,"props":882,"children":883},{},[884],{"type":35,"value":885},"Option 1 : Schema per Service (dans la même base de données)",{"type":29,"tag":37,"props":887,"children":888},{},[889],{"type":35,"value":890},"Chaque service possède son schéma (namespace) dans une base de données partagée. Le service A ne peut accéder qu'aux tables du schéma A.",{"type":29,"tag":651,"props":892,"children":896},{"code":893,"language":894,"meta":8,"className":895,"style":8},"-- Service A n'accède qu'à son schéma\nSET search_path TO ordering;\nSELECT * FROM orders;  -- → ordering.orders\n\n-- Service B n'accède qu'à son schéma\nSET search_path TO inventory;\nSELECT * FROM products;  -- → inventory.products\n","sql","language-sql shiki shiki-themes catppuccin-frappe github-dark",[897],{"type":29,"tag":565,"props":898,"children":899},{"__ignoreMap":8},[900,912,937,966,975,984,1005],{"type":29,"tag":901,"props":902,"children":905},"span",{"class":903,"line":904},"line",1,[906],{"type":29,"tag":901,"props":907,"children":909},{"style":908},"--shiki-default:#737994;--shiki-default-font-style:italic;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit",[910],{"type":35,"value":911},"-- Service A n'accède qu'à son schéma\n",{"type":29,"tag":901,"props":913,"children":914},{"class":903,"line":463},[915,921,927,932],{"type":29,"tag":901,"props":916,"children":918},{"style":917},"--shiki-default:#CA9EE6;--shiki-dark:#F97583",[919],{"type":35,"value":920},"SET",{"type":29,"tag":901,"props":922,"children":924},{"style":923},"--shiki-default:#C6D0F5;--shiki-dark:#E1E4E8",[925],{"type":35,"value":926}," search_path ",{"type":29,"tag":901,"props":928,"children":929},{"style":917},[930],{"type":35,"value":931},"TO",{"type":29,"tag":901,"props":933,"children":934},{"style":923},[935],{"type":35,"value":936}," ordering;\n",{"type":29,"tag":901,"props":938,"children":939},{"class":903,"line":469},[940,945,951,956,961],{"type":29,"tag":901,"props":941,"children":942},{"style":917},[943],{"type":35,"value":944},"SELECT",{"type":29,"tag":901,"props":946,"children":948},{"style":947},"--shiki-default:#81C8BE;--shiki-dark:#F97583",[949],{"type":35,"value":950}," *",{"type":29,"tag":901,"props":952,"children":953},{"style":917},[954],{"type":35,"value":955}," FROM",{"type":29,"tag":901,"props":957,"children":958},{"style":923},[959],{"type":35,"value":960}," orders;  ",{"type":29,"tag":901,"props":962,"children":963},{"style":908},[964],{"type":35,"value":965},"-- → ordering.orders\n",{"type":29,"tag":901,"props":967,"children":969},{"class":903,"line":968},4,[970],{"type":29,"tag":901,"props":971,"children":972},{"emptyLinePlaceholder":13},[973],{"type":35,"value":974},"\n",{"type":29,"tag":901,"props":976,"children":978},{"class":903,"line":977},5,[979],{"type":29,"tag":901,"props":980,"children":981},{"style":908},[982],{"type":35,"value":983},"-- Service B n'accède qu'à son schéma\n",{"type":29,"tag":901,"props":985,"children":987},{"class":903,"line":986},6,[988,992,996,1000],{"type":29,"tag":901,"props":989,"children":990},{"style":917},[991],{"type":35,"value":920},{"type":29,"tag":901,"props":993,"children":994},{"style":923},[995],{"type":35,"value":926},{"type":29,"tag":901,"props":997,"children":998},{"style":917},[999],{"type":35,"value":931},{"type":29,"tag":901,"props":1001,"children":1002},{"style":923},[1003],{"type":35,"value":1004}," inventory;\n",{"type":29,"tag":901,"props":1006,"children":1008},{"class":903,"line":1007},7,[1009,1013,1017,1021,1026],{"type":29,"tag":901,"props":1010,"children":1011},{"style":917},[1012],{"type":35,"value":944},{"type":29,"tag":901,"props":1014,"children":1015},{"style":947},[1016],{"type":35,"value":950},{"type":29,"tag":901,"props":1018,"children":1019},{"style":917},[1020],{"type":35,"value":955},{"type":29,"tag":901,"props":1022,"children":1023},{"style":923},[1024],{"type":35,"value":1025}," products;  ",{"type":29,"tag":901,"props":1027,"children":1028},{"style":908},[1029],{"type":35,"value":1030},"-- → inventory.products\n",{"type":29,"tag":37,"props":1032,"children":1033},{},[1034],{"type":35,"value":1035},"Avantages : les transactions ACID restent possibles si nécessaire. Complexité opérationnelle minimale (une seule base de données).",{"type":29,"tag":37,"props":1037,"children":1038},{},[1039],{"type":29,"tag":65,"props":1040,"children":1041},{},[1042],{"type":35,"value":1043},"Option 2 : Read replicas dédiées par service",{"type":29,"tag":37,"props":1045,"children":1046},{},[1047],{"type":35,"value":1048},"La base de données principale est partagée pour les écritures, mais chaque service lit depuis sa propre replica read-only synchronisée. Utile quand le problème principal est la contention de lecture.",{"type":29,"tag":37,"props":1050,"children":1051},{},[1052],{"type":29,"tag":65,"props":1053,"children":1054},{},[1055],{"type":35,"value":1056},"Option 3 : CQRS sans séparation de base",{"type":29,"tag":37,"props":1058,"children":1059},{},[1060],{"type":35,"value":1061},"Séparer les modèles de lecture et d'écriture sans nécessairement avoir des bases de données séparées. Les requêtes complexes lisent des vues matérialisées maintenues à jour par des événements.",{"type":29,"tag":76,"props":1063,"children":1064},{},[],{"type":29,"tag":80,"props":1066,"children":1068},{"id":1067},"quand-migrer-vers-database-per-service",[1069],{"type":35,"value":1070},"Quand migrer vers Database per Service",{"type":29,"tag":37,"props":1072,"children":1073},{},[1074],{"type":29,"tag":65,"props":1075,"children":1076},{},[1077],{"type":35,"value":1078},"Les signaux que la base partagée devient un problème :",{"type":29,"tag":1080,"props":1081,"children":1082},"ul",{},[1083,1089,1094,1099],{"type":29,"tag":1084,"props":1085,"children":1086},"li",{},[1087],{"type":35,"value":1088},"Les migrations de base de données nécessitent de coordonner 3 équipes ou plus",{"type":29,"tag":1084,"props":1090,"children":1091},{},[1092],{"type":35,"value":1093},"Un service lent dégrade régulièrement les performances des autres",{"type":29,"tag":1084,"props":1095,"children":1096},{},[1097],{"type":35,"value":1098},"Deux services ont des besoins contradictoires sur le schéma d'une table partagée",{"type":29,"tag":1084,"props":1100,"children":1101},{},[1102],{"type":35,"value":1103},"L'équipe veut utiliser un moteur de base de données différent pour un service spécifique",{"type":29,"tag":37,"props":1105,"children":1106},{},[1107,1112],{"type":29,"tag":65,"props":1108,"children":1109},{},[1110],{"type":35,"value":1111},"La migration progressive :",{"type":35,"value":1113}," commencer par les tables du service le plus indépendant. Migrer la table, mettre en place la synchronisation des données si nécessaire (CDC avec Debezium, événements de domaine), valider, puis passer à la table suivante.",{"type":29,"tag":651,"props":1115,"children":1117},{"code":1116},"Plan de migration en 4 phases :\nPhase 1 : service de notifications (aucune dépendance cross-service)\nPhase 2 : service de recherche (lecture seule, pas d'écriture cross-service)\nPhase 3 : service de catalogue produit (écriture rarement liée aux autres)\nPhase 4 : service de commandes (transactions complexes — laisser pour dernier)\n",[1118],{"type":29,"tag":565,"props":1119,"children":1120},{"__ignoreMap":8},[1121],{"type":35,"value":1116},{"type":29,"tag":76,"props":1123,"children":1124},{},[],{"type":29,"tag":80,"props":1126,"children":1128},{"id":1127},"le-cas-particulier-du-polyglot-persistence",[1129],{"type":35,"value":1130},"Le cas particulier du polyglot persistence",{"type":29,"tag":37,"props":1132,"children":1133},{},[1134],{"type":35,"value":1135},"Database per Service devient moins coûteux quand les services utilisent des bases de données managées (DynamoDB, MongoDB Atlas, Redis Cloud) avec une facturation à l'usage. Le coût opérationnel est absorbé par le fournisseur.",{"type":29,"tag":37,"props":1137,"children":1138},{},[1139],{"type":35,"value":1140},"Le pattern polyglot persistence (chaque service utilise le moteur adapté à ses besoins) ne vaut sa complexité que si les besoins sont vraiment distincts et que l'équipe a la maturité opérationnelle pour gérer plusieurs moteurs.",{"type":29,"tag":1080,"props":1142,"children":1143},{},[1144,1149,1154,1159],{"type":29,"tag":1084,"props":1145,"children":1146},{},[1147],{"type":35,"value":1148},"Service de recherche → Elasticsearch",{"type":29,"tag":1084,"props":1150,"children":1151},{},[1152],{"type":35,"value":1153},"Service de sessions → Redis",{"type":29,"tag":1084,"props":1155,"children":1156},{},[1157],{"type":35,"value":1158},"Service de catalogue → MongoDB (documents flexibles)",{"type":29,"tag":1084,"props":1160,"children":1161},{},[1162],{"type":35,"value":1163},"Service de commandes → PostgreSQL (transactions ACID)",{"type":29,"tag":76,"props":1165,"children":1166},{},[],{"type":29,"tag":80,"props":1168,"children":1170},{"id":1169},"faq-sur-database-per-service",[1171],{"type":35,"value":1172},"FAQ sur Database per Service",{"type":29,"tag":381,"props":1174,"children":1175},{},[1176,1181],{"type":29,"tag":385,"props":1177,"children":1178},{},[1179],{"type":35,"value":1180},"1. Comment gérer la cohérence des données entre services sans transactions distribuées ?",{"type":29,"tag":37,"props":1182,"children":1183},{},[1184],{"type":35,"value":1185},"Eventual consistency avec compensation. Accepter que les données ne soient pas instantanément cohérentes entre services, seulement éventuellement cohérentes. Pour les cas où une cohérence forte est nécessaire, utiliser le pattern Outbox : écrire l'événement dans la même transaction que la donnée, puis publier l'événement de façon asynchrone. Pour les cas d'échec, implémenter des compensating transactions explicites plutôt que des rollbacks automatiques.",{"type":29,"tag":381,"props":1187,"children":1188},{},[1189,1194],{"type":29,"tag":385,"props":1190,"children":1191},{},[1192],{"type":35,"value":1193},"2. Peut-on utiliser des transactions distribuées (2PC) à la place des Sagas ?",{"type":29,"tag":37,"props":1195,"children":1196},{},[1197],{"type":35,"value":1198},"Techniquement oui, mais déconseillé. Le Two-Phase Commit est lent (lock pendant la phase de préparation), fragile (coordinator failure = système bloqué), et complexe à implémenter correctement. Les Sagas sont plus complexes à concevoir mais plus robustes en production. La recommandation de Sam Newman et de l'industrie : éviter 2PC, préférer les Sagas ou revoir l'architecture pour réduire les transactions cross-services.",{"type":29,"tag":381,"props":1200,"children":1201},{},[1202,1207],{"type":29,"tag":385,"props":1203,"children":1204},{},[1205],{"type":35,"value":1206},"3. Comment gérer les reportings qui nécessitent des données de plusieurs services ?",{"type":29,"tag":37,"props":1208,"children":1209},{},[1210],{"type":35,"value":1211},"Data warehouse ou OLAP dédié. Chaque service publie ses événements vers un pipeline de données (Kafka → Spark/Flink → Data Warehouse). Les analyses et rapports lisent le data warehouse, pas les bases des services. C'est le principe CQRS à l'échelle de l'architecture : les services gèrent les écritures, le data warehouse gère les lectures analytiques complexes.",{"type":29,"tag":381,"props":1213,"children":1214},{},[1215,1220],{"type":29,"tag":385,"props":1216,"children":1217},{},[1218],{"type":35,"value":1219},"4. Quel outil utiliser pour la synchronisation de données entre services ?",{"type":29,"tag":37,"props":1221,"children":1222},{},[1223],{"type":35,"value":1224},"Change Data Capture (CDC) avec Debezium : il capture les changements PostgreSQL/MySQL en temps réel et les publie sur Kafka. Pour des cas plus simples : événements de domaine publiés sur une queue à chaque changement d'état. L'approche CDC est plus robuste (aucun changement applicatif requis) mais plus complexe à opérer. Les événements de domaine sont plus simples mais nécessitent une discipline applicative.",{"type":29,"tag":381,"props":1226,"children":1227},{},[1228,1233],{"type":29,"tag":385,"props":1229,"children":1230},{},[1231],{"type":35,"value":1232},"5. Database per Service est-il compatible avec les architectures serverless (Lambda, Cloud Functions) ?",{"type":29,"tag":37,"props":1234,"children":1235},{},[1236],{"type":35,"value":1237},"Oui, et c'est souvent plus simple. Les bases de données managées à l'usage (DynamoDB, Firestore, Aurora Serverless) s'adaptent naturellement au modèle serverless : pas de pool de connexions à gérer, facturation à la requête. Le principal défi est la gestion des connexions (Lambda peut créer des milliers de connexions simultanées), résolu par des proxy de connexions comme RDS Proxy pour PostgreSQL/MySQL.",{"type":29,"tag":76,"props":1239,"children":1240},{},[],{"type":29,"tag":176,"props":1242,"children":1245},{"cta":1243,"href":1244,"title":454,"type":455},"Faire mon auto-évaluation →","/ema",[1246],{"type":29,"tag":37,"props":1247,"children":1248},{},[1249],{"type":35,"value":1250},"L'Engineering Maturity Self-Assessment couvre le domaine Architecture Distribuée : évaluez votre maturité sur le découpage des services, la gestion des données, et la résilience. Score et plan d'action en 10 minutes.",{"type":29,"tag":1252,"props":1253,"children":1254},"style",{},[1255],{"type":35,"value":1256},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":8,"searchDepth":463,"depth":463,"links":1258},[1259,1260,1261,1262,1263,1264,1265],{"id":540,"depth":463,"text":543},{"id":621,"depth":463,"text":624},{"id":704,"depth":463,"text":707},{"id":869,"depth":463,"text":872},{"id":1067,"depth":463,"text":1070},{"id":1127,"depth":463,"text":1130},{"id":1169,"depth":463,"text":1172},"content:fr:architecture-craft:database-per-service-microservices.md","fr/architecture-craft/database-per-service-microservices.md","fr/architecture-craft/database-per-service-microservices",{"_path":1270,"_dir":1271,"_draft":7,"_partial":7,"_locale":8,"title":1272,"description":1273,"id":1274,"date":1275,"listed":13,"nocomments":7,"hidden":7,"categories":1276,"tags":1277,"--cover":1282,"readingTime":1283,"body":1287,"_type":476,"_id":2113,"_source":478,"_file":2114,"_stem":2115,"_extension":481},"/fr/management/delegation-technique-confiance","management","Délégation technique : la matrice par niveau de séniorité","La délégation technique ne se fait pas de la même façon selon le niveau du développeur. La matrice qui évite le micro-management et l'abandon — et comment construire la confiance progressivement.",34,"2026-03-23",[1271],[1278,1279,1280,1281],"Délégation","Management","Séniorité","Confiance","covers/articles/delegation-technique-confiance.jpg",{"text":497,"minutes":1284,"time":1285,"words":1286},7.99,479400,1598,{"type":26,"children":1288,"toc":2101},[1289,1294,1299,1304,1316,1319,1325,1335,1345,1355,1365,1375,1378,1384,1390,1521,1531,1534,1540,1666,1676,1685,1688,1694,1820,1830,1833,1839,1852,1860,1870,1880,1890,1900,1903,1909,1917,1940,1948,1971,1981,1984,1990,1995,2000,2003,2009,2030,2043,2056,2077,2090,2093],{"type":29,"tag":30,"props":1290,"children":1292},{"id":1291},"délégation-technique-la-matrice-par-niveau-de-séniorité",[1293],{"type":35,"value":1272},{"type":29,"tag":37,"props":1295,"children":1296},{},[1297],{"type":35,"value":1298},"J'ai fait les deux erreurs. Chez Crédit Agricole, j'ai micro-managé un développeur senior sur son domaine de compétence : je relisais ses PR ligne par ligne, je lui demandais de justifier chaque choix d'implémentation. Il est parti au bout de 8 mois. Son feedback d'adieu : \"Je me sentais traité comme un junior.\" Dans une autre organisation, j'ai délégué une décision d'architecture à un développeur junior sans filet de sécurité. Il a passé 3 semaines à tourner en rond sans oser dire qu'il était perdu. La feature a pris 6 semaines de retard.",{"type":29,"tag":37,"props":1300,"children":1301},{},[1302],{"type":35,"value":1303},"Le micro-management détruit les meilleurs. L'abandon détruit les moins expérimentés. La délégation efficace est la zone entre les deux, et elle se calibre par personne, par tâche, et par contexte.",{"type":29,"tag":37,"props":1305,"children":1306},{},[1307,1309,1314],{"type":35,"value":1308},"Hersey & Blanchard ont formalisé ce principe dans le modèle du Situational Leadership : le niveau d'autonomie accordé doit correspondre au niveau de compétence et de motivation du collaborateur ",{"type":29,"tag":65,"props":1310,"children":1311},{},[1312],{"type":35,"value":1313},"sur la tâche spécifique",{"type":35,"value":1315},". Pas sur la personne en général. Un développeur senior peut être en pleine autonomie sur l'architecture d'un service et avoir besoin d'accompagnement sur la facilitation d'un atelier. La délégation se calibre par tâche, pas par titre.",{"type":29,"tag":76,"props":1317,"children":1318},{},[],{"type":29,"tag":80,"props":1320,"children":1322},{"id":1321},"les-4-niveaux-de-délégation",[1323],{"type":35,"value":1324},"Les 4 niveaux de délégation",{"type":29,"tag":37,"props":1326,"children":1327},{},[1328,1333],{"type":29,"tag":65,"props":1329,"children":1330},{},[1331],{"type":35,"value":1332},"Niveau D1 : Direction :",{"type":35,"value":1334}," faible compétence, forte motivation. Le développeur est enthousiaste mais ne sait pas encore faire. Je décide et j'explique pourquoi.",{"type":29,"tag":37,"props":1336,"children":1337},{},[1338,1343],{"type":29,"tag":65,"props":1339,"children":1340},{},[1341],{"type":35,"value":1342},"Niveau D2 : Coaching :",{"type":35,"value":1344}," compétence croissante, motivation variable. Le développeur commence à maîtriser mais manque de confiance. Je décide après discussion, j'explique le raisonnement.",{"type":29,"tag":37,"props":1346,"children":1347},{},[1348,1353],{"type":29,"tag":65,"props":1349,"children":1350},{},[1351],{"type":35,"value":1352},"Niveau D3 : Support :",{"type":35,"value":1354}," compétence forte, motivation variable. Le développeur sait faire mais hésite à décider seul. Il propose, je valide ou je questionne.",{"type":29,"tag":37,"props":1356,"children":1357},{},[1358,1363],{"type":29,"tag":65,"props":1359,"children":1360},{},[1361],{"type":35,"value":1362},"Niveau D4 : Délégation complète :",{"type":35,"value":1364}," compétence forte, forte motivation. Le développeur sait faire et veut le faire. Il décide, je suis informé.",{"type":29,"tag":37,"props":1366,"children":1367},{},[1368,1373],{"type":29,"tag":65,"props":1369,"children":1370},{},[1371],{"type":35,"value":1372},"L'erreur que je vois le plus souvent :",{"type":35,"value":1374}," traiter une personne au même niveau sur toutes les dimensions. Un développeur senior peut être D4 sur son périmètre technique et D1 sur la conduite d'un entretien de recrutement. La matrice ne s'applique pas à la personne : elle s'applique à la combinaison personne + tâche.",{"type":29,"tag":76,"props":1376,"children":1377},{},[],{"type":29,"tag":80,"props":1379,"children":1381},{"id":1380},"la-matrice-de-délégation-par-domaine-et-séniorité",[1382],{"type":35,"value":1383},"La matrice de délégation par domaine et séniorité",{"type":29,"tag":116,"props":1385,"children":1387},{"id":1386},"développeur-junior-0-2-ans-dexpérience",[1388],{"type":35,"value":1389},"Développeur junior (0-2 ans d'expérience)",{"type":29,"tag":714,"props":1391,"children":1392},{},[1393,1414],{"type":29,"tag":718,"props":1394,"children":1395},{},[1396],{"type":29,"tag":722,"props":1397,"children":1398},{},[1399,1404,1409],{"type":29,"tag":726,"props":1400,"children":1401},{},[1402],{"type":35,"value":1403},"Domaine de décision",{"type":29,"tag":726,"props":1405,"children":1406},{},[1407],{"type":35,"value":1408},"Niveau de délégation",{"type":29,"tag":726,"props":1410,"children":1411},{},[1412],{"type":35,"value":1413},"Ce que ça signifie en pratique",{"type":29,"tag":742,"props":1415,"children":1416},{},[1417,1435,1453,1470,1487,1504],{"type":29,"tag":722,"props":1418,"children":1419},{},[1420,1425,1430],{"type":29,"tag":749,"props":1421,"children":1422},{},[1423],{"type":35,"value":1424},"Implémentation d'une story",{"type":29,"tag":749,"props":1426,"children":1427},{},[1428],{"type":35,"value":1429},"D2",{"type":29,"tag":749,"props":1431,"children":1432},{},[1433],{"type":35,"value":1434},"Le junior propose l'approche, validation avant de commencer",{"type":29,"tag":722,"props":1436,"children":1437},{},[1438,1443,1448],{"type":29,"tag":749,"props":1439,"children":1440},{},[1441],{"type":35,"value":1442},"Choix de librairie",{"type":29,"tag":749,"props":1444,"children":1445},{},[1446],{"type":35,"value":1447},"D1",{"type":29,"tag":749,"props":1449,"children":1450},{},[1451],{"type":35,"value":1452},"Je choisis avec explication",{"type":29,"tag":722,"props":1454,"children":1455},{},[1456,1461,1465],{"type":29,"tag":749,"props":1457,"children":1458},{},[1459],{"type":35,"value":1460},"Architecture d'un service",{"type":29,"tag":749,"props":1462,"children":1463},{},[1464],{"type":35,"value":1447},{"type":29,"tag":749,"props":1466,"children":1467},{},[1468],{"type":35,"value":1469},"Décision manager/senior, explication détaillée",{"type":29,"tag":722,"props":1471,"children":1472},{},[1473,1478,1482],{"type":29,"tag":749,"props":1474,"children":1475},{},[1476],{"type":35,"value":1477},"Refactoring local",{"type":29,"tag":749,"props":1479,"children":1480},{},[1481],{"type":35,"value":1429},{"type":29,"tag":749,"props":1483,"children":1484},{},[1485],{"type":35,"value":1486},"Proposition + validation avant merge",{"type":29,"tag":722,"props":1488,"children":1489},{},[1490,1495,1499],{"type":29,"tag":749,"props":1491,"children":1492},{},[1493],{"type":35,"value":1494},"Tests à écrire",{"type":29,"tag":749,"props":1496,"children":1497},{},[1498],{"type":35,"value":1429},{"type":29,"tag":749,"props":1500,"children":1501},{},[1502],{"type":35,"value":1503},"Proposition + review attentive",{"type":29,"tag":722,"props":1505,"children":1506},{},[1507,1512,1516],{"type":29,"tag":749,"props":1508,"children":1509},{},[1510],{"type":35,"value":1511},"Communication avec le PO",{"type":29,"tag":749,"props":1513,"children":1514},{},[1515],{"type":35,"value":1447},{"type":29,"tag":749,"props":1517,"children":1518},{},[1519],{"type":35,"value":1520},"Manager/senior présent ou brief avant",{"type":29,"tag":37,"props":1522,"children":1523},{},[1524,1529],{"type":29,"tag":65,"props":1525,"children":1526},{},[1527],{"type":35,"value":1528},"Ma règle pour le junior :",{"type":35,"value":1530}," jamais de décision irréversible sans validation. Les décisions réversibles (un commit sur une branche locale, une exploration technique) peuvent être prises en autonomie. Les décisions irréversibles (merge en production, modification de schéma de base de données) nécessitent une validation.",{"type":29,"tag":76,"props":1532,"children":1533},{},[],{"type":29,"tag":116,"props":1535,"children":1537},{"id":1536},"développeur-intermédiaire-2-5-ans-dexpérience",[1538],{"type":35,"value":1539},"Développeur intermédiaire (2-5 ans d'expérience)",{"type":29,"tag":714,"props":1541,"children":1542},{},[1543,1561],{"type":29,"tag":718,"props":1544,"children":1545},{},[1546],{"type":29,"tag":722,"props":1547,"children":1548},{},[1549,1553,1557],{"type":29,"tag":726,"props":1550,"children":1551},{},[1552],{"type":35,"value":1403},{"type":29,"tag":726,"props":1554,"children":1555},{},[1556],{"type":35,"value":1408},{"type":29,"tag":726,"props":1558,"children":1559},{},[1560],{"type":35,"value":1413},{"type":29,"tag":742,"props":1562,"children":1563},{},[1564,1581,1598,1615,1632,1649],{"type":29,"tag":722,"props":1565,"children":1566},{},[1567,1571,1576],{"type":29,"tag":749,"props":1568,"children":1569},{},[1570],{"type":35,"value":1424},{"type":29,"tag":749,"props":1572,"children":1573},{},[1574],{"type":35,"value":1575},"D3-D4",{"type":29,"tag":749,"props":1577,"children":1578},{},[1579],{"type":35,"value":1580},"Pleine autonomie sur l'implémentation",{"type":29,"tag":722,"props":1582,"children":1583},{},[1584,1588,1593],{"type":29,"tag":749,"props":1585,"children":1586},{},[1587],{"type":35,"value":1442},{"type":29,"tag":749,"props":1589,"children":1590},{},[1591],{"type":35,"value":1592},"D3",{"type":29,"tag":749,"props":1594,"children":1595},{},[1596],{"type":35,"value":1597},"Propose + justifie, validation légère",{"type":29,"tag":722,"props":1599,"children":1600},{},[1601,1605,1610],{"type":29,"tag":749,"props":1602,"children":1603},{},[1604],{"type":35,"value":1460},{"type":29,"tag":749,"props":1606,"children":1607},{},[1608],{"type":35,"value":1609},"D2-D3",{"type":29,"tag":749,"props":1611,"children":1612},{},[1613],{"type":35,"value":1614},"Co-construction avec le manager/senior",{"type":29,"tag":722,"props":1616,"children":1617},{},[1618,1623,1627],{"type":29,"tag":749,"props":1619,"children":1620},{},[1621],{"type":35,"value":1622},"Refactoring de périmètre moyen",{"type":29,"tag":749,"props":1624,"children":1625},{},[1626],{"type":35,"value":1592},{"type":29,"tag":749,"props":1628,"children":1629},{},[1630],{"type":35,"value":1631},"Autonomie avec point d'étape",{"type":29,"tag":722,"props":1633,"children":1634},{},[1635,1640,1644],{"type":29,"tag":749,"props":1636,"children":1637},{},[1638],{"type":35,"value":1639},"Découpage de stories",{"type":29,"tag":749,"props":1641,"children":1642},{},[1643],{"type":35,"value":1592},{"type":29,"tag":749,"props":1645,"children":1646},{},[1647],{"type":35,"value":1648},"Propose le découpage, validation PO/manager",{"type":29,"tag":722,"props":1650,"children":1651},{},[1652,1657,1661],{"type":29,"tag":749,"props":1653,"children":1654},{},[1655],{"type":35,"value":1656},"Mentoring d'un junior",{"type":29,"tag":749,"props":1658,"children":1659},{},[1660],{"type":35,"value":1429},{"type":29,"tag":749,"props":1662,"children":1663},{},[1664],{"type":35,"value":1665},"Encadré par le senior au début",{"type":29,"tag":37,"props":1667,"children":1668},{},[1669,1674],{"type":29,"tag":65,"props":1670,"children":1671},{},[1672],{"type":35,"value":1673},"Ma règle pour l'intermédiaire :",{"type":35,"value":1675}," autonomie sur l'exécution, validation sur les décisions d'impact moyen à fort. L'intermédiaire doit être challengé à prendre des décisions et à les justifier, pas protégé de toute décision. C'est dans cet espace inconfortable que la progression se fait.",{"type":29,"tag":176,"props":1677,"children":1679},{"cta":178,"href":179,"title":1678,"type":181},"Vous peinez à calibrer le bon niveau d'autonomie pour chaque membre de votre équipe ?",[1680],{"type":29,"tag":37,"props":1681,"children":1682},{},[1683],{"type":35,"value":1684},"Vous avez peut-être des seniors frustrés par trop de contrôle et des juniors perdus par trop de liberté, dans la même équipe. Construire un système de délégation progressive adapté nécessite un audit des compétences et des niveaux de confiance actuels. En 30 minutes, je peux définir avec vous la matrice de délégation adaptée à vos 3 à 4 profils clés.",{"type":29,"tag":76,"props":1686,"children":1687},{},[],{"type":29,"tag":116,"props":1689,"children":1691},{"id":1690},"développeur-senior-5-ans-dexpérience",[1692],{"type":35,"value":1693},"Développeur senior (5+ ans d'expérience)",{"type":29,"tag":714,"props":1695,"children":1696},{},[1697,1715],{"type":29,"tag":718,"props":1698,"children":1699},{},[1700],{"type":29,"tag":722,"props":1701,"children":1702},{},[1703,1707,1711],{"type":29,"tag":726,"props":1704,"children":1705},{},[1706],{"type":35,"value":1403},{"type":29,"tag":726,"props":1708,"children":1709},{},[1710],{"type":35,"value":1408},{"type":29,"tag":726,"props":1712,"children":1713},{},[1714],{"type":35,"value":1413},{"type":29,"tag":742,"props":1716,"children":1717},{},[1718,1734,1752,1769,1786,1803],{"type":29,"tag":722,"props":1719,"children":1720},{},[1721,1725,1729],{"type":29,"tag":749,"props":1722,"children":1723},{},[1724],{"type":35,"value":1460},{"type":29,"tag":749,"props":1726,"children":1727},{},[1728],{"type":35,"value":1575},{"type":29,"tag":749,"props":1730,"children":1731},{},[1732],{"type":35,"value":1733},"Décision senior, information manager",{"type":29,"tag":722,"props":1735,"children":1736},{},[1737,1742,1747],{"type":29,"tag":749,"props":1738,"children":1739},{},[1740],{"type":35,"value":1741},"Choix technologique d'impact limité",{"type":29,"tag":749,"props":1743,"children":1744},{},[1745],{"type":35,"value":1746},"D4",{"type":29,"tag":749,"props":1748,"children":1749},{},[1750],{"type":35,"value":1751},"Pleine autonomie",{"type":29,"tag":722,"props":1753,"children":1754},{},[1755,1760,1764],{"type":29,"tag":749,"props":1756,"children":1757},{},[1758],{"type":35,"value":1759},"Choix technologique d'impact fort",{"type":29,"tag":749,"props":1761,"children":1762},{},[1763],{"type":35,"value":1592},{"type":29,"tag":749,"props":1765,"children":1766},{},[1767],{"type":35,"value":1768},"Proposition structurée (ADR), validation manager/CTO",{"type":29,"tag":722,"props":1770,"children":1771},{},[1772,1777,1781],{"type":29,"tag":749,"props":1773,"children":1774},{},[1775],{"type":35,"value":1776},"Standards d'équipe",{"type":29,"tag":749,"props":1778,"children":1779},{},[1780],{"type":35,"value":1592},{"type":29,"tag":749,"props":1782,"children":1783},{},[1784],{"type":35,"value":1785},"Propose, présente à l'équipe, manager valide",{"type":29,"tag":722,"props":1787,"children":1788},{},[1789,1794,1798],{"type":29,"tag":749,"props":1790,"children":1791},{},[1792],{"type":35,"value":1793},"Recrutement technique",{"type":29,"tag":749,"props":1795,"children":1796},{},[1797],{"type":35,"value":1592},{"type":29,"tag":749,"props":1799,"children":1800},{},[1801],{"type":35,"value":1802},"Conduit les entretiens techniques, input sur la décision",{"type":29,"tag":722,"props":1804,"children":1805},{},[1806,1811,1815],{"type":29,"tag":749,"props":1807,"children":1808},{},[1809],{"type":35,"value":1810},"Architecture cross-services",{"type":29,"tag":749,"props":1812,"children":1813},{},[1814],{"type":35,"value":1609},{"type":29,"tag":749,"props":1816,"children":1817},{},[1818],{"type":35,"value":1819},"Co-construction avec le CTO",{"type":29,"tag":37,"props":1821,"children":1822},{},[1823,1828],{"type":29,"tag":65,"props":1824,"children":1825},{},[1826],{"type":35,"value":1827},"Ma règle pour le senior :",{"type":35,"value":1829}," autonomie forte sur son périmètre de compétence, co-construction sur les décisions d'impact organisationnel. Le micro-management d'un senior sur son domaine de compétence est la première cause de départ des profils techniques forts. J'ai appris ça de la pire façon.",{"type":29,"tag":76,"props":1831,"children":1832},{},[],{"type":29,"tag":80,"props":1834,"children":1836},{"id":1835},"comment-construire-la-confiance-pour-déléguer-davantage",[1837],{"type":35,"value":1838},"Comment construire la confiance pour déléguer davantage",{"type":29,"tag":37,"props":1840,"children":1841},{},[1842,1844,1850],{"type":35,"value":1843},"La délégation ne se donne pas avec l'ancienneté. Elle se construit dans les deux sens, elle repose sur la ",{"type":29,"tag":48,"props":1845,"children":1847},{"href":1846},"/fr/management/confiance-equipe-engineering",[1848],{"type":35,"value":1849},"confiance",{"type":35,"value":1851}," comme substrat indispensable : le développeur démontre qu'il peut gérer une décision, je délègue la suivante. Le cycle est symétrique.",{"type":29,"tag":37,"props":1853,"children":1854},{},[1855],{"type":29,"tag":65,"props":1856,"children":1857},{},[1858],{"type":35,"value":1859},"Les 4 étapes du cycle de délégation que j'utilise :",{"type":29,"tag":37,"props":1861,"children":1862},{},[1863,1868],{"type":29,"tag":65,"props":1864,"children":1865},{},[1866],{"type":35,"value":1867},"Étape 1 : Mission claire :",{"type":35,"value":1869}," je définis clairement le périmètre de la décision, les contraintes, et les critères de succès. Pas \"améliore les tests\" : \"augmente la couverture du service X de 40% à 70% en ciblant les fonctions critiques, budget : 3 jours.\"",{"type":29,"tag":37,"props":1871,"children":1872},{},[1873,1878],{"type":29,"tag":65,"props":1874,"children":1875},{},[1876],{"type":35,"value":1877},"Étape 2 : Filet de sécurité défini :",{"type":35,"value":1879}," je définit en avance ce qui déclencherait une escalade. \"Si tu rencontres des dépendances avec le service Y ou si l'implémentation prend plus de 5 jours, viens me voir avant de continuer.\" Le filet rassure le développeur et me protège.",{"type":29,"tag":37,"props":1881,"children":1882},{},[1883,1888],{"type":29,"tag":65,"props":1884,"children":1885},{},[1886],{"type":35,"value":1887},"Étape 3 : Autonomie réelle :",{"type":35,"value":1889}," entre le début et le filet de sécurité, le développeur décide seul. Je ne vérifie pas l'avancement quotidiennement, sauf si le développeur le demande.",{"type":29,"tag":37,"props":1891,"children":1892},{},[1893,1898],{"type":29,"tag":65,"props":1894,"children":1895},{},[1896],{"type":35,"value":1897},"Étape 4 : Débriefing :",{"type":35,"value":1899}," après la mission, un point sur les décisions prises. \"Qu'est-ce que tu ferais différemment ? Qu'est-ce que tu as appris ?\" Ce n'est pas un contrôle : c'est un apprentissage partagé.",{"type":29,"tag":76,"props":1901,"children":1902},{},[],{"type":29,"tag":80,"props":1904,"children":1906},{"id":1905},"les-signaux-dune-délégation-mal-calibrée",[1907],{"type":35,"value":1908},"Les signaux d'une délégation mal calibrée",{"type":29,"tag":37,"props":1910,"children":1911},{},[1912],{"type":29,"tag":65,"props":1913,"children":1914},{},[1915],{"type":35,"value":1916},"Signaux de sur-délégation (trop d'autonomie trop tôt) :",{"type":29,"tag":1080,"props":1918,"children":1919},{},[1920,1925,1930,1935],{"type":29,"tag":1084,"props":1921,"children":1922},{},[1923],{"type":35,"value":1924},"Le développeur pose des questions sur chaque micro-décision",{"type":29,"tag":1084,"props":1926,"children":1927},{},[1928],{"type":35,"value":1929},"Les délais glissent sans alerte de sa part",{"type":29,"tag":1084,"props":1931,"children":1932},{},[1933],{"type":35,"value":1934},"La qualité du travail est irrégulière",{"type":29,"tag":1084,"props":1936,"children":1937},{},[1938],{"type":35,"value":1939},"Il dit \"j'ai fait X\" mais ne peut pas expliquer pourquoi",{"type":29,"tag":37,"props":1941,"children":1942},{},[1943],{"type":29,"tag":65,"props":1944,"children":1945},{},[1946],{"type":35,"value":1947},"Signaux de sous-délégation (trop de contrôle) :",{"type":29,"tag":1080,"props":1949,"children":1950},{},[1951,1956,1961,1966],{"type":29,"tag":1084,"props":1952,"children":1953},{},[1954],{"type":35,"value":1955},"Le développeur \"fait valider\" des décisions triviales",{"type":29,"tag":1084,"props":1957,"children":1958},{},[1959],{"type":35,"value":1960},"Il n'apporte plus de propositions, il attend les instructions",{"type":29,"tag":1084,"props":1962,"children":1963},{},[1964],{"type":35,"value":1965},"Il exprime de la frustration sur son manque d'autonomie",{"type":29,"tag":1084,"props":1967,"children":1968},{},[1969],{"type":35,"value":1970},"Il perd en motivation visible sur plusieurs semaines",{"type":29,"tag":37,"props":1972,"children":1973},{},[1974,1979],{"type":29,"tag":65,"props":1975,"children":1976},{},[1977],{"type":35,"value":1978},"Le recalibrage :",{"type":35,"value":1980}," la délégation peut monter ou descendre selon l'évolution des compétences et de la confiance. Un développeur qui traverse une période difficile peut temporairement revenir à un niveau de délégation plus supporté, sans que ce soit perçu comme une rétrogradation, à condition d'expliquer pourquoi.",{"type":29,"tag":76,"props":1982,"children":1983},{},[],{"type":29,"tag":80,"props":1985,"children":1987},{"id":1986},"la-délégation-comme-outil-de-développement",[1988],{"type":35,"value":1989},"La délégation comme outil de développement",{"type":29,"tag":37,"props":1991,"children":1992},{},[1993],{"type":35,"value":1994},"La délégation progressive n'est pas seulement un outil de management : c'est un outil de développement. Vygotsky appelle ça la zone proximale de développement : déléguer légèrement au-delà de ce que le développeur sait faire aujourd'hui, avec un filet de sécurité, accélère son développement. Déléguer dans la zone de confort maintient le statu quo. Déléguer trop loin au-delà génère de l'anxiété et des erreurs.",{"type":29,"tag":37,"props":1996,"children":1997},{},[1998],{"type":35,"value":1999},"Dans un client dans l'édition logicielle (30 personnes), j'accompagnais un développeur intermédiaire qui se plaignait de manque d'autonomie. Son manager lui faisait valider toutes ses PRs, même les plus triviales. Après un audit de délégation et la mise en place de la matrice, le développeur a obtenu l'autonomie complète sur son périmètre (service de notifications) avec un seul filet de sécurité (escalader si impact sur d'autres services). En 3 mois, il avait redesigné l'architecture du service, documenté ses décisions, et formé un junior sur son périmètre. Ces trois choses étaient impossibles dans l'ancien mode de fonctionnement.",{"type":29,"tag":76,"props":2001,"children":2002},{},[],{"type":29,"tag":80,"props":2004,"children":2006},{"id":2005},"faq-sur-la-délégation-technique",[2007],{"type":35,"value":2008},"FAQ sur la délégation technique",{"type":29,"tag":381,"props":2010,"children":2011},{},[2012,2017],{"type":29,"tag":385,"props":2013,"children":2014},{},[2015],{"type":35,"value":2016},"Comment gérer la délégation quand un développeur senior refuse les responsabilités ?",{"type":29,"tag":37,"props":2018,"children":2019},{},[2020,2022,2028],{"type":35,"value":2021},"La résistance à la délégation est souvent une protection contre l'échec ou un manque de clarté sur les attentes. Je distingue les deux cas. Si c'est la peur de l'échec : je rends les filets de sécurité plus explicites et les conséquences de l'erreur moins sévères. Si c'est le manque de clarté : je redéfinis la mission avec des critères de succès très précis. Un senior qui refuse systématiquement les responsabilités sur un horizon de 6 mois a peut-être atteint son niveau de confort dans son rôle actuel : conversation honnête nécessaire lors de l'",{"type":29,"tag":48,"props":2023,"children":2025},{"href":2024},"/fr/management/entretien-annuel-developpeur-format",[2026],{"type":35,"value":2027},"entretien annuel",{"type":35,"value":2029}," sur les aspirations et les attentes mutuelles.",{"type":29,"tag":381,"props":2031,"children":2032},{},[2033,2038],{"type":29,"tag":385,"props":2034,"children":2035},{},[2036],{"type":35,"value":2037},"Comment documenter les niveaux de délégation pour éviter les ambiguïtés ?",{"type":29,"tag":37,"props":2039,"children":2040},{},[2041],{"type":35,"value":2042},"Un simple document partagé avec l'équipe qui liste les domaines de décision et le niveau de délégation pour chaque niveau de séniorité. Je le mets à jour lors des promotions ou changements de périmètre. L'important n'est pas la précision exhaustive : c'est que le développeur et moi ayons la même compréhension des zones d'autonomie. En cas d'ambiguïté, la règle par défaut est D3 (le développeur propose, je valide), ce qui laisse l'autonomie sur l'exécution et la validation sur les décisions.",{"type":29,"tag":381,"props":2044,"children":2045},{},[2046,2051],{"type":29,"tag":385,"props":2047,"children":2048},{},[2049],{"type":35,"value":2050},"Quelle est la différence entre délégation et abandon ?",{"type":29,"tag":37,"props":2052,"children":2053},{},[2054],{"type":35,"value":2055},"La délégation a trois éléments que l'abandon n'a pas : une mission claire (périmètre et critères de succès définis), un filet de sécurité (les conditions d'escalade sont définies en avance), et un débriefing (retour sur l'expérience). L'abandon, c'est \"débrouille-toi\" sans ces trois éléments. La délégation sans mission claire ressemble à de l'abandon, même si l'intention du manager est bonne.",{"type":29,"tag":381,"props":2057,"children":2058},{},[2059,2064],{"type":29,"tag":385,"props":2060,"children":2061},{},[2062],{"type":35,"value":2063},"Comment déléguer dans un contexte de forte dette technique où chaque décision a des conséquences importantes ?",{"type":29,"tag":37,"props":2065,"children":2066},{},[2067,2069,2075],{"type":35,"value":2068},"En rendant les filets de sécurité plus explicites et plus fréquents. Pas \"viens me voir si tu as un problème\", mais \"viens me voir après J+2 pour un point d'étape, et immédiatement si tu rencontres X ou Y.\" Dans un contexte de ",{"type":29,"tag":48,"props":2070,"children":2072},{"href":2071},"/fr/dette-technique/programme-refactoring-approuve-business",[2073],{"type":35,"value":2074},"forte dette technique",{"type":35,"value":2076},", la délégation est possible et nécessaire, mais avec des checkpoints plus fréquents pour détecter tôt les décisions qui pourraient avoir des effets de bord non anticipés.",{"type":29,"tag":381,"props":2078,"children":2079},{},[2080,2085],{"type":29,"tag":385,"props":2081,"children":2082},{},[2083],{"type":35,"value":2084},"Comment calibrer la délégation pour un nouveau membre de l'équipe, même senior ?",{"type":29,"tag":37,"props":2086,"children":2087},{},[2088],{"type":35,"value":2089},"Je commence à D2 pour les 30 premiers jours, quelle que soit la séniorité. Non pas parce que le développeur manque de compétence, mais parce qu'il manque de contexte sur le codebase, les décisions passées, et les normes de l'équipe. La montée en délégation est rapide (D2 → D4 en 4 à 6 semaines pour un senior compétent) mais elle doit partir de là. J'explique cette progression explicitement à l'onboarding pour éviter la frustration.",{"type":29,"tag":76,"props":2091,"children":2092},{},[],{"type":29,"tag":176,"props":2094,"children":2095},{"cta":1243,"href":1244,"title":454,"type":455},[2096],{"type":29,"tag":37,"props":2097,"children":2098},{},[2099],{"type":35,"value":2100},"L'Engineering Maturity Self-Assessment couvre le domaine Management Technique : évaluez votre niveau de maturité sur la délégation, le développement de l'autonomie, et les pratiques de feedback. Score et recommandations en 10 minutes.",{"title":8,"searchDepth":463,"depth":463,"links":2102},[2103,2104,2109,2110,2111,2112],{"id":1321,"depth":463,"text":1324},{"id":1380,"depth":463,"text":1383,"children":2105},[2106,2107,2108],{"id":1386,"depth":469,"text":1389},{"id":1536,"depth":469,"text":1539},{"id":1690,"depth":469,"text":1693},{"id":1835,"depth":463,"text":1838},{"id":1905,"depth":463,"text":1908},{"id":1986,"depth":463,"text":1989},{"id":2005,"depth":463,"text":2008},"content:fr:management:delegation-technique-confiance.md","fr/management/delegation-technique-confiance.md","fr/management/delegation-technique-confiance",{"_path":2117,"_dir":2118,"_draft":7,"_partial":7,"_locale":8,"title":2119,"description":2120,"id":2121,"date":2122,"listed":13,"nocomments":7,"hidden":7,"categories":2123,"tags":2124,"--cover":2129,"readingTime":2130,"body":2134,"_type":476,"_id":4102,"_source":478,"_file":4103,"_stem":4104,"_extension":481},"/fr/intelligence-artificielle/ia-code-review-retour-experience","intelligence-artificielle","IA en code review : retour d'expérience après 6 mois","Après 6 mois d'outils IA dans les code reviews : ce qu'ils trouvent bien, ce qu'ils ratent systématiquement, et comment les intégrer sans dégrader la culture de review.",37,"2026-03-20",[2118],[2125,2126,2127,2128],"Code Review","IA","Retour d'expérience","Qualité","covers/articles/ia-code-review-retour-experience.jpg",{"text":21,"minutes":2131,"time":2132,"words":2133},8.765,525900,1753,{"type":26,"children":2135,"toc":4093},[2136,2141,2146,2151,2159,2162,2168,2173,2198,2300,2310,2320,2330,2333,2339,2344,2354,2364,2374,2384,2394,2403,2406,2412,2417,2427,2437,2447,2450,2456,2464,2469,2477,2490,2577,2585,2590,2598,2603,2606,2612,2622,2632,2642,2652,2655,2661,2671,2681,2691,2701,2706,2709,2715,2735,2748,4037,4050,4063,4076,4079,4089],{"type":29,"tag":30,"props":2137,"children":2139},{"id":2138},"ia-en-code-review-retour-dexpérience-après-6-mois",[2140],{"type":35,"value":2119},{"type":29,"tag":37,"props":2142,"children":2143},{},[2144],{"type":35,"value":2145},"En janvier 2026, j'ai accompagné un client (15 développeurs) dans l'adoption de CodeRabbit. Le CTO avait une attente simple : réduire le temps de review sans dégrader la qualité. Six semaines plus tard, le temps de review humaine avait baissé de 35% (de 45 minutes à 30 minutes par PR en moyenne). Le taux de faux positifs de l'IA était à 28% initialement, réduit à 15% après ajustement de la configuration avec les conventions de l'équipe. Les reviewers disaient \"je me concentre sur ce qui compte\".",{"type":29,"tag":37,"props":2147,"children":2148},{},[2149],{"type":35,"value":2150},"Mais dans une autre équipe, chez un éditeur de logiciels de 18 développeurs, l'adoption du même type d'outil avait produit l'effet inverse : une \"alert fatigue\" qui avait dégradé la culture de review. Les développeurs ignoraient les commentaires IA en masse, y compris les commentaires importants.",{"type":29,"tag":37,"props":2152,"children":2153},{},[2154],{"type":29,"tag":65,"props":2155,"children":2156},{},[2157],{"type":35,"value":2158},"La différence entre ces deux résultats n'était pas l'outil. C'était la méthode d'intégration.",{"type":29,"tag":76,"props":2160,"children":2161},{},[],{"type":29,"tag":80,"props":2163,"children":2165},{"id":2164},"ce-que-lia-trouve-bien",[2166],{"type":35,"value":2167},"Ce que l'IA trouve bien",{"type":29,"tag":37,"props":2169,"children":2170},{},[2171],{"type":35,"value":2172},"L'IA en code review excelle sur les patterns connus et répétables.",{"type":29,"tag":37,"props":2174,"children":2175},{},[2176,2181,2183,2189,2191,2196],{"type":29,"tag":65,"props":2177,"children":2178},{},[2179],{"type":35,"value":2180},"Problèmes de sécurité évidents :",{"type":35,"value":2182}," injections SQL, secrets hardcodés, XSS potentiels, dépendances avec CVE connus, des ",{"type":29,"tag":48,"props":2184,"children":2186},{"href":2185},"/fr/intelligence-artificielle/llm-securite-code-vulnerabilites",[2187],{"type":35,"value":2188},"vulnérabilités typiques du code LLM-généré",{"type":35,"value":2190},". L'IA les détecte mieux que la review humaine moyenne, non pas parce qu'elle est plus intelligente, mais parce qu'elle ne fatigue pas et applique systématiquement les patterns connus. Une étude de ",{"type":29,"tag":65,"props":2192,"children":2193},{},[2194],{"type":35,"value":2195},"Stanford (2023)",{"type":35,"value":2197}," documentait que 40% du code IA-généré contenait des vulnérabilités dans des contextes de sécurité spécifiques : l'IA en code review détecte précisément ces patterns.",{"type":29,"tag":651,"props":2199,"children":2203},{"className":2200,"code":2201,"language":2202,"meta":8,"style":8},"language-python shiki shiki-themes catppuccin-frappe github-dark","# L'IA détecte ce pattern immédiatement\nquery = f\"SELECT * FROM users WHERE email = '{email}'\"  # SQL injection\n# Et suggère\nquery = \"SELECT * FROM users WHERE email = %s\"\n","python",[2204],{"type":29,"tag":565,"props":2205,"children":2206},{"__ignoreMap":8},[2207,2215,2266,2274],{"type":29,"tag":901,"props":2208,"children":2209},{"class":903,"line":904},[2210],{"type":29,"tag":901,"props":2211,"children":2212},{"style":908},[2213],{"type":35,"value":2214},"# L'IA détecte ce pattern immédiatement\n",{"type":29,"tag":901,"props":2216,"children":2217},{"class":903,"line":463},[2218,2223,2228,2234,2240,2246,2251,2256,2261],{"type":29,"tag":901,"props":2219,"children":2220},{"style":923},[2221],{"type":35,"value":2222},"query ",{"type":29,"tag":901,"props":2224,"children":2225},{"style":947},[2226],{"type":35,"value":2227},"=",{"type":29,"tag":901,"props":2229,"children":2231},{"style":2230},"--shiki-default:#A6D189;--shiki-default-font-style:italic;--shiki-dark:#F97583;--shiki-dark-font-style:inherit",[2232],{"type":35,"value":2233}," f",{"type":29,"tag":901,"props":2235,"children":2237},{"style":2236},"--shiki-default:#A6D189;--shiki-dark:#9ECBFF",[2238],{"type":35,"value":2239},"\"SELECT * FROM users WHERE email = '",{"type":29,"tag":901,"props":2241,"children":2243},{"style":2242},"--shiki-default:#F4B8E4;--shiki-dark:#79B8FF",[2244],{"type":35,"value":2245},"{",{"type":29,"tag":901,"props":2247,"children":2248},{"style":923},[2249],{"type":35,"value":2250},"email",{"type":29,"tag":901,"props":2252,"children":2253},{"style":2242},[2254],{"type":35,"value":2255},"}",{"type":29,"tag":901,"props":2257,"children":2258},{"style":2236},[2259],{"type":35,"value":2260},"'\"",{"type":29,"tag":901,"props":2262,"children":2263},{"style":908},[2264],{"type":35,"value":2265},"  # SQL injection\n",{"type":29,"tag":901,"props":2267,"children":2268},{"class":903,"line":469},[2269],{"type":29,"tag":901,"props":2270,"children":2271},{"style":908},[2272],{"type":35,"value":2273},"# Et suggère\n",{"type":29,"tag":901,"props":2275,"children":2276},{"class":903,"line":968},[2277,2281,2285,2290,2295],{"type":29,"tag":901,"props":2278,"children":2279},{"style":923},[2280],{"type":35,"value":2222},{"type":29,"tag":901,"props":2282,"children":2283},{"style":947},[2284],{"type":35,"value":2227},{"type":29,"tag":901,"props":2286,"children":2287},{"style":2236},[2288],{"type":35,"value":2289}," \"SELECT * FROM users WHERE email = ",{"type":29,"tag":901,"props":2291,"children":2292},{"style":2242},[2293],{"type":35,"value":2294},"%s",{"type":29,"tag":901,"props":2296,"children":2297},{"style":2236},[2298],{"type":35,"value":2299},"\"\n",{"type":29,"tag":37,"props":2301,"children":2302},{},[2303,2308],{"type":29,"tag":65,"props":2304,"children":2305},{},[2306],{"type":35,"value":2307},"Problèmes de style et de conventions :",{"type":35,"value":2309}," nommage incohérent, fonctions trop longues, complexité cyclomatique élevée, code dupliqué détectable par pattern matching. L'IA commente ces points avec une régularité que les reviewers humains n'ont pas, car ils s'habituent aux patterns de l'équipe et les ignorent progressivement.",{"type":29,"tag":37,"props":2311,"children":2312},{},[2313,2318],{"type":29,"tag":65,"props":2314,"children":2315},{},[2316],{"type":35,"value":2317},"Documentation manquante :",{"type":35,"value":2319}," fonctions publiques sans docstring, paramètres non typés, valeurs de retour non documentées. L'IA les signale systématiquement et peut générer la documentation manquante en temps réel.",{"type":29,"tag":37,"props":2321,"children":2322},{},[2323,2328],{"type":29,"tag":65,"props":2324,"children":2325},{},[2326],{"type":35,"value":2327},"Tests manquants :",{"type":35,"value":2329}," branches de code non couvertes par les tests présents dans la PR. L'IA peut identifier \"ce bloc else n'est pas testé\" avec une précision correcte.",{"type":29,"tag":76,"props":2331,"children":2332},{},[],{"type":29,"tag":80,"props":2334,"children":2336},{"id":2335},"ce-que-lia-rate-systématiquement",[2337],{"type":35,"value":2338},"Ce que l'IA rate systématiquement",{"type":29,"tag":37,"props":2340,"children":2341},{},[2342],{"type":35,"value":2343},"Après 6 mois d'observation, j'ai identifié 5 angles morts récurrents.",{"type":29,"tag":37,"props":2345,"children":2346},{},[2347,2352],{"type":29,"tag":65,"props":2348,"children":2349},{},[2350],{"type":35,"value":2351},"La cohérence avec le reste du codebase :",{"type":35,"value":2353}," l'IA revoit la PR en isolation. Si la base de code utilise un pattern de gestion d'erreur spécifique, l'IA peut suggérer un pattern différent, techniquement correct mais incohérent avec le reste. Après 6 mois, c'est le problème numéro un des équipes : l'IA crée du bruit avec des suggestions valides techniquement mais inadaptées au contexte.",{"type":29,"tag":37,"props":2355,"children":2356},{},[2357,2362],{"type":29,"tag":65,"props":2358,"children":2359},{},[2360],{"type":35,"value":2361},"La logique métier incorrecte :",{"type":35,"value":2363}," une fonction qui calcule incorrectement une remise selon des règles business spécifiques : l'IA ne voit pas le problème si le code est techniquement correct. Ce bug ne sera trouvé que par un reviewer humain qui connaît les règles métier.",{"type":29,"tag":37,"props":2365,"children":2366},{},[2367,2372],{"type":29,"tag":65,"props":2368,"children":2369},{},[2370],{"type":35,"value":2371},"L'impact architectural :",{"type":35,"value":2373}," un changement qui passe tous les tests et respecte tous les patterns de style peut introduire un couplage architectural problématique à long terme. L'IA ne voit pas les implications systémiques d'un changement local.",{"type":29,"tag":37,"props":2375,"children":2376},{},[2377,2382],{"type":29,"tag":65,"props":2378,"children":2379},{},[2380],{"type":35,"value":2381},"La duplication de logique métier cross-services :",{"type":35,"value":2383}," deux services qui implémentent la même règle légèrement différemment. L'IA revoit un service à la fois, elle ne peut pas détecter la duplication sans contexte étendu.",{"type":29,"tag":37,"props":2385,"children":2386},{},[2387,2392],{"type":29,"tag":65,"props":2388,"children":2389},{},[2390],{"type":35,"value":2391},"L'intention du changement :",{"type":35,"value":2393}," une PR qui modifie une constante de configuration. L'IA commente sur le style. Elle ne peut pas dire \"cette constante avait été fixée à cette valeur pour contourner un bug du service X, la modifier va créer des problèmes en production.\"",{"type":29,"tag":176,"props":2395,"children":2397},{"cta":178,"href":179,"title":2396,"type":181},"Vous adoptez des outils IA dans votre workflow de review et vous voulez éviter les pièges ?",[2398],{"type":29,"tag":37,"props":2399,"children":2400},{},[2401],{"type":35,"value":2402},"Vous avez adopté ou envisagez d'adopter un outil IA en code review, mais vous ne savez pas comment l'intégrer sans dégrader la culture d'équipe. En 30 minutes, on définit les règles d'utilisation, les limites, et le processus adapté à votre contexte.",{"type":29,"tag":76,"props":2404,"children":2405},{},[],{"type":29,"tag":80,"props":2407,"children":2409},{"id":2408},"limpact-sur-la-culture-de-review",[2410],{"type":35,"value":2411},"L'impact sur la culture de review",{"type":29,"tag":37,"props":2413,"children":2414},{},[2415],{"type":35,"value":2416},"Ce que les équipes rapportent après 6 mois :",{"type":29,"tag":37,"props":2418,"children":2419},{},[2420,2425],{"type":29,"tag":65,"props":2421,"children":2422},{},[2423],{"type":35,"value":2424},"Ce qui s'améliore :",{"type":35,"value":2426}," les reviews humaines se concentrent plus sur le fond (logique métier, architecture, cohérence) et moins sur la forme (style, conventions). L'IA filtre le bruit. Les développeurs juniors reçoivent plus de feedback structuré et rapide, l'IA joue un rôle de \"premier reviewer\" qui leur permet d'améliorer leur code avant la review humaine.",{"type":29,"tag":37,"props":2428,"children":2429},{},[2430,2435],{"type":29,"tag":65,"props":2431,"children":2432},{},[2433],{"type":35,"value":2434},"Ce qui se dégrade si mal géré :",{"type":35,"value":2436}," dans plusieurs équipes, le volume de commentaires IA a créé une \"alert fatigue\". Les développeurs commencent à ignorer les commentaires IA en masse, y compris les commentaires importants. Une équipe a constaté une augmentation de 30% du nombre de commentaires de PR, avec une diminution de la qualité de l'engagement sur chacun.",{"type":29,"tag":37,"props":2438,"children":2439},{},[2440,2445],{"type":29,"tag":65,"props":2441,"children":2442},{},[2443],{"type":35,"value":2444},"Le risque principal :",{"type":35,"value":2446}," la délégation de responsabilité. \"L'IA a approuvé, donc ça doit être bon.\" Ce pattern crée une fausse sécurité dangereuse. Les reviewers humains réduisent l'intensité de leur review quand l'IA a déjà commenté. J'ai vu ce pattern se répéter dans chaque équipe qui n'avait pas défini explicitement la séparation des responsabilités.",{"type":29,"tag":76,"props":2448,"children":2449},{},[],{"type":29,"tag":80,"props":2451,"children":2453},{"id":2452},"les-règles-dintégration-qui-fonctionnent",[2454],{"type":35,"value":2455},"Les règles d'intégration qui fonctionnent",{"type":29,"tag":37,"props":2457,"children":2458},{},[2459],{"type":29,"tag":65,"props":2460,"children":2461},{},[2462],{"type":35,"value":2463},"Règle 1 : Séparer les commentaires IA des commentaires humains",{"type":29,"tag":37,"props":2465,"children":2466},{},[2467],{"type":35,"value":2468},"Les commentaires IA doivent être visuellement distincts. Le reviewer humain sait que l'IA a déjà reviewé les aspects de style/sécurité et peut se concentrer sur le fond. CodeRabbit et les intégrations GitHub Copilot le font nativement. Si vous utilisez une intégration personnalisée, utilisez un bot account dédié.",{"type":29,"tag":37,"props":2470,"children":2471},{},[2472],{"type":29,"tag":65,"props":2473,"children":2474},{},[2475],{"type":35,"value":2476},"Règle 2 : Définir ce que l'IA revoit, définir ce que l'humain revoit",{"type":29,"tag":37,"props":2478,"children":2479},{},[2480,2482,2488],{"type":35,"value":2481},"Complétez ce tableau avec la ",{"type":29,"tag":48,"props":2483,"children":2485},{"href":2484},"/fr/intelligence-artificielle/tester-code-genere-ia-checklist",[2486],{"type":35,"value":2487},"checklist de validation du code IA",{"type":35,"value":2489}," pour les PRs à fort contenu généré.",{"type":29,"tag":714,"props":2491,"children":2492},{},[2493,2509],{"type":29,"tag":718,"props":2494,"children":2495},{},[2496],{"type":29,"tag":722,"props":2497,"children":2498},{},[2499,2504],{"type":29,"tag":726,"props":2500,"children":2501},{},[2502],{"type":35,"value":2503},"L'IA revoit",{"type":29,"tag":726,"props":2505,"children":2506},{},[2507],{"type":35,"value":2508},"L'humain revoit",{"type":29,"tag":742,"props":2510,"children":2511},{},[2512,2525,2538,2551,2564],{"type":29,"tag":722,"props":2513,"children":2514},{},[2515,2520],{"type":29,"tag":749,"props":2516,"children":2517},{},[2518],{"type":35,"value":2519},"Sécurité (injections, secrets)",{"type":29,"tag":749,"props":2521,"children":2522},{},[2523],{"type":35,"value":2524},"Logique métier",{"type":29,"tag":722,"props":2526,"children":2527},{},[2528,2533],{"type":29,"tag":749,"props":2529,"children":2530},{},[2531],{"type":35,"value":2532},"Style et conventions",{"type":29,"tag":749,"props":2534,"children":2535},{},[2536],{"type":35,"value":2537},"Impact architectural",{"type":29,"tag":722,"props":2539,"children":2540},{},[2541,2546],{"type":29,"tag":749,"props":2542,"children":2543},{},[2544],{"type":35,"value":2545},"Tests manquants",{"type":29,"tag":749,"props":2547,"children":2548},{},[2549],{"type":35,"value":2550},"Cohérence avec le codebase",{"type":29,"tag":722,"props":2552,"children":2553},{},[2554,2559],{"type":29,"tag":749,"props":2555,"children":2556},{},[2557],{"type":35,"value":2558},"Complexité excessive",{"type":29,"tag":749,"props":2560,"children":2561},{},[2562],{"type":35,"value":2563},"Intention du changement",{"type":29,"tag":722,"props":2565,"children":2566},{},[2567,2572],{"type":29,"tag":749,"props":2568,"children":2569},{},[2570],{"type":35,"value":2571},"Documentation manquante",{"type":29,"tag":749,"props":2573,"children":2574},{},[2575],{"type":35,"value":2576},"Trade-offs de design",{"type":29,"tag":37,"props":2578,"children":2579},{},[2580],{"type":29,"tag":65,"props":2581,"children":2582},{},[2583],{"type":35,"value":2584},"Règle 3 : Ne pas rendre la review IA bloquante par défaut",{"type":29,"tag":37,"props":2586,"children":2587},{},[2588],{"type":35,"value":2589},"La review IA ne doit pas bloquer le merge de façon automatique sur les commentaires non-critiques. Seuls les commentaires de sécurité (injection, secrets, vulnérabilités connues) méritent un blocage automatique. Les autres sont des suggestions que l'auteur de la PR peut accepter ou rejeter explicitement.",{"type":29,"tag":37,"props":2591,"children":2592},{},[2593],{"type":29,"tag":65,"props":2594,"children":2595},{},[2596],{"type":35,"value":2597},"Règle 4 : Conserver la review humaine comme étape obligatoire",{"type":29,"tag":37,"props":2599,"children":2600},{},[2601],{"type":35,"value":2602},"Même avec un outil IA excellent, la review humaine reste obligatoire. La tentation de supprimer la review humaine pour les \"petites PR\" est dangereuse, car c'est souvent sur une \"petite PR\" que le bug critique est introduit.",{"type":29,"tag":76,"props":2604,"children":2605},{},[],{"type":29,"tag":80,"props":2607,"children":2609},{"id":2608},"les-métriques-de-suivi-à-6-mois",[2610],{"type":35,"value":2611},"Les métriques de suivi à 6 mois",{"type":29,"tag":37,"props":2613,"children":2614},{},[2615,2620],{"type":29,"tag":65,"props":2616,"children":2617},{},[2618],{"type":35,"value":2619},"Time to first review :",{"type":35,"value":2621}," le temps entre la création d'une PR et le premier commentaire. Avec un outil IA, ce metric descend à moins de 5 minutes (le bot review instantanément). C'est un gain réel pour les développeurs qui attendent un feedback.",{"type":29,"tag":37,"props":2623,"children":2624},{},[2625,2630],{"type":29,"tag":65,"props":2626,"children":2627},{},[2628],{"type":35,"value":2629},"Human review time :",{"type":35,"value":2631}," le temps que les développeurs humains passent sur les reviews. L'objectif est que ce temps reste stable ou diminue légèrement (l'IA a filtré le bruit) tout que la qualité augmente.",{"type":29,"tag":37,"props":2633,"children":2634},{},[2635,2640],{"type":29,"tag":65,"props":2636,"children":2637},{},[2638],{"type":35,"value":2639},"False positive rate de l'IA :",{"type":35,"value":2641}," le pourcentage de commentaires IA que l'auteur de la PR rejette comme non-pertinents. Un taux supérieur à 30% signifie que l'IA génère trop de bruit : ajustez la configuration ou le prompt système.",{"type":29,"tag":37,"props":2643,"children":2644},{},[2645,2650],{"type":29,"tag":65,"props":2646,"children":2647},{},[2648],{"type":35,"value":2649},"Bug escape rate :",{"type":35,"value":2651}," le nombre de bugs trouvés en production par rapport aux bugs trouvés en review. Si ce ratio s'améliore avec l'IA, l'outil fonctionne. S'il se dégrade, l'IA crée une fausse sécurité.",{"type":29,"tag":76,"props":2653,"children":2654},{},[],{"type":29,"tag":80,"props":2656,"children":2658},{"id":2657},"les-outils-et-leur-positionnement",[2659],{"type":35,"value":2660},"Les outils et leur positionnement",{"type":29,"tag":37,"props":2662,"children":2663},{},[2664,2669],{"type":29,"tag":65,"props":2665,"children":2666},{},[2667],{"type":35,"value":2668},"GitHub Copilot Code Review :",{"type":35,"value":2670}," intégration native dans GitHub, activée au niveau de la PR. Bon pour le style et les patterns de sécurité courants. Limite : connaissance du codebase limitée au diff de la PR.",{"type":29,"tag":37,"props":2672,"children":2673},{},[2674,2679],{"type":29,"tag":65,"props":2675,"children":2676},{},[2677],{"type":35,"value":2678},"CodeRabbit :",{"type":35,"value":2680}," outil spécialisé review avec contexte étendu du codebase. Meilleur pour la cohérence avec le codebase que Copilot. Configuration par règles yaml.",{"type":29,"tag":37,"props":2682,"children":2683},{},[2684,2689],{"type":29,"tag":65,"props":2685,"children":2686},{},[2687],{"type":35,"value":2688},"Claude / GPT-4 via API :",{"type":35,"value":2690}," intégration personnalisée avec contexte métier. Le plus flexible : vous pouvez injecter les conventions de l'équipe, les règles métier critiques, et l'architecture dans le prompt système. Le plus complexe à configurer.",{"type":29,"tag":37,"props":2692,"children":2693},{},[2694,2699],{"type":29,"tag":65,"props":2695,"children":2696},{},[2697],{"type":35,"value":2698},"Cursor :",{"type":35,"value":2700}," IDE avec review intégrée en cours d'écriture, pas seulement sur la PR. Utile pour les développeurs qui veulent le feedback avant même de créer la PR.",{"type":29,"tag":37,"props":2702,"children":2703},{},[2704],{"type":35,"value":2705},"L'IA en code review est un amplificateur, pas un remplacement. Elle amplifie la capacité de détection sur les patterns connus et libère le temps humain pour ce que l'IA ne peut pas faire. Les équipes qui sortiront gagnantes de cette transition ne seront pas celles qui délèguent le plus à l'IA. Ce seront celles qui comprennent précisément ce qu'elles lui délèguent.",{"type":29,"tag":76,"props":2707,"children":2708},{},[],{"type":29,"tag":80,"props":2710,"children":2712},{"id":2711},"faq-sur-lia-en-code-review",[2713],{"type":35,"value":2714},"FAQ sur l'IA en code review",{"type":29,"tag":381,"props":2716,"children":2717},{},[2718,2723],{"type":29,"tag":385,"props":2719,"children":2720},{},[2721],{"type":35,"value":2722},"1. Quelle est la différence entre un linter et un outil de review IA ?",{"type":29,"tag":37,"props":2724,"children":2725},{},[2726,2728,2733],{"type":35,"value":2727},"Un ",{"type":29,"tag":48,"props":2729,"children":2730},{"href":337},[2731],{"type":35,"value":2732},"linter",{"type":35,"value":2734}," applique des règles déterministes prédéfinies : syntaxe, style, patterns interdits. Il est rapide, sans faux positifs sur ce qu'il est configuré à détecter. Un outil IA applique un raisonnement contextuel sur le code : il peut détecter des problèmes que le linter ne peut pas formaliser en règles (ex : \"cette fonction fait trop de choses\"). La complémentarité est optimale : linter pour les règles déterministes, IA pour les jugements contextuels.",{"type":29,"tag":381,"props":2736,"children":2737},{},[2738,2743],{"type":29,"tag":385,"props":2739,"children":2740},{},[2741],{"type":35,"value":2742},"2. L'IA peut-elle reviewer du code dans des langages peu courants ou des DSLs internes ?",{"type":29,"tag":37,"props":2744,"children":2745},{},[2746],{"type":35,"value":2747},"Les LLMs sont entraînés principalement sur les langages populaires (Python, JavaScript, Java, Go, TypeScript). Pour les langages peu courants ou les DSLs internes, la qualité du review IA est dégradée. Dans ce cas, utilisez l'IA uniquement pour les aspects génériques (sécurité, documentation) et laissez les aspects spécifiques au langage aux reviewers humains.",{"type":29,"tag":381,"props":2749,"children":2750},{},[2751,2756],{"type":29,"tag":385,"props":2752,"children":2753},{},[2754],{"type":35,"value":2755},"3. Comment gérer le coût des reviews IA sur un grand nombre de PRs ?",{"type":29,"tag":37,"props":2757,"children":2758},{},[2759,2761,3501,3503,4035],{"type":35,"value":2760},"Les coûts varient selon l'outil. GitHub Copilot Code Review est inclus dans l'abonnement Copilot (19",{"type":29,"tag":901,"props":2762,"children":2765},{"className":2763},[2764],"katex",[2766,3100],{"type":29,"tag":901,"props":2767,"children":2770},{"className":2768},[2769],"katex-mathml",[2771],{"type":29,"tag":2772,"props":2773,"children":2775},"math",{"xmlns":2774},"http://www.w3.org/1998/Math/MathML",[2776],{"type":29,"tag":2777,"props":2778,"children":2779},"semantics",{},[2780,3093],{"type":29,"tag":2781,"props":2782,"children":2783},"mrow",{},[2784,2791,2796,2801,2806,2811,2815,2820,2836,2841,2845,2850,2854,2858,2862,2866,2871,2876,2882,2886,2891,2895,2899,2903,2908,2912,2917,2921,2925,2930,2934,2938,2943,2947,2951,2955,2959,2964,2968,2972,2976,2980,2984,2988,2992,2996,3000,3004,3008,3019,3023,3027,3031,3035,3039,3043,3047,3051,3055,3059,3064,3068,3072,3076,3081,3087],{"type":29,"tag":2785,"props":2786,"children":2788},"mi",{"mathvariant":2787},"normal",[2789],{"type":35,"value":2790},"/",{"type":29,"tag":2785,"props":2792,"children":2793},{},[2794],{"type":35,"value":2795},"m",{"type":29,"tag":2785,"props":2797,"children":2798},{},[2799],{"type":35,"value":2800},"o",{"type":29,"tag":2785,"props":2802,"children":2803},{},[2804],{"type":35,"value":2805},"i",{"type":29,"tag":2785,"props":2807,"children":2808},{},[2809],{"type":35,"value":2810},"s",{"type":29,"tag":2785,"props":2812,"children":2813},{"mathvariant":2787},[2814],{"type":35,"value":2790},{"type":29,"tag":2785,"props":2816,"children":2817},{},[2818],{"type":35,"value":2819},"d",{"type":29,"tag":2821,"props":2822,"children":2824},"mover",{"accent":2823},"true",[2825,2830],{"type":29,"tag":2785,"props":2826,"children":2827},{},[2828],{"type":35,"value":2829},"e",{"type":29,"tag":2831,"props":2832,"children":2833},"mo",{},[2834],{"type":35,"value":2835},"ˊ",{"type":29,"tag":2785,"props":2837,"children":2838},{},[2839],{"type":35,"value":2840},"v",{"type":29,"tag":2785,"props":2842,"children":2843},{},[2844],{"type":35,"value":2829},{"type":29,"tag":2785,"props":2846,"children":2847},{},[2848],{"type":35,"value":2849},"l",{"type":29,"tag":2785,"props":2851,"children":2852},{},[2853],{"type":35,"value":2800},{"type":29,"tag":2785,"props":2855,"children":2856},{},[2857],{"type":35,"value":37},{"type":29,"tag":2785,"props":2859,"children":2860},{},[2861],{"type":35,"value":37},{"type":29,"tag":2785,"props":2863,"children":2864},{},[2865],{"type":35,"value":2829},{"type":29,"tag":2785,"props":2867,"children":2868},{},[2869],{"type":35,"value":2870},"u",{"type":29,"tag":2785,"props":2872,"children":2873},{},[2874],{"type":35,"value":2875},"r",{"type":29,"tag":2831,"props":2877,"children":2879},{"stretchy":2878},"false",[2880],{"type":35,"value":2881},")",{"type":29,"tag":2785,"props":2883,"children":2884},{"mathvariant":2787},[2885],{"type":35,"value":342},{"type":29,"tag":2785,"props":2887,"children":2888},{},[2889],{"type":35,"value":2890},"C",{"type":29,"tag":2785,"props":2892,"children":2893},{},[2894],{"type":35,"value":2800},{"type":29,"tag":2785,"props":2896,"children":2897},{},[2898],{"type":35,"value":2819},{"type":29,"tag":2785,"props":2900,"children":2901},{},[2902],{"type":35,"value":2829},{"type":29,"tag":2785,"props":2904,"children":2905},{},[2906],{"type":35,"value":2907},"R",{"type":29,"tag":2785,"props":2909,"children":2910},{},[2911],{"type":35,"value":48},{"type":29,"tag":2785,"props":2913,"children":2914},{},[2915],{"type":35,"value":2916},"b",{"type":29,"tag":2785,"props":2918,"children":2919},{},[2920],{"type":35,"value":2916},{"type":29,"tag":2785,"props":2922,"children":2923},{},[2924],{"type":35,"value":2805},{"type":29,"tag":2785,"props":2926,"children":2927},{},[2928],{"type":35,"value":2929},"t",{"type":29,"tag":2785,"props":2931,"children":2932},{},[2933],{"type":35,"value":48},{"type":29,"tag":2785,"props":2935,"children":2936},{},[2937],{"type":35,"value":2870},{"type":29,"tag":2785,"props":2939,"children":2940},{},[2941],{"type":35,"value":2942},"n",{"type":29,"tag":2785,"props":2944,"children":2945},{},[2946],{"type":35,"value":2929},{"type":29,"tag":2785,"props":2948,"children":2949},{},[2950],{"type":35,"value":2805},{"type":29,"tag":2785,"props":2952,"children":2953},{},[2954],{"type":35,"value":2829},{"type":29,"tag":2785,"props":2956,"children":2957},{},[2958],{"type":35,"value":2875},{"type":29,"tag":2785,"props":2960,"children":2961},{},[2962],{"type":35,"value":2963},"g",{"type":29,"tag":2785,"props":2965,"children":2966},{},[2967],{"type":35,"value":2875},{"type":29,"tag":2785,"props":2969,"children":2970},{},[2971],{"type":35,"value":48},{"type":29,"tag":2785,"props":2973,"children":2974},{},[2975],{"type":35,"value":2929},{"type":29,"tag":2785,"props":2977,"children":2978},{},[2979],{"type":35,"value":2870},{"type":29,"tag":2785,"props":2981,"children":2982},{},[2983],{"type":35,"value":2805},{"type":29,"tag":2785,"props":2985,"children":2986},{},[2987],{"type":35,"value":2929},{"type":29,"tag":2785,"props":2989,"children":2990},{},[2991],{"type":35,"value":2849},{"type":29,"tag":2785,"props":2993,"children":2994},{},[2995],{"type":35,"value":2805},{"type":29,"tag":2785,"props":2997,"children":2998},{},[2999],{"type":35,"value":2795},{"type":29,"tag":2785,"props":3001,"children":3002},{},[3003],{"type":35,"value":2805},{"type":29,"tag":2785,"props":3005,"children":3006},{},[3007],{"type":35,"value":2929},{"type":29,"tag":2821,"props":3009,"children":3010},{"accent":2823},[3011,3015],{"type":29,"tag":2785,"props":3012,"children":3013},{},[3014],{"type":35,"value":2829},{"type":29,"tag":2831,"props":3016,"children":3017},{},[3018],{"type":35,"value":2835},{"type":29,"tag":2785,"props":3020,"children":3021},{},[3022],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3024,"children":3025},{},[3026],{"type":35,"value":2929},{"type":29,"tag":2785,"props":3028,"children":3029},{},[3030],{"type":35,"value":2870},{"type":29,"tag":2785,"props":3032,"children":3033},{},[3034],{"type":35,"value":2942},{"type":29,"tag":2785,"props":3036,"children":3037},{},[3038],{"type":35,"value":2929},{"type":29,"tag":2785,"props":3040,"children":3041},{},[3042],{"type":35,"value":2805},{"type":29,"tag":2785,"props":3044,"children":3045},{},[3046],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3048,"children":3049},{},[3050],{"type":35,"value":2875},{"type":29,"tag":2785,"props":3052,"children":3053},{},[3054],{"type":35,"value":37},{"type":29,"tag":2785,"props":3056,"children":3057},{},[3058],{"type":35,"value":48},{"type":29,"tag":2785,"props":3060,"children":3061},{},[3062],{"type":35,"value":3063},"y",{"type":29,"tag":2785,"props":3065,"children":3066},{},[3067],{"type":35,"value":48},{"type":29,"tag":2785,"props":3069,"children":3070},{},[3071],{"type":35,"value":2942},{"type":29,"tag":2785,"props":3073,"children":3074},{},[3075],{"type":35,"value":2929},{"type":29,"tag":2831,"props":3077,"children":3078},{"stretchy":2878},[3079],{"type":35,"value":3080},"(",{"type":29,"tag":3082,"props":3083,"children":3084},"mtext",{},[3085],{"type":35,"value":3086}," ",{"type":29,"tag":3088,"props":3089,"children":3090},"mn",{},[3091],{"type":35,"value":3092},"19",{"type":29,"tag":3094,"props":3095,"children":3097},"annotation",{"encoding":3096},"application/x-tex",[3098],{"type":35,"value":3099},"/mois/développeur). CodeRabbit a un tier gratuit limité et un tier payant (~19",{"type":29,"tag":901,"props":3101,"children":3104},{"className":3102,"ariaHidden":2823},[3103],"katex-html",[3105],{"type":29,"tag":901,"props":3106,"children":3109},{"className":3107},[3108],"base",[3110,3116,3122,3128,3133,3138,3143,3148,3153,3207,3213,3218,3224,3229,3235,3240,3245,3251,3257,3262,3268,3273,3278,3283,3289,3295,3300,3305,3310,3315,3320,3325,3331,3336,3341,3346,3351,3356,3361,3367,3373,3378,3422,3427,3432,3437,3442,3447,3452,3457,3462,3467,3472,3478,3483,3489,3496],{"type":29,"tag":901,"props":3111,"children":3115},{"className":3112,"style":3114},[3113],"strut","height:1em;vertical-align:-0.25em;",[],{"type":29,"tag":901,"props":3117,"children":3120},{"className":3118},[3119],"mord",[3121],{"type":35,"value":2790},{"type":29,"tag":901,"props":3123,"children":3126},{"className":3124},[3119,3125],"mathnormal",[3127],{"type":35,"value":2795},{"type":29,"tag":901,"props":3129,"children":3131},{"className":3130},[3119,3125],[3132],{"type":35,"value":2800},{"type":29,"tag":901,"props":3134,"children":3136},{"className":3135},[3119,3125],[3137],{"type":35,"value":2805},{"type":29,"tag":901,"props":3139,"children":3141},{"className":3140},[3119,3125],[3142],{"type":35,"value":2810},{"type":29,"tag":901,"props":3144,"children":3146},{"className":3145},[3119],[3147],{"type":35,"value":2790},{"type":29,"tag":901,"props":3149,"children":3151},{"className":3150},[3119,3125],[3152],{"type":35,"value":2819},{"type":29,"tag":901,"props":3154,"children":3157},{"className":3155},[3119,3156],"accent",[3158],{"type":29,"tag":901,"props":3159,"children":3162},{"className":3160},[3161],"vlist-t",[3163],{"type":29,"tag":901,"props":3164,"children":3167},{"className":3165},[3166],"vlist-r",[3168],{"type":29,"tag":901,"props":3169,"children":3173},{"className":3170,"style":3172},[3171],"vlist","height:0.6944em;",[3174,3189],{"type":29,"tag":901,"props":3175,"children":3177},{"style":3176},"top:-3em;",[3178,3184],{"type":29,"tag":901,"props":3179,"children":3183},{"className":3180,"style":3182},[3181],"pstrut","height:3em;",[],{"type":29,"tag":901,"props":3185,"children":3187},{"className":3186},[3119,3125],[3188],{"type":35,"value":2829},{"type":29,"tag":901,"props":3190,"children":3191},{"style":3176},[3192,3196],{"type":29,"tag":901,"props":3193,"children":3195},{"className":3194,"style":3182},[3181],[],{"type":29,"tag":901,"props":3197,"children":3201},{"className":3198,"style":3200},[3199],"accent-body","left:-0.1944em;",[3202],{"type":29,"tag":901,"props":3203,"children":3205},{"className":3204},[3119],[3206],{"type":35,"value":2835},{"type":29,"tag":901,"props":3208,"children":3211},{"className":3209,"style":3210},[3119,3125],"margin-right:0.03588em;",[3212],{"type":35,"value":2840},{"type":29,"tag":901,"props":3214,"children":3216},{"className":3215},[3119,3125],[3217],{"type":35,"value":2829},{"type":29,"tag":901,"props":3219,"children":3222},{"className":3220,"style":3221},[3119,3125],"margin-right:0.01968em;",[3223],{"type":35,"value":2849},{"type":29,"tag":901,"props":3225,"children":3227},{"className":3226},[3119,3125],[3228],{"type":35,"value":2800},{"type":29,"tag":901,"props":3230,"children":3232},{"className":3231},[3119,3125],[3233],{"type":35,"value":3234},"pp",{"type":29,"tag":901,"props":3236,"children":3238},{"className":3237},[3119,3125],[3239],{"type":35,"value":2829},{"type":29,"tag":901,"props":3241,"children":3243},{"className":3242},[3119,3125],[3244],{"type":35,"value":2870},{"type":29,"tag":901,"props":3246,"children":3249},{"className":3247,"style":3248},[3119,3125],"margin-right:0.02778em;",[3250],{"type":35,"value":2875},{"type":29,"tag":901,"props":3252,"children":3255},{"className":3253},[3254],"mclose",[3256],{"type":35,"value":2881},{"type":29,"tag":901,"props":3258,"children":3260},{"className":3259},[3119],[3261],{"type":35,"value":342},{"type":29,"tag":901,"props":3263,"children":3266},{"className":3264,"style":3265},[3119,3125],"margin-right:0.07153em;",[3267],{"type":35,"value":2890},{"type":29,"tag":901,"props":3269,"children":3271},{"className":3270},[3119,3125],[3272],{"type":35,"value":2800},{"type":29,"tag":901,"props":3274,"children":3276},{"className":3275},[3119,3125],[3277],{"type":35,"value":2819},{"type":29,"tag":901,"props":3279,"children":3281},{"className":3280},[3119,3125],[3282],{"type":35,"value":2829},{"type":29,"tag":901,"props":3284,"children":3287},{"className":3285,"style":3286},[3119,3125],"margin-right:0.00773em;",[3288],{"type":35,"value":2907},{"type":29,"tag":901,"props":3290,"children":3292},{"className":3291},[3119,3125],[3293],{"type":35,"value":3294},"abbi",{"type":29,"tag":901,"props":3296,"children":3298},{"className":3297},[3119,3125],[3299],{"type":35,"value":2929},{"type":29,"tag":901,"props":3301,"children":3303},{"className":3302},[3119,3125],[3304],{"type":35,"value":48},{"type":29,"tag":901,"props":3306,"children":3308},{"className":3307},[3119,3125],[3309],{"type":35,"value":2870},{"type":29,"tag":901,"props":3311,"children":3313},{"className":3312},[3119,3125],[3314],{"type":35,"value":2942},{"type":29,"tag":901,"props":3316,"children":3318},{"className":3317},[3119,3125],[3319],{"type":35,"value":2929},{"type":29,"tag":901,"props":3321,"children":3323},{"className":3322},[3119,3125],[3324],{"type":35,"value":2805},{"type":29,"tag":901,"props":3326,"children":3328},{"className":3327,"style":3248},[3119,3125],[3329],{"type":35,"value":3330},"er",{"type":29,"tag":901,"props":3332,"children":3334},{"className":3333,"style":3210},[3119,3125],[3335],{"type":35,"value":2963},{"type":29,"tag":901,"props":3337,"children":3339},{"className":3338,"style":3248},[3119,3125],[3340],{"type":35,"value":2875},{"type":29,"tag":901,"props":3342,"children":3344},{"className":3343},[3119,3125],[3345],{"type":35,"value":48},{"type":29,"tag":901,"props":3347,"children":3349},{"className":3348},[3119,3125],[3350],{"type":35,"value":2929},{"type":29,"tag":901,"props":3352,"children":3354},{"className":3353},[3119,3125],[3355],{"type":35,"value":2870},{"type":29,"tag":901,"props":3357,"children":3359},{"className":3358},[3119,3125],[3360],{"type":35,"value":2805},{"type":29,"tag":901,"props":3362,"children":3364},{"className":3363,"style":3221},[3119,3125],[3365],{"type":35,"value":3366},"tl",{"type":29,"tag":901,"props":3368,"children":3370},{"className":3369},[3119,3125],[3371],{"type":35,"value":3372},"imi",{"type":29,"tag":901,"props":3374,"children":3376},{"className":3375},[3119,3125],[3377],{"type":35,"value":2929},{"type":29,"tag":901,"props":3379,"children":3381},{"className":3380},[3119,3156],[3382],{"type":29,"tag":901,"props":3383,"children":3385},{"className":3384},[3161],[3386],{"type":29,"tag":901,"props":3387,"children":3389},{"className":3388},[3166],[3390],{"type":29,"tag":901,"props":3391,"children":3393},{"className":3392,"style":3172},[3171],[3394,3406],{"type":29,"tag":901,"props":3395,"children":3396},{"style":3176},[3397,3401],{"type":29,"tag":901,"props":3398,"children":3400},{"className":3399,"style":3182},[3181],[],{"type":29,"tag":901,"props":3402,"children":3404},{"className":3403},[3119,3125],[3405],{"type":35,"value":2829},{"type":29,"tag":901,"props":3407,"children":3408},{"style":3176},[3409,3413],{"type":29,"tag":901,"props":3410,"children":3412},{"className":3411,"style":3182},[3181],[],{"type":29,"tag":901,"props":3414,"children":3416},{"className":3415,"style":3200},[3199],[3417],{"type":29,"tag":901,"props":3418,"children":3420},{"className":3419},[3119],[3421],{"type":35,"value":2835},{"type":29,"tag":901,"props":3423,"children":3425},{"className":3424},[3119,3125],[3426],{"type":35,"value":2829},{"type":29,"tag":901,"props":3428,"children":3430},{"className":3429},[3119,3125],[3431],{"type":35,"value":2929},{"type":29,"tag":901,"props":3433,"children":3435},{"className":3434},[3119,3125],[3436],{"type":35,"value":2870},{"type":29,"tag":901,"props":3438,"children":3440},{"className":3439},[3119,3125],[3441],{"type":35,"value":2942},{"type":29,"tag":901,"props":3443,"children":3445},{"className":3444},[3119,3125],[3446],{"type":35,"value":2929},{"type":29,"tag":901,"props":3448,"children":3450},{"className":3449},[3119,3125],[3451],{"type":35,"value":2805},{"type":29,"tag":901,"props":3453,"children":3455},{"className":3454,"style":3248},[3119,3125],[3456],{"type":35,"value":3330},{"type":29,"tag":901,"props":3458,"children":3460},{"className":3459},[3119,3125],[3461],{"type":35,"value":37},{"type":29,"tag":901,"props":3463,"children":3465},{"className":3464},[3119,3125],[3466],{"type":35,"value":48},{"type":29,"tag":901,"props":3468,"children":3470},{"className":3469,"style":3210},[3119,3125],[3471],{"type":35,"value":3063},{"type":29,"tag":901,"props":3473,"children":3475},{"className":3474},[3119,3125],[3476],{"type":35,"value":3477},"an",{"type":29,"tag":901,"props":3479,"children":3481},{"className":3480},[3119,3125],[3482],{"type":35,"value":2929},{"type":29,"tag":901,"props":3484,"children":3487},{"className":3485},[3486],"mopen",[3488],{"type":35,"value":3080},{"type":29,"tag":901,"props":3490,"children":3494},{"className":3491},[3492,3493],"mspace","nobreak",[3495],{"type":35,"value":3086},{"type":29,"tag":901,"props":3497,"children":3499},{"className":3498},[3119],[3500],{"type":35,"value":3092},{"type":35,"value":3502},"/mois/utilisateur). Une intégration API directe coûte environ 0,5 à 2",{"type":29,"tag":901,"props":3504,"children":3506},{"className":3505},[2764],[3507,3744],{"type":29,"tag":901,"props":3508,"children":3510},{"className":3509},[2769],[3511],{"type":29,"tag":2772,"props":3512,"children":3513},{"xmlns":2774},[3514],{"type":29,"tag":2777,"props":3515,"children":3516},{},[3517,3739],{"type":29,"tag":2781,"props":3518,"children":3519},{},[3520,3524,3528,3532,3537,3541,3545,3549,3553,3557,3561,3565,3569,3573,3577,3581,3585,3589,3593,3597,3602,3606,3610,3615,3619,3623,3627,3631,3635,3639,3643,3647,3651,3655,3659,3664,3668,3672,3677,3681,3693,3697,3701,3705,3709,3713,3717,3722,3734],{"type":29,"tag":2785,"props":3521,"children":3522},{},[3523],{"type":35,"value":37},{"type":29,"tag":2785,"props":3525,"children":3526},{},[3527],{"type":35,"value":48},{"type":29,"tag":2785,"props":3529,"children":3530},{},[3531],{"type":35,"value":2875},{"type":29,"tag":2785,"props":3533,"children":3534},{},[3535],{"type":35,"value":3536},"P",{"type":29,"tag":2785,"props":3538,"children":3539},{},[3540],{"type":35,"value":2907},{"type":29,"tag":2785,"props":3542,"children":3543},{},[3544],{"type":35,"value":2810},{"type":29,"tag":2785,"props":3546,"children":3547},{},[3548],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3550,"children":3551},{},[3552],{"type":35,"value":2849},{"type":29,"tag":2785,"props":3554,"children":3555},{},[3556],{"type":35,"value":2800},{"type":29,"tag":2785,"props":3558,"children":3559},{},[3560],{"type":35,"value":2942},{"type":29,"tag":2785,"props":3562,"children":3563},{},[3564],{"type":35,"value":2849},{"type":29,"tag":2785,"props":3566,"children":3567},{},[3568],{"type":35,"value":48},{"type":29,"tag":2785,"props":3570,"children":3571},{},[3572],{"type":35,"value":2929},{"type":29,"tag":2785,"props":3574,"children":3575},{},[3576],{"type":35,"value":48},{"type":29,"tag":2785,"props":3578,"children":3579},{},[3580],{"type":35,"value":2805},{"type":29,"tag":2785,"props":3582,"children":3583},{},[3584],{"type":35,"value":2849},{"type":29,"tag":2785,"props":3586,"children":3587},{},[3588],{"type":35,"value":2849},{"type":29,"tag":2785,"props":3590,"children":3591},{},[3592],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3594,"children":3595},{"mathvariant":2787},[3596],{"type":35,"value":342},{"type":29,"tag":2785,"props":3598,"children":3599},{},[3600],{"type":35,"value":3601},"S",{"type":29,"tag":2785,"props":3603,"children":3604},{},[3605],{"type":35,"value":2870},{"type":29,"tag":2785,"props":3607,"children":3608},{},[3609],{"type":35,"value":2875},{"type":29,"tag":3088,"props":3611,"children":3612},{},[3613],{"type":35,"value":3614},"50",{"type":29,"tag":2785,"props":3616,"children":3617},{},[3618],{"type":35,"value":3536},{"type":29,"tag":2785,"props":3620,"children":3621},{},[3622],{"type":35,"value":2907},{"type":29,"tag":2785,"props":3624,"children":3625},{},[3626],{"type":35,"value":2810},{"type":29,"tag":2785,"props":3628,"children":3629},{"mathvariant":2787},[3630],{"type":35,"value":2790},{"type":29,"tag":2785,"props":3632,"children":3633},{},[3634],{"type":35,"value":2810},{"type":29,"tag":2785,"props":3636,"children":3637},{},[3638],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3640,"children":3641},{},[3642],{"type":35,"value":2795},{"type":29,"tag":2785,"props":3644,"children":3645},{},[3646],{"type":35,"value":48},{"type":29,"tag":2785,"props":3648,"children":3649},{},[3650],{"type":35,"value":2805},{"type":29,"tag":2785,"props":3652,"children":3653},{},[3654],{"type":35,"value":2942},{"type":29,"tag":2785,"props":3656,"children":3657},{},[3658],{"type":35,"value":2829},{"type":29,"tag":2831,"props":3660,"children":3661},{"separator":2823},[3662],{"type":35,"value":3663},",",{"type":29,"tag":2785,"props":3665,"children":3666},{},[3667],{"type":35,"value":2849},{"type":29,"tag":2785,"props":3669,"children":3670},{},[3671],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3673,"children":3674},{},[3675],{"type":35,"value":3676},"c",{"type":29,"tag":2785,"props":3678,"children":3679},{},[3680],{"type":35,"value":2800},{"type":29,"tag":2821,"props":3682,"children":3683},{"accent":2823},[3684,3688],{"type":29,"tag":2785,"props":3685,"children":3686},{},[3687],{"type":35,"value":2870},{"type":29,"tag":2831,"props":3689,"children":3690},{},[3691],{"type":35,"value":3692},"^",{"type":29,"tag":2785,"props":3694,"children":3695},{},[3696],{"type":35,"value":2929},{"type":29,"tag":2785,"props":3698,"children":3699},{},[3700],{"type":35,"value":2829},{"type":29,"tag":2785,"props":3702,"children":3703},{},[3704],{"type":35,"value":2810},{"type":29,"tag":2785,"props":3706,"children":3707},{},[3708],{"type":35,"value":2929},{"type":29,"tag":2785,"props":3710,"children":3711},{},[3712],{"type":35,"value":2819},{"type":29,"tag":2785,"props":3714,"children":3715},{},[3716],{"type":35,"value":2829},{"type":29,"tag":3088,"props":3718,"children":3719},{},[3720],{"type":35,"value":3721},"25",{"type":29,"tag":2821,"props":3723,"children":3724},{"accent":2823},[3725,3729],{"type":29,"tag":2785,"props":3726,"children":3727},{},[3728],{"type":35,"value":48},{"type":29,"tag":2831,"props":3730,"children":3731},{},[3732],{"type":35,"value":3733},"ˋ",{"type":29,"tag":3088,"props":3735,"children":3736},{},[3737],{"type":35,"value":3738},"100",{"type":29,"tag":3094,"props":3740,"children":3741},{"encoding":3096},[3742],{"type":35,"value":3743}," par PR selon la taille. Sur 50 PRs/semaine, le coût est de 25 à 100",{"type":29,"tag":901,"props":3745,"children":3747},{"className":3746,"ariaHidden":2823},[3103],[3748],{"type":29,"tag":901,"props":3749,"children":3751},{"className":3750},[3108],[3752,3756,3761,3766,3771,3777,3783,3788,3793,3798,3803,3808,3813,3819,3825,3830,3835,3841,3846,3851,3856,3861,3866,3871,3876,3882,3887,3893,3898,3903,3909,3954,3959,3965,3970,3975,3980,3985,4030],{"type":29,"tag":901,"props":3753,"children":3755},{"className":3754,"style":3114},[3113],[],{"type":29,"tag":901,"props":3757,"children":3759},{"className":3758},[3119,3125],[3760],{"type":35,"value":37},{"type":29,"tag":901,"props":3762,"children":3764},{"className":3763},[3119,3125],[3765],{"type":35,"value":48},{"type":29,"tag":901,"props":3767,"children":3769},{"className":3768,"style":3248},[3119,3125],[3770],{"type":35,"value":2875},{"type":29,"tag":901,"props":3772,"children":3774},{"className":3773,"style":3286},[3119,3125],[3775],{"type":35,"value":3776},"PR",{"type":29,"tag":901,"props":3778,"children":3780},{"className":3779},[3119,3125],[3781],{"type":35,"value":3782},"se",{"type":29,"tag":901,"props":3784,"children":3786},{"className":3785,"style":3221},[3119,3125],[3787],{"type":35,"value":2849},{"type":29,"tag":901,"props":3789,"children":3791},{"className":3790},[3119,3125],[3792],{"type":35,"value":2800},{"type":29,"tag":901,"props":3794,"children":3796},{"className":3795},[3119,3125],[3797],{"type":35,"value":2942},{"type":29,"tag":901,"props":3799,"children":3801},{"className":3800,"style":3221},[3119,3125],[3802],{"type":35,"value":2849},{"type":29,"tag":901,"props":3804,"children":3806},{"className":3805},[3119,3125],[3807],{"type":35,"value":48},{"type":29,"tag":901,"props":3809,"children":3811},{"className":3810},[3119,3125],[3812],{"type":35,"value":2929},{"type":29,"tag":901,"props":3814,"children":3816},{"className":3815},[3119,3125],[3817],{"type":35,"value":3818},"ai",{"type":29,"tag":901,"props":3820,"children":3822},{"className":3821,"style":3221},[3119,3125],[3823],{"type":35,"value":3824},"ll",{"type":29,"tag":901,"props":3826,"children":3828},{"className":3827},[3119,3125],[3829],{"type":35,"value":2829},{"type":29,"tag":901,"props":3831,"children":3833},{"className":3832},[3119],[3834],{"type":35,"value":342},{"type":29,"tag":901,"props":3836,"children":3839},{"className":3837,"style":3838},[3119,3125],"margin-right:0.05764em;",[3840],{"type":35,"value":3601},{"type":29,"tag":901,"props":3842,"children":3844},{"className":3843},[3119,3125],[3845],{"type":35,"value":2870},{"type":29,"tag":901,"props":3847,"children":3849},{"className":3848,"style":3248},[3119,3125],[3850],{"type":35,"value":2875},{"type":29,"tag":901,"props":3852,"children":3854},{"className":3853},[3119],[3855],{"type":35,"value":3614},{"type":29,"tag":901,"props":3857,"children":3859},{"className":3858,"style":3286},[3119,3125],[3860],{"type":35,"value":3776},{"type":29,"tag":901,"props":3862,"children":3864},{"className":3863},[3119,3125],[3865],{"type":35,"value":2810},{"type":29,"tag":901,"props":3867,"children":3869},{"className":3868},[3119],[3870],{"type":35,"value":2790},{"type":29,"tag":901,"props":3872,"children":3874},{"className":3873},[3119,3125],[3875],{"type":35,"value":3782},{"type":29,"tag":901,"props":3877,"children":3879},{"className":3878},[3119,3125],[3880],{"type":35,"value":3881},"main",{"type":29,"tag":901,"props":3883,"children":3885},{"className":3884},[3119,3125],[3886],{"type":35,"value":2829},{"type":29,"tag":901,"props":3888,"children":3891},{"className":3889},[3890],"mpunct",[3892],{"type":35,"value":3663},{"type":29,"tag":901,"props":3894,"children":3897},{"className":3895,"style":3896},[3492],"margin-right:0.1667em;",[],{"type":29,"tag":901,"props":3899,"children":3901},{"className":3900,"style":3221},[3119,3125],[3902],{"type":35,"value":2849},{"type":29,"tag":901,"props":3904,"children":3906},{"className":3905},[3119,3125],[3907],{"type":35,"value":3908},"eco",{"type":29,"tag":901,"props":3910,"children":3912},{"className":3911},[3119,3156],[3913],{"type":29,"tag":901,"props":3914,"children":3916},{"className":3915},[3161],[3917],{"type":29,"tag":901,"props":3918,"children":3920},{"className":3919},[3166],[3921],{"type":29,"tag":901,"props":3922,"children":3924},{"className":3923,"style":3172},[3171],[3925,3937],{"type":29,"tag":901,"props":3926,"children":3927},{"style":3176},[3928,3932],{"type":29,"tag":901,"props":3929,"children":3931},{"className":3930,"style":3182},[3181],[],{"type":29,"tag":901,"props":3933,"children":3935},{"className":3934},[3119,3125],[3936],{"type":35,"value":2870},{"type":29,"tag":901,"props":3938,"children":3939},{"style":3176},[3940,3944],{"type":29,"tag":901,"props":3941,"children":3943},{"className":3942,"style":3182},[3181],[],{"type":29,"tag":901,"props":3945,"children":3948},{"className":3946,"style":3947},[3199],"left:-0.2222em;",[3949],{"type":29,"tag":901,"props":3950,"children":3952},{"className":3951},[3119],[3953],{"type":35,"value":3692},{"type":29,"tag":901,"props":3955,"children":3957},{"className":3956},[3119,3125],[3958],{"type":35,"value":2929},{"type":29,"tag":901,"props":3960,"children":3962},{"className":3961},[3119,3125],[3963],{"type":35,"value":3964},"es",{"type":29,"tag":901,"props":3966,"children":3968},{"className":3967},[3119,3125],[3969],{"type":35,"value":2929},{"type":29,"tag":901,"props":3971,"children":3973},{"className":3972},[3119,3125],[3974],{"type":35,"value":2819},{"type":29,"tag":901,"props":3976,"children":3978},{"className":3977},[3119,3125],[3979],{"type":35,"value":2829},{"type":29,"tag":901,"props":3981,"children":3983},{"className":3982},[3119],[3984],{"type":35,"value":3721},{"type":29,"tag":901,"props":3986,"children":3988},{"className":3987},[3119,3156],[3989],{"type":29,"tag":901,"props":3990,"children":3992},{"className":3991},[3161],[3993],{"type":29,"tag":901,"props":3994,"children":3996},{"className":3995},[3166],[3997],{"type":29,"tag":901,"props":3998,"children":4000},{"className":3999,"style":3172},[3171],[4001,4013],{"type":29,"tag":901,"props":4002,"children":4003},{"style":3176},[4004,4008],{"type":29,"tag":901,"props":4005,"children":4007},{"className":4006,"style":3182},[3181],[],{"type":29,"tag":901,"props":4009,"children":4011},{"className":4010},[3119,3125],[4012],{"type":35,"value":48},{"type":29,"tag":901,"props":4014,"children":4015},{"style":3176},[4016,4020],{"type":29,"tag":901,"props":4017,"children":4019},{"className":4018,"style":3182},[3181],[],{"type":29,"tag":901,"props":4021,"children":4024},{"className":4022,"style":4023},[3199],"left:-0.25em;",[4025],{"type":29,"tag":901,"props":4026,"children":4028},{"className":4027},[3119],[4029],{"type":35,"value":3733},{"type":29,"tag":901,"props":4031,"children":4033},{"className":4032},[3119],[4034],{"type":35,"value":3738},{"type":35,"value":4036},"/semaine, marginal par rapport au coût d'un développeur. Le ROI est positif dès qu'une review IA prévient un seul bug en production.",{"type":29,"tag":381,"props":4038,"children":4039},{},[4040,4045],{"type":29,"tag":385,"props":4041,"children":4042},{},[4043],{"type":35,"value":4044},"4. Comment éviter que les développeurs seniors rejettent l'IA en code review ?",{"type":29,"tag":37,"props":4046,"children":4047},{},[4048],{"type":35,"value":4049},"En les impliquant dans la configuration. Les seniors qui configurent les règles de l'outil (quels patterns l'IA doit signaler, quels patterns ignorer) deviennent propriétaires de l'outil plutôt que sujets. Leur expertise améliore la qualité de l'IA, et leur résistance diminue quand ils voient leurs propres standards appliqués automatiquement.",{"type":29,"tag":381,"props":4051,"children":4052},{},[4053,4058],{"type":29,"tag":385,"props":4054,"children":4055},{},[4056],{"type":35,"value":4057},"5. L'IA en code review peut-elle nuire à l'apprentissage des développeurs juniors ?",{"type":29,"tag":37,"props":4059,"children":4060},{},[4061],{"type":35,"value":4062},"Risque réel si mal géré. Un junior qui reçoit du feedback uniquement de l'IA apprend les patterns que l'IA connaît, mais pas les jugements contextuels que les seniors auraient partagés. La règle : l'IA est le premier reviewer pour les juniors (feedback immédiat sur style et sécurité), mais la review humaine d'un senior reste obligatoire. Le senior peut commenter sur \"pourquoi cette architecture plutôt qu'une autre\", ce que l'IA ne peut pas faire.",{"type":29,"tag":381,"props":4064,"children":4065},{},[4066,4071],{"type":29,"tag":385,"props":4067,"children":4068},{},[4069],{"type":35,"value":4070},"6. Comment mesurer si l'IA améliore réellement la qualité du code sur 6 mois ?",{"type":29,"tag":37,"props":4072,"children":4073},{},[4074],{"type":35,"value":4075},"Deux métriques combinées : le bug escape rate (bugs détectés en production / bugs détectés en review) et la densité de défauts par KLOC sur le code produit depuis l'adoption. Si le bug escape rate diminue et que la densité de défauts diminue, l'IA améliore la qualité. Si seulement le bug escape rate diminue, l'IA détecte mieux mais ne change pas les pratiques de développement : il faut renforcer la formation.",{"type":29,"tag":76,"props":4077,"children":4078},{},[],{"type":29,"tag":176,"props":4080,"children":4083},{"cta":4081,"href":453,"title":4082,"type":455},"Testez la readiness IA de votre équipe →","Ressource gratuite : AI-Ready Engineering Team Checklist",[4084],{"type":29,"tag":37,"props":4085,"children":4086},{},[4087],{"type":35,"value":4088},"La checklist AI-Ready inclut une section dédiée à l'adoption des outils IA en code review : critères de sélection d'outil, règles d'intégration, et métriques de suivi à 30 et 90 jours.",{"type":29,"tag":1252,"props":4090,"children":4091},{},[4092],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":4094},[4095,4096,4097,4098,4099,4100,4101],{"id":2164,"depth":463,"text":2167},{"id":2335,"depth":463,"text":2338},{"id":2408,"depth":463,"text":2411},{"id":2452,"depth":463,"text":2455},{"id":2608,"depth":463,"text":2611},{"id":2657,"depth":463,"text":2660},{"id":2711,"depth":463,"text":2714},"content:fr:intelligence-artificielle:ia-code-review-retour-experience.md","fr/intelligence-artificielle/ia-code-review-retour-experience.md","fr/intelligence-artificielle/ia-code-review-retour-experience",{"_path":50,"_dir":4106,"_draft":7,"_partial":7,"_locale":8,"title":4107,"description":4108,"id":4109,"date":4110,"listed":13,"nocomments":7,"hidden":7,"categories":4111,"tags":4112,"--cover":4117,"readingTime":4118,"body":4122,"_type":476,"_id":4567,"_source":478,"_file":4568,"_stem":4569,"_extension":481},"pratiques-agiles","Limiter le Work In Progress : le levier le plus sous-estimé","La loi de Little appliquée à l'engineering : réduire le WIP est plus efficace que d'accélérer les développeurs. La démonstration et le protocole de mise en œuvre.",32,"2026-03-18",[4106],[4113,4114,4115,4116],"Work In Progress","WIP","Kanban","Flow","covers/articles/reduire-work-in-progress.jpg",{"text":21,"minutes":4119,"time":4120,"words":4121},8.105,486300,1621,{"type":26,"children":4123,"toc":4559},[4124,4129,4134,4139,4144,4149,4154,4157,4163,4168,4176,4181,4186,4202,4219,4236,4241,4244,4250,4255,4265,4275,4285,4310,4319,4322,4328,4338,4348,4353,4371,4381,4391,4401,4404,4410,4420,4438,4448,4451,4457,4462,4467,4472,4475,4481,4494,4507,4520,4533,4546,4549],{"type":29,"tag":30,"props":4125,"children":4127},{"id":4126},"limiter-le-work-in-progress-le-levier-le-plus-sous-estimé",[4128],{"type":35,"value":4107},{"type":29,"tag":37,"props":4130,"children":4131},{},[4132],{"type":35,"value":4133},"J'accompagnais une équipe produit de 8 développeurs chez un client dans le secteur financier. Ils me demandaient comment livrer plus vite. Je leur ai demandé de compter le nombre de stories \"In Progress\" sur leur board.",{"type":29,"tag":37,"props":4135,"children":4136},{},[4137],{"type":35,"value":4138},"Il y en avait 22.",{"type":29,"tag":37,"props":4140,"children":4141},{},[4142],{"type":35,"value":4143},"22 stories pour 8 développeurs. Chaque développeur avait en moyenne 2,75 sujets en cours simultanément. Certains jonglaient entre 4 contextes différents dans la même journée.",{"type":29,"tag":37,"props":4145,"children":4146},{},[4147],{"type":35,"value":4148},"J'ai posé la question suivante : \"Quelle est la dernière fois qu'une story est allée de 'To Do' à 'Done' en moins de 3 jours ?\" Silence. L'un d'eux a vérifié Jira. La réponse était : 6 semaines auparavant.",{"type":29,"tag":37,"props":4150,"children":4151},{},[4152],{"type":35,"value":4153},"La solution que je leur ai proposée n'était pas d'embaucher, ni de changer de framework, ni d'adopter une nouvelle méthodologie. C'était de réduire le nombre de choses en cours simultanément. Ça semblait trop simple. C'était la bonne réponse.",{"type":29,"tag":76,"props":4155,"children":4156},{},[],{"type":29,"tag":80,"props":4158,"children":4160},{"id":4159},"la-loi-de-little-la-démonstration-mathématique",[4161],{"type":35,"value":4162},"La loi de Little : la démonstration mathématique",{"type":29,"tag":37,"props":4164,"children":4165},{},[4166],{"type":35,"value":4167},"La loi de Little, formulée par le mathématicien John Dutton Converse Little en 1961, s'applique à tout système de flux (file d'attente bancaire, réseau logistique, ou équipe de développement logiciel).",{"type":29,"tag":37,"props":4169,"children":4170},{},[4171],{"type":29,"tag":65,"props":4172,"children":4173},{},[4174],{"type":35,"value":4175},"Lead Time = Work In Progress / Throughput",{"type":29,"tag":37,"props":4177,"children":4178},{},[4179],{"type":35,"value":4180},"Traduction pour l'engineering : si votre équipe livre 10 stories par semaine (throughput) et a 30 stories en cours simultanément (WIP), le lead time moyen est de 3 semaines. Pour réduire le lead time à 1 semaine sans changer le throughput : réduire le WIP à 10 stories.",{"type":29,"tag":37,"props":4182,"children":4183},{},[4184],{"type":35,"value":4185},"La démonstration chiffrée est implacable.",{"type":29,"tag":37,"props":4187,"children":4188},{},[4189,4194,4196,4201],{"type":29,"tag":65,"props":4190,"children":4191},{},[4192],{"type":35,"value":4193},"Scénario A : WIP illimité",{"type":35,"value":4195}," : équipe de 5 développeurs, 15 stories en cours (3 par développeur), throughput de 10 stories par semaine. Lead Time moyen : 15 / 10 = ",{"type":29,"tag":65,"props":4197,"children":4198},{},[4199],{"type":35,"value":4200},"1,5 semaine",{"type":35,"value":342},{"type":29,"tag":37,"props":4203,"children":4204},{},[4205,4210,4212,4217],{"type":29,"tag":65,"props":4206,"children":4207},{},[4208],{"type":35,"value":4209},"Scénario B : WIP limité à 8",{"type":35,"value":4211}," : même équipe, même throughput, 8 stories en cours. Lead Time moyen : 8 / 10 = ",{"type":29,"tag":65,"props":4213,"children":4214},{},[4215],{"type":35,"value":4216},"0,8 semaine",{"type":35,"value":4218}," (−47%).",{"type":29,"tag":37,"props":4220,"children":4221},{},[4222,4227,4229,4234],{"type":29,"tag":65,"props":4223,"children":4224},{},[4225],{"type":35,"value":4226},"Scénario C : WIP limité à 5",{"type":35,"value":4228}," : 5 stories en cours (1 par développeur). Lead Time moyen : 5 / 10 = ",{"type":29,"tag":65,"props":4230,"children":4231},{},[4232],{"type":35,"value":4233},"0,5 semaine",{"type":35,"value":4235}," (−67%).",{"type":29,"tag":37,"props":4237,"children":4238},{},[4239],{"type":35,"value":4240},"En réduisant le WIP de 15 à 5, le lead time est divisé par 3, sans changer une ligne de code, sans recruter, sans changer de framework. C'est contre-intuitif dans une culture qui valorise l'occupation maximale. C'est pourtant ce que la théorie des contraintes de Goldratt et les principes Kanban enseignent depuis des décennies.",{"type":29,"tag":76,"props":4242,"children":4243},{},[],{"type":29,"tag":80,"props":4245,"children":4247},{"id":4246},"pourquoi-le-wip-augmente-naturellement",[4248],{"type":35,"value":4249},"Pourquoi le WIP augmente naturellement",{"type":29,"tag":37,"props":4251,"children":4252},{},[4253],{"type":35,"value":4254},"Dans la plupart des équipes, le WIP augmente sans décision consciente. Les mécanismes sont structurels.",{"type":29,"tag":37,"props":4256,"children":4257},{},[4258,4263],{"type":29,"tag":65,"props":4259,"children":4260},{},[4261],{"type":35,"value":4262},"Le multitâche comme norme.",{"type":35,"value":4264}," Un développeur bloqué sur une story en attend le feedback, démarre une deuxième story, est interrompu pour une troisième urgence. Sans règle explicite, 3 stories en parallèle par développeur devient la norme, et personne ne la remet en question.",{"type":29,"tag":37,"props":4266,"children":4267},{},[4268,4273],{"type":29,"tag":65,"props":4269,"children":4270},{},[4271],{"type":35,"value":4272},"La peur du \"slack\".",{"type":35,"value":4274}," Un développeur qui n'a rien en cours est perçu comme improductif. Résultat : chacun s'assigne une nouvelle story plutôt que d'aider un collègue à terminer. Le système optimise l'occupation individuelle au détriment du flux collectif.",{"type":29,"tag":37,"props":4276,"children":4277},{},[4278,4283],{"type":29,"tag":65,"props":4279,"children":4280},{},[4281],{"type":35,"value":4282},"Les dépendances non résolues.",{"type":35,"value":4284}," Une story en attente d'une décision produit, d'une clarification métier, ou d'une PR de review contribue au WIP sans avancer. Elle bloque la colonne sans produire de valeur.",{"type":29,"tag":37,"props":4286,"children":4287},{},[4288,4300,4302,4308],{"type":29,"tag":65,"props":4289,"children":4290},{},[4291,4293,4299],{"type":35,"value":4292},"Le ",{"type":29,"tag":48,"props":4294,"children":4296},{"href":4295},"/fr/pratiques-agiles/anti-patterns-backlog",[4297],{"type":35,"value":4298},"backlog infini",{"type":35,"value":342},{"type":35,"value":4301}," Si le backlog a 200 stories priorisées et qu'il n'y a pas de limite explicite, l'équipe accepte plus qu'elle ne peut faire. C'est le ",{"type":29,"tag":48,"props":4303,"children":4305},{"href":4304},"/fr/pratiques-agiles/sprint-planning-efficace",[4306],{"type":35,"value":4307},"sprint planning",{"type":35,"value":4309}," qui génère du WIP excessif.",{"type":29,"tag":176,"props":4311,"children":4313},{"cta":178,"href":179,"title":4312,"type":181},"Votre lead time dépasse 3 semaines et vous cherchez les bons leviers pour le réduire ?",[4314],{"type":29,"tag":37,"props":4315,"children":4316},{},[4317],{"type":35,"value":4318},"Identifier les bonnes limites de WIP pour votre équipe nécessite une analyse du flux actuel. En 30 minutes, je calcule votre lead time théorique, j'identifie les goulots d'étranglement, et je définis avec vous les limites de WIP adaptées à votre contexte.",{"type":29,"tag":76,"props":4320,"children":4321},{},[],{"type":29,"tag":80,"props":4323,"children":4325},{"id":4324},"le-protocole-dimplémentation-en-5-étapes",[4326],{"type":35,"value":4327},"Le protocole d'implémentation en 5 étapes",{"type":29,"tag":37,"props":4329,"children":4330},{},[4331,4336],{"type":29,"tag":65,"props":4332,"children":4333},{},[4334],{"type":35,"value":4335},"Étape 1 : Mesurer le WIP actuel.",{"type":35,"value":4337}," Avant d'imposer une limite, mesurer l'état réel. Pendant 2 semaines, poser ces questions en daily standup : combien de stories chaque développeur a-t-il en cours aujourd'hui ? Combien de stories sont en cours depuis plus de 5 jours ? Quel est le nombre total de stories \"In Progress\" sur le board ? Calculer la moyenne. C'est le WIP de départ.",{"type":29,"tag":37,"props":4339,"children":4340},{},[4341,4346],{"type":29,"tag":65,"props":4342,"children":4343},{},[4344],{"type":35,"value":4345},"Étape 2 : Définir les limites initiales.",{"type":35,"value":4347}," Règle pratique de départ : limite WIP = nombre de développeurs × 1,5. Pour une équipe de 6 : limite WIP = 9. C'est plus restrictif que l'état naturel (souvent 2 à 3 fois le nombre de développeurs) mais pas encore au niveau optimal.",{"type":29,"tag":37,"props":4349,"children":4350},{},[4351],{"type":35,"value":4352},"La limite s'applique par colonne du board Kanban, pas au total :",{"type":29,"tag":1080,"props":4354,"children":4355},{},[4356,4361,4366],{"type":29,"tag":1084,"props":4357,"children":4358},{},[4359],{"type":35,"value":4360},"\"In Progress\" : limite = N développeurs",{"type":29,"tag":1084,"props":4362,"children":4363},{},[4364],{"type":35,"value":4365},"\"In Review\" : limite = N/2",{"type":29,"tag":1084,"props":4367,"children":4368},{},[4369],{"type":35,"value":4370},"\"In Testing\" : limite = N/3",{"type":29,"tag":37,"props":4372,"children":4373},{},[4374,4379],{"type":29,"tag":65,"props":4375,"children":4376},{},[4377],{"type":35,"value":4378},"Étape 3 : Rendre la limite visible et automatique.",{"type":35,"value":4380}," Sur Jira, configurer le \"Work In Progress Limit\" sur chaque colonne du board. Jira affiche une alerte visuelle (colonne en rouge) quand la limite est atteinte. La règle doit être visible passivement, pas nécessiter une vérification active.",{"type":29,"tag":37,"props":4382,"children":4383},{},[4384,4389],{"type":29,"tag":65,"props":4385,"children":4386},{},[4387],{"type":35,"value":4388},"Étape 4 : Créer la règle \"finir avant de commencer\".",{"type":35,"value":4390}," Quand la limite WIP est atteinte, avant d'ouvrir une nouvelle story : fermer une story en cours. Ce qui implique concrètement d'aider un collègue à débloquer sa story, de prioriser les code reviews en attente (qui bloquent les stories en review), ou de diviser une grande story bloquée en sous-stories terminables.",{"type":29,"tag":37,"props":4392,"children":4393},{},[4394,4399],{"type":29,"tag":65,"props":4395,"children":4396},{},[4397],{"type":35,"value":4398},"Étape 5 : Ajuster la limite après 4 sprints.",{"type":35,"value":4400}," La limite initiale n'est pas la limite optimale. Si le board n'atteint jamais la limite : trop haute, la réduire de 20%. Si la limite bloque constamment le flux : peut-être trop basse, ou signal d'un goulot d'étranglement à résoudre autrement.",{"type":29,"tag":76,"props":4402,"children":4403},{},[],{"type":29,"tag":80,"props":4405,"children":4407},{"id":4406},"les-résistances-et-comment-les-adresser",[4408],{"type":35,"value":4409},"Les résistances et comment les adresser",{"type":29,"tag":37,"props":4411,"children":4412},{},[4413,4418],{"type":29,"tag":65,"props":4414,"children":4415},{},[4416],{"type":35,"value":4417},"\"Je suis bloqué, je dois bien commencer autre chose.\"",{"type":35,"value":4419}," Cette résistance est légitime. Ma réponse : le blocage est l'information importante, pas le contournement. Un développeur bloqué doit d'abord chercher à débloquer : escalader la dépendance, poser la question dans Slack, demander de l'aide. Ce n'est qu'après 2 heures de blocage sans perspective de résolution que commencer une autre story est acceptable. Et ce dépassement doit être visible sur le board.",{"type":29,"tag":37,"props":4421,"children":4422},{},[4423,4428,4430,4436],{"type":29,"tag":65,"props":4424,"children":4425},{},[4426],{"type":35,"value":4427},"\"Le business veut des estimations et une limite WIP les rend impossibles.\"",{"type":35,"value":4429}," Faux. Avec une limite WIP et la loi de Little, les prédictions sont plus précises, pas moins. \"Nous avons X stories en cours et Y en backlog. Avec notre ",{"type":29,"tag":48,"props":4431,"children":4433},{"href":4432},"/fr/pratiques-agiles/story-points-estimation-agile-alternative",[4434],{"type":35,"value":4435},"throughput",{"type":35,"value":4437}," de 10 stories par semaine et une limite WIP de 8, la feature Z sera livrée dans cet intervalle de confiance.\" C'est plus précis qu'une vélocité en story points qui dérive avec le temps.",{"type":29,"tag":37,"props":4439,"children":4440},{},[4441,4446],{"type":29,"tag":65,"props":4442,"children":4443},{},[4444],{"type":35,"value":4445},"\"Mes développeurs vont s'ennuyer en attendant.\"",{"type":35,"value":4447}," Les développeurs ne s'ennuient jamais : ils ont du backlog et de la dette technique. La vraie question est : qu'est-ce qui est plus précieux, commencer une nouvelle story ou aider à terminer les stories en cours ? La réponse est presque toujours la deuxième option. Finir une story livrée au client vaut plus que démarrer une story qui attendra 3 semaines dans la file.",{"type":29,"tag":76,"props":4449,"children":4450},{},[],{"type":29,"tag":80,"props":4452,"children":4454},{"id":4453},"ce-que-ça-a-changé",[4455],{"type":35,"value":4456},"Ce que ça a changé",{"type":29,"tag":37,"props":4458,"children":4459},{},[4460],{"type":35,"value":4461},"Dans l'équipe de 8 développeurs mentionnée en introduction, le WIP moyen était de 22 stories simultanées. Après implémentation des limites WIP à 10 et de la règle \"finir avant de commencer\", le WIP a baissé à 9 en 6 semaines. Le lead time moyen est passé de 18 jours à 7 jours. Le nombre de stories livrées par sprint n'a pas changé, mais leur délai de livraison a été divisé par 2,5.",{"type":29,"tag":37,"props":4463,"children":4464},{},[4465],{"type":35,"value":4466},"Les métriques à suivre pour mesurer l'impact : WIP moyen hebdomadaire (la tendance doit baisser), age du WIP en jours (les stories vieilles de plus de 2 sprints sont des signaux d'alerte), et distribution du lead time par story (une distribution qui se resserre indique un flux qui se normalise).",{"type":29,"tag":37,"props":4468,"children":4469},{},[4470],{"type":35,"value":4471},"Ce n'était jamais un problème de personnes. C'était un problème de système, et le système a changé quand les règles ont changé.",{"type":29,"tag":76,"props":4473,"children":4474},{},[],{"type":29,"tag":80,"props":4476,"children":4478},{"id":4477},"faq-sur-les-limites-de-wip",[4479],{"type":35,"value":4480},"FAQ sur les limites de WIP",{"type":29,"tag":381,"props":4482,"children":4483},{},[4484,4489],{"type":29,"tag":385,"props":4485,"children":4486},{},[4487],{"type":35,"value":4488},"1. Les limites de WIP s'appliquent-elles en Scrum comme en Kanban ?",{"type":29,"tag":37,"props":4490,"children":4491},{},[4492],{"type":35,"value":4493},"Oui. En Kanban, les limites WIP sont un principe fondamental. En Scrum, elles s'appliquent au niveau du sprint board. La différence est que Scrum permet de remplir le sprint à 100% de la capacité théorique, ce qui crée du WIP élevé. En ajoutant une limite explicite (ex: max 2 stories par développeur simultanément), l'équipe Scrum bénéficie des mêmes avantages de flux que Kanban.",{"type":29,"tag":381,"props":4495,"children":4496},{},[4497,4502],{"type":29,"tag":385,"props":4498,"children":4499},{},[4500],{"type":35,"value":4501},"2. Comment gérer les urgences qui obligent à dépasser la limite WIP ?",{"type":29,"tag":37,"props":4503,"children":4504},{},[4505],{"type":35,"value":4506},"Les urgences existent et peuvent justifier de dépasser temporairement la limite. La règle : chaque dépassement est une décision consciente et visible, la colonne du board vire au rouge. Après chaque urgence, analyser en rétro : était-ce vraiment une urgence ? Aurait-on pu l'anticiper ? Les équipes qui dépassent la limite pour urgence chaque semaine ont un problème de priorisation, pas de WIP.",{"type":29,"tag":381,"props":4508,"children":4509},{},[4510,4515],{"type":29,"tag":385,"props":4511,"children":4512},{},[4513],{"type":35,"value":4514},"3. Quelle est la limite WIP optimale ?",{"type":29,"tag":37,"props":4516,"children":4517},{},[4518],{"type":35,"value":4519},"Il n'y a pas de réponse universelle : elle dépend de la taille d'équipe, de la complexité des stories, et du niveau d'interdépendances. La règle empirique est de commencer à 1,5 fois le nombre de développeurs et d'ajuster vers le bas jusqu'à trouver la valeur où le lead time se stabilise sans créer de goulot d'étranglement. En pratique, la plupart des équipes trouvent leur optimum entre 1 et 2 fois le nombre de développeurs.",{"type":29,"tag":381,"props":4521,"children":4522},{},[4523,4528],{"type":29,"tag":385,"props":4524,"children":4525},{},[4526],{"type":35,"value":4527},"4. Comment les limites WIP interagissent-elles avec les bugs urgents ?",{"type":29,"tag":37,"props":4529,"children":4530},{},[4531],{"type":35,"value":4532},"Les bugs urgents (P1/P0) sont traités comme des interruptions explicites. Un bug P1 peut entrer en cours sans respecter la limite WIP, mais il doit être la priorité absolue jusqu'à sa résolution. Le développeur qui prend un bug P1 stationne sa story en cours dans une colonne \"On Hold\". Le WIP réel ne dépasse pas la limite : il y a une substitution consciente et visible.",{"type":29,"tag":381,"props":4534,"children":4535},{},[4536,4541],{"type":29,"tag":385,"props":4537,"children":4538},{},[4539],{"type":35,"value":4540},"5. Comment convaincre le management que moins de WIP n'est pas moins de travail ?",{"type":29,"tag":37,"props":4542,"children":4543},{},[4544],{"type":35,"value":4545},"Par la démonstration chiffrée de la loi de Little. Montrer le calcul : avec un WIP de 20 et un throughput de 10 stories par semaine, le lead time est de 2 semaines. Avec un WIP de 10, le lead time est de 1 semaine. Même throughput, deux fois plus de réactivité pour le business. Le business valorise la rapidité de livraison : les limites WIP la produisent sans recruter.",{"type":29,"tag":76,"props":4547,"children":4548},{},[],{"type":29,"tag":176,"props":4550,"children":4553},{"cta":4551,"href":453,"title":4552,"type":455},"Télécharger le guide gratuit →","Ressource gratuite : Guide Lead Time -50% en 90 jours",[4554],{"type":29,"tag":37,"props":4555,"children":4556},{},[4557],{"type":35,"value":4558},"Le guide complet pour réduire votre lead time en 90 jours inclut un chapitre détaillé sur l'implémentation des limites WIP, les métriques de suivi, et les benchmarks par taille d'équipe, avec les données issues de mes accompagnements terrain.",{"title":8,"searchDepth":463,"depth":463,"links":4560},[4561,4562,4563,4564,4565,4566],{"id":4159,"depth":463,"text":4162},{"id":4246,"depth":463,"text":4249},{"id":4324,"depth":463,"text":4327},{"id":4406,"depth":463,"text":4409},{"id":4453,"depth":463,"text":4456},{"id":4477,"depth":463,"text":4480},"content:fr:pratiques-agiles:reduire-work-in-progress-velocite.md","fr/pratiques-agiles/reduire-work-in-progress-velocite.md","fr/pratiques-agiles/reduire-work-in-progress-velocite",{"_path":355,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":4571,"description":4572,"id":4573,"date":4574,"listed":13,"nocomments":7,"hidden":7,"categories":4575,"tags":4576,"--cover":4580,"readingTime":4581,"body":4585,"_type":476,"_id":5078,"_source":478,"_file":5079,"_stem":5080,"_extension":481},"Pair programming : ROI réel et conditions de succès","Les études montrent un ROI de 15% sur la qualité à long terme — mais seulement dans certaines conditions. Ce que la recherche dit vraiment sur le pair programming.",31,"2026-03-16",[6],[4577,4578,4579],"Pair Programming","ROI","Pratiques Engineering","covers/articles/pair-programming-roi.jpg",{"text":497,"minutes":4582,"time":4583,"words":4584},7.08,424800,1416,{"type":26,"children":4586,"toc":5065},[4587,4592,4597,4605,4610,4613,4619,4638,4643,4662,4672,4675,4681,4686,4696,4706,4716,4726,4729,4738,4741,4747,4753,4758,4781,4786,4804,4810,4815,4820,4826,4859,4865,4870,4873,4879,4889,4899,4909,4912,4918,4928,4938,4956,4973,4976,4982,4995,5008,5021,5041,5054,5057],{"type":29,"tag":30,"props":4588,"children":4590},{"id":4589},"pair-programming-roi-réel-et-conditions-de-succès",[4591],{"type":35,"value":4571},{"type":29,"tag":37,"props":4593,"children":4594},{},[4595],{"type":35,"value":4596},"J'accompagnais une équipe dans une banque d'investissement parisienne : 18 développeurs, une culture tech solide. Trois nouveaux développeurs venaient de rejoindre l'équipe. Habituellement, leur montée en compétence prenait 8 semaines avant d'être autonomes sur les modules critiques. J'ai proposé d'introduire le pair programming exclusivement sur leur onboarding : chaque nouveau développeur pairait systématiquement avec un senior sur ses premières stories complexes. Le résultat, mesuré 6 semaines plus tard : les trois nouvelles recrues étaient autonomes en 4 semaines au lieu de 8. Et sans qu'on le planifie, les seniors avaient commencé à se pairer entre eux sur les stories de refactoring difficiles.",{"type":29,"tag":37,"props":4598,"children":4599},{},[4600],{"type":29,"tag":65,"props":4601,"children":4602},{},[4603],{"type":35,"value":4604},"Le pair programming est soit adulé par les équipes XP, soit rejeté par les managers qui voient \"deux personnes sur un seul clavier\". Rarement évalué objectivement. Or les données sont là, et elles sont plus nuancées que ce que les deux camps affirment.",{"type":29,"tag":37,"props":4606,"children":4607},{},[4608],{"type":35,"value":4609},"J'ai introduit le pair programming dans une dizaine d'équipes au cours des 10 dernières années, dans la finance, les médias, les télécoms. Certaines fois, ça a transformé la culture et la qualité. D'autres fois, ça a créé des tensions et été abandonné en 3 semaines. La différence ne tenait pas à la pratique, mais aux conditions d'introduction.",{"type":29,"tag":76,"props":4611,"children":4612},{},[],{"type":29,"tag":80,"props":4614,"children":4616},{"id":4615},"ce-que-la-recherche-dit-vraiment",[4617],{"type":35,"value":4618},"Ce que la recherche dit vraiment",{"type":29,"tag":37,"props":4620,"children":4621},{},[4622,4624,4629,4631,4636],{"type":35,"value":4623},"L'étude de référence est celle de Laurie Williams et Robert Kessler (2000, University of Utah) : sur un projet de développement logiciel, le pair programming produit un code avec ",{"type":29,"tag":65,"props":4625,"children":4626},{},[4627],{"type":35,"value":4628},"15% moins de défauts",{"type":35,"value":4630}," que le développement solo, mais avec ",{"type":29,"tag":65,"props":4632,"children":4633},{},[4634],{"type":35,"value":4635},"15% de temps supplémentaire",{"type":35,"value":4637}," à court terme.",{"type":29,"tag":37,"props":4639,"children":4640},{},[4641],{"type":35,"value":4642},"Le ROI net sur le long terme est positif pour une raison simple : le coût d'un défaut en production est 10 à 100 fois supérieur au coût de le détecter pendant le développement. 15% de temps en plus pour 15% de défauts en moins, c'est rentable dès que les défauts ont un coût significatif.",{"type":29,"tag":37,"props":4644,"children":4645},{},[4646,4648,4653,4655,4660],{"type":35,"value":4647},"Une méta-analyse de 2007 (Hannay et al., 18 études) nuance cependant les résultats : le bénéfice du pair programming est plus élevé pour les ",{"type":29,"tag":65,"props":4649,"children":4650},{},[4651],{"type":35,"value":4652},"tâches complexes",{"type":35,"value":4654}," et ",{"type":29,"tag":65,"props":4656,"children":4657},{},[4658],{"type":35,"value":4659},"les juniors qui travaillent avec des seniors",{"type":35,"value":4661},". Sur des tâches simples ou répétitives, l'overhead est présent sans le bénéfice proportionnel.",{"type":29,"tag":37,"props":4663,"children":4664},{},[4665,4670],{"type":29,"tag":65,"props":4666,"children":4667},{},[4668],{"type":35,"value":4669},"Ce que ça signifie concrètement",{"type":35,"value":4671}," : le pair programming n'est pas une pratique à appliquer uniformément. C'est une pratique à utiliser sur les bonnes tâches, dans les bonnes conditions.",{"type":29,"tag":76,"props":4673,"children":4674},{},[],{"type":29,"tag":80,"props":4676,"children":4678},{"id":4677},"quand-le-pair-programming-dégrade-la-productivité",[4679],{"type":35,"value":4680},"Quand le pair programming dégrade la productivité",{"type":29,"tag":37,"props":4682,"children":4683},{},[4684],{"type":35,"value":4685},"Avant les conditions de succès, les conditions d'échec, parce qu'elles sont plus fréquentes.",{"type":29,"tag":37,"props":4687,"children":4688},{},[4689,4694],{"type":29,"tag":65,"props":4690,"children":4691},{},[4692],{"type":35,"value":4693},"Tâches trop simples",{"type":35,"value":4695}," : un bug trivial, une modification de configuration, une story de 1 point. L'overhead cognitif de coordonner deux personnes dépasse le bénéfice. Résultat : frustration et sentiment de temps perdu.",{"type":29,"tag":37,"props":4697,"children":4698},{},[4699,4704],{"type":29,"tag":65,"props":4700,"children":4701},{},[4702],{"type":35,"value":4703},"Parité trop déséquilibrée sans intention pédagogique",{"type":35,"value":4705}," : un senior qui \"dicte\" pendant qu'un junior \"exécute\" n'est pas du pair programming, c'est de la supervision déguisée. C'est épuisant pour les deux et n'apporte pas les bénéfices de qualité attendus.",{"type":29,"tag":37,"props":4707,"children":4708},{},[4709,4714],{"type":29,"tag":65,"props":4710,"children":4711},{},[4712],{"type":35,"value":4713},"Sessions trop longues sans rotation",{"type":35,"value":4715}," : après 90 minutes de pair programming intensif, la fatigue cognitive s'accumule. Des sessions de plus de 2 heures sans pause produisent des erreurs que des sessions de 90 minutes n'auraient pas produites.",{"type":29,"tag":37,"props":4717,"children":4718},{},[4719,4724],{"type":29,"tag":65,"props":4720,"children":4721},{},[4722],{"type":35,"value":4723},"Introduction imposée sans explication",{"type":35,"value":4725}," : \"Désormais, toutes les stories se font en pair programming.\" Sans comprendre pourquoi, les développeurs perçoivent la pratique comme un manque de confiance. La résistance est immédiate et dure.",{"type":29,"tag":76,"props":4727,"children":4728},{},[],{"type":29,"tag":176,"props":4730,"children":4732},{"cta":178,"href":179,"title":4731,"type":181},"Vous voulez introduire le pair programming mais vous ne savez pas comment éviter la résistance ?",[4733],{"type":29,"tag":37,"props":4734,"children":4735},{},[4736],{"type":35,"value":4737},"Vous avez tenté de lancer le pair programming et ça n'a pas pris, ou vous voulez bien faire du premier coup pour ne pas brûler le capital de confiance de l'équipe. L'introduction réussie dépend de la communication des objectifs, du choix des premières tâches, et du format adapté à votre contexte. En 30 minutes, on définit la stratégie adaptée.",{"type":29,"tag":76,"props":4739,"children":4740},{},[],{"type":29,"tag":80,"props":4742,"children":4744},{"id":4743},"les-4-conditions-de-succès",[4745],{"type":35,"value":4746},"Les 4 conditions de succès",{"type":29,"tag":116,"props":4748,"children":4750},{"id":4749},"condition-1-le-bon-contexte-de-tâche",[4751],{"type":35,"value":4752},"Condition 1 : Le bon contexte de tâche",{"type":29,"tag":37,"props":4754,"children":4755},{},[4756],{"type":35,"value":4757},"Le pair programming apporte le plus de valeur sur :",{"type":29,"tag":1080,"props":4759,"children":4760},{},[4761,4766,4771,4776],{"type":29,"tag":1084,"props":4762,"children":4763},{},[4764],{"type":35,"value":4765},"Les tâches complexes avec des contraintes non-triviales",{"type":29,"tag":1084,"props":4767,"children":4768},{},[4769],{"type":35,"value":4770},"Les tâches dans des zones de code peu connues ou à haut risque",{"type":29,"tag":1084,"props":4772,"children":4773},{},[4774],{"type":35,"value":4775},"Les tâches d'architecture ou de design",{"type":29,"tag":1084,"props":4777,"children":4778},{},[4779],{"type":35,"value":4780},"L'onboarding d'un nouveau développeur sur un module spécifique",{"type":29,"tag":37,"props":4782,"children":4783},{},[4784],{"type":35,"value":4785},"Il apporte peu de valeur sur :",{"type":29,"tag":1080,"props":4787,"children":4788},{},[4789,4794,4799],{"type":29,"tag":1084,"props":4790,"children":4791},{},[4792],{"type":35,"value":4793},"Les tâches répétitives et bien définies",{"type":29,"tag":1084,"props":4795,"children":4796},{},[4797],{"type":35,"value":4798},"Les investigations longues et exploratoires (pair review après, pas pair programming pendant)",{"type":29,"tag":1084,"props":4800,"children":4801},{},[4802],{"type":35,"value":4803},"Les optimisations de performance nécessitant du profiling individuel",{"type":29,"tag":116,"props":4805,"children":4807},{"id":4806},"condition-2-la-rotation-du-rôle-drivernavigator",[4808],{"type":35,"value":4809},"Condition 2 : La rotation du rôle driver/navigator",{"type":29,"tag":37,"props":4811,"children":4812},{},[4813],{"type":35,"value":4814},"Le format classique est driver/navigator : le driver écrit le code, le navigator réfléchit à la direction et détecte les erreurs. La rotation doit être explicite et fréquente, toutes les 25 à 30 minutes (technique Pomodoro adaptée).",{"type":29,"tag":37,"props":4816,"children":4817},{},[4818],{"type":35,"value":4819},"Sans rotation, l'un des deux s'ennuie ou se décroche. Avec rotation, les deux restent engagés et le code bénéficie de deux perspectives actives.",{"type":29,"tag":116,"props":4821,"children":4823},{"id":4822},"condition-3-la-parité-ajustée-à-lobjectif",[4824],{"type":35,"value":4825},"Condition 3 : La parité ajustée à l'objectif",{"type":29,"tag":1080,"props":4827,"children":4828},{},[4829,4839,4849],{"type":29,"tag":1084,"props":4830,"children":4831},{},[4832,4837],{"type":29,"tag":65,"props":4833,"children":4834},{},[4835],{"type":35,"value":4836},"Objectif qualité",{"type":35,"value":4838}," : deux développeurs de niveau similaire, l'un challenge l'autre, la qualité est le produit des deux regards",{"type":29,"tag":1084,"props":4840,"children":4841},{},[4842,4847],{"type":29,"tag":65,"props":4843,"children":4844},{},[4845],{"type":35,"value":4846},"Objectif formation",{"type":35,"value":4848}," : un senior + un junior avec intention pédagogique explicite, le senior explique ses raisonnements, le junior pose des questions sans être jugé",{"type":29,"tag":1084,"props":4850,"children":4851},{},[4852,4857],{"type":29,"tag":65,"props":4853,"children":4854},{},[4855],{"type":35,"value":4856},"Objectif connaissance métier",{"type":35,"value":4858}," : un développeur qui connaît le code + un développeur qui connaît le métier, le knowledge sharing est bidirectionnel",{"type":29,"tag":116,"props":4860,"children":4862},{"id":4861},"condition-4-la-durée-et-le-rythme",[4863],{"type":35,"value":4864},"Condition 4 : La durée et le rythme",{"type":29,"tag":37,"props":4866,"children":4867},{},[4868],{"type":35,"value":4869},"Sessions recommandées : 90 à 120 minutes maximum par bloc, avec une pause de 15 minutes. Maximum 4 heures de pair programming par jour pour une personne. Au-delà, la qualité baisse et la fatigue s'accumule.",{"type":29,"tag":76,"props":4871,"children":4872},{},[],{"type":29,"tag":80,"props":4874,"children":4876},{"id":4875},"les-3-formats",[4877],{"type":35,"value":4878},"Les 3 formats",{"type":29,"tag":37,"props":4880,"children":4881},{},[4882,4887],{"type":29,"tag":65,"props":4883,"children":4884},{},[4885],{"type":35,"value":4886},"Driver/Navigator (classique)",{"type":35,"value":4888}," : un développeur code, l'autre navigue. Rotation toutes les 25-30 minutes. Format le plus connu, le plus polyvalent.",{"type":29,"tag":37,"props":4890,"children":4891},{},[4892,4897],{"type":29,"tag":65,"props":4893,"children":4894},{},[4895],{"type":35,"value":4896},"Ping-Pong (TDD)",{"type":35,"value":4898}," : développeur A écrit un test qui échoue, développeur B écrit le code minimum pour le faire passer, développeur A écrit le prochain test. Particulièrement efficace pour ancrer le TDD dans les habitudes de l'équipe, et pour rendre le TDD moins aride pour les développeurs qui résistent à l'écriture de tests.",{"type":29,"tag":37,"props":4900,"children":4901},{},[4902,4907],{"type":29,"tag":65,"props":4903,"children":4904},{},[4905],{"type":35,"value":4906},"Mob programming (Ensemble)",{"type":35,"value":4908}," : l'équipe entière (3 à 6 personnes) travaille sur le même problème avec un seul clavier. Un driver, le reste navigue. Rotation toutes les 7-15 minutes. Très efficace pour les décisions d'architecture et l'onboarding accéléré, coûteux en temps d'équipe.",{"type":29,"tag":76,"props":4910,"children":4911},{},[],{"type":29,"tag":80,"props":4913,"children":4915},{"id":4914},"comment-lintroduire-progressivement-sans-résistance",[4916],{"type":35,"value":4917},"Comment l'introduire progressivement sans résistance",{"type":29,"tag":37,"props":4919,"children":4920},{},[4921,4926],{"type":29,"tag":65,"props":4922,"children":4923},{},[4924],{"type":35,"value":4925},"Semaine 1-2",{"type":35,"value":4927}," : proposition volontaire. \"Si quelqu'un veut essayer le pair programming sur sa prochaine story complexe, voilà comment ça fonctionne.\" Trouver 2 volontaires enthousiastes.",{"type":29,"tag":37,"props":4929,"children":4930},{},[4931,4936],{"type":29,"tag":65,"props":4932,"children":4933},{},[4934],{"type":35,"value":4935},"Semaine 3-4",{"type":35,"value":4937}," : débrief public. Partager les retours des premiers pairs en rétrospective. Ne pas idéaliser, partager les difficultés aussi.",{"type":29,"tag":37,"props":4939,"children":4940},{},[4941,4946,4948,4954],{"type":29,"tag":65,"props":4942,"children":4943},{},[4944],{"type":35,"value":4945},"Mois 2",{"type":35,"value":4947}," : intégrer dans la ",{"type":29,"tag":48,"props":4949,"children":4951},{"href":4950},"/fr/dette-technique/definition-of-done-qualite",[4952],{"type":35,"value":4953},"DoD",{"type":35,"value":4955}," pour les stories complexes (score > M en sizing). Pas pour toutes les stories.",{"type":29,"tag":37,"props":4957,"children":4958},{},[4959,4964,4966,4972],{"type":29,"tag":65,"props":4960,"children":4961},{},[4962],{"type":35,"value":4963},"Mois 3+",{"type":35,"value":4965}," : laisser l'équipe définir ses propres règles sur quand pairer. Les équipes qui ont le contrôle sur leur pratique l'adoptent plus durablement que celles qui la subissent. Le pair programming s'intègre naturellement dans les ",{"type":29,"tag":48,"props":4967,"children":4969},{"href":4968},"/fr/management/engineering-culture-rituels",[4970],{"type":35,"value":4971},"rituels de culture engineering",{"type":35,"value":342},{"type":29,"tag":76,"props":4974,"children":4975},{},[],{"type":29,"tag":80,"props":4977,"children":4979},{"id":4978},"faq-sur-le-pair-programming",[4980],{"type":35,"value":4981},"FAQ sur le pair programming",{"type":29,"tag":381,"props":4983,"children":4984},{},[4985,4990],{"type":29,"tag":385,"props":4986,"children":4987},{},[4988],{"type":35,"value":4989},"1. Le pair programming est-il compatible avec le télétravail ?",{"type":29,"tag":37,"props":4991,"children":4992},{},[4993],{"type":35,"value":4994},"Oui, avec les bons outils. VS Code Live Share, JetBrains Code With Me, et Tuple sont conçus pour le pair programming à distance. La qualité est légèrement inférieure à l'in-person (plus de latence dans la communication) mais tout à fait viable. La règle : pas de pair programming à distance sur des connexions \u003C 10 Mbps ou avec des outils de visioconférence trop lourds.",{"type":29,"tag":381,"props":4996,"children":4997},{},[4998,5003],{"type":29,"tag":385,"props":4999,"children":5000},{},[5001],{"type":35,"value":5002},"2. Comment gérer le pair programming avec des développeurs introvertis ?",{"type":29,"tag":37,"props":5004,"children":5005},{},[5006],{"type":35,"value":5007},"Le pair programming intense et continu est épuisant pour les introvertis. Solution : sessions de 90 minutes maximum, avec des blocs de travail solo entre les sessions. Le format ping-pong TDD fonctionne souvent mieux que le driver/navigator pour les introvertis : les rôles sont clairs, alternés, et le focus est sur le code, pas sur la conversation.",{"type":29,"tag":381,"props":5009,"children":5010},{},[5011,5016],{"type":29,"tag":385,"props":5012,"children":5013},{},[5014],{"type":35,"value":5015},"3. Faut-il mesurer le ROI du pair programming dans notre équipe ?",{"type":29,"tag":37,"props":5017,"children":5018},{},[5019],{"type":35,"value":5020},"Oui, et c'est simple. Mesurer sur 2 mois : le taux de bugs sur les stories développées en pair vs solo, et le cycle time des stories complexes. Si le taux de bugs baisse significativement (> 15%), le ROI est positif même avec un overhead de temps modéré. Sur l'équipe bancaire que j'ai mentionnée, la réduction du temps d'onboarding de 8 à 4 semaines représentait seule 20 000€ d'économie par recrue.",{"type":29,"tag":381,"props":5022,"children":5023},{},[5024,5029],{"type":29,"tag":385,"props":5025,"children":5026},{},[5027],{"type":35,"value":5028},"4. Le pair programming remplace-t-il la code review ?",{"type":29,"tag":37,"props":5030,"children":5031},{},[5032,5034,5039],{"type":35,"value":5033},"Non. Le pair programming réduit le besoin de review approfondie (le code a déjà eu un second regard) mais ne la remplace pas. Une ",{"type":29,"tag":48,"props":5035,"children":5036},{"href":2117},[5037],{"type":35,"value":5038},"code review",{"type":35,"value":5040}," asynchrone reste nécessaire pour : la cohérence avec les standards de l'équipe, les aspects de sécurité, et le regard externe d'un développeur non impliqué dans la session.",{"type":29,"tag":381,"props":5042,"children":5043},{},[5044,5049],{"type":29,"tag":385,"props":5045,"children":5046},{},[5047],{"type":35,"value":5048},"5. Comment justifier le pair programming au management qui voit \"deux développeurs sur un seul clavier\" ?",{"type":29,"tag":37,"props":5050,"children":5051},{},[5052],{"type":35,"value":5053},"Le même argument que pour les tests : le coût de corriger un bug en production est 10 à 100 fois le coût de le détecter pendant le développement. 15% de temps en plus pendant le développement pour 15% de défauts en moins, c'est un ROI positif sur la durée. Je propose un pilote de 6 semaines avec mesure des métriques de qualité avant/après : les chiffres parlent d'eux-mêmes.",{"type":29,"tag":76,"props":5055,"children":5056},{},[],{"type":29,"tag":176,"props":5058,"children":5059},{"cta":452,"href":453,"title":454,"type":455},[5060],{"type":29,"tag":37,"props":5061,"children":5062},{},[5063],{"type":35,"value":5064},"L'assessment évalue vos pratiques de collaboration et de qualité, incluant les revues de code et les pratiques de développement collaboratif. Score de maturité et plan d'action sur 90 jours.",{"title":8,"searchDepth":463,"depth":463,"links":5066},[5067,5068,5069,5075,5076,5077],{"id":4615,"depth":463,"text":4618},{"id":4677,"depth":463,"text":4680},{"id":4743,"depth":463,"text":4746,"children":5070},[5071,5072,5073,5074],{"id":4749,"depth":469,"text":4752},{"id":4806,"depth":469,"text":4809},{"id":4822,"depth":469,"text":4825},{"id":4861,"depth":469,"text":4864},{"id":4875,"depth":463,"text":4878},{"id":4914,"depth":463,"text":4917},{"id":4978,"depth":463,"text":4981},"content:fr:dette-technique:pair-programming-roi-conditions.md","fr/dette-technique/pair-programming-roi-conditions.md","fr/dette-technique/pair-programming-roi-conditions",{"_path":5082,"_dir":484,"_draft":7,"_partial":7,"_locale":8,"title":5083,"description":5084,"id":5085,"date":5086,"listed":13,"nocomments":7,"hidden":7,"categories":5087,"tags":5088,"--cover":5093,"readingTime":5094,"body":5098,"_type":476,"_id":9901,"_source":478,"_file":9902,"_stem":9903,"_extension":481},"/fr/architecture-craft/dependency-inversion-pratique","Dependency Inversion Principle : 3 exemples concrets","Le DIP est le principe SOLID le plus mal compris. Pas un pattern de conception — une règle sur la direction des dépendances. Trois implémentations dans trois langages.",30,"2026-03-13",[484],[5089,5090,5091,5092],"SOLID","Dependency Inversion","Architecture","Clean Code","covers/articles/dependency-inversion-principe.jpg",{"text":497,"minutes":5095,"time":5096,"words":5097},7.155,429300,1431,{"type":26,"children":5099,"toc":9892},[5100,5105,5110,5115,5120,5123,5129,5142,5147,5518,5526,5572,5575,5581,5625,5633,5638,5641,5647,6720,6728,7221,7230,7233,7239,8730,8740,8743,8749,9674,9692,9695,9701,9709,9727,9735,9753,9771,9774,9780,9793,9806,9819,9840,9877,9880,9888],{"type":29,"tag":30,"props":5101,"children":5103},{"id":5102},"dependency-inversion-principle-3-exemples-concrets",[5104],{"type":35,"value":5083},{"type":29,"tag":37,"props":5106,"children":5107},{},[5108],{"type":35,"value":5109},"Chez un client dans le secteur du retail en ligne que j'accompagnais (20 développeurs, 8 services backend), la suite de tests prenait 18 minutes à s'exécuter. Pas parce que les tests étaient lents. Parce que chaque test unitaire démarrait une vraie base de données PostgreSQL, un vrai serveur Redis, et appelait le vrai Sendgrid.",{"type":29,"tag":37,"props":5111,"children":5112},{},[5113],{"type":35,"value":5114},"Ce n'était pas un problème de tests. C'était un problème d'architecture : les modules métier dépendaient directement des implémentations concrètes d'infrastructure.",{"type":29,"tag":37,"props":5116,"children":5117},{},[5118],{"type":35,"value":5119},"Après avoir introduit le Dependency Inversion Principle sur les 8 services les plus critiques, la suite de tests est passée à 3 minutes. La couverture de tests a augmenté de 35% à 72% en 3 mois. Pas parce que les développeurs avaient soudain envie d'écrire des tests, mais parce que les tests étaient devenus faciles à écrire.",{"type":29,"tag":76,"props":5121,"children":5122},{},[],{"type":29,"tag":80,"props":5124,"children":5126},{"id":5125},"le-problème-la-dépendance-directe",[5127],{"type":35,"value":5128},"Le problème : la dépendance directe",{"type":29,"tag":37,"props":5130,"children":5131},{},[5132,5134,5140],{"type":35,"value":5133},"Robert C. Martin (Uncle Bob) a formulé le DIP en 1996 dans ses travaux sur les principes SOLID : \"Les modules de haut niveau ne doivent pas dépendre des modules de bas niveau. Les deux doivent dépendre d'abstractions.\" C'est la règle de dépendance au cœur de la ",{"type":29,"tag":48,"props":5135,"children":5137},{"href":5136},"/fr/architecture-craft/clean-architecture-3-regles",[5138],{"type":35,"value":5139},"Clean Architecture",{"type":35,"value":5141}," : les flèches de dépendance doivent toujours pointer vers l'intérieur, vers le domaine métier.",{"type":29,"tag":37,"props":5143,"children":5144},{},[5145],{"type":35,"value":5146},"En pratique, la quasi-totalité des codebases sans discipline architecturale viole ce principe :",{"type":29,"tag":651,"props":5148,"children":5150},{"code":5149,"language":2202,"meta":8,"className":2200,"style":8},"# Violation du DIP — le module de haut niveau dépend du module de bas niveau\n\nclass OrderService:\n    def __init__(self):\n        self.db = PostgreSQLDatabase(host=\"localhost\", port=5432)  # dépendance directe\n        self.email = SendgridEmailClient(api_key=\"...\")              # dépendance directe\n\n    def create_order(self, order_data):\n        order_id = self.db.save(order_data)\n        self.email.send_confirmation(order_data[\"email\"], order_id)\n        return order_id\n",[5151],{"type":29,"tag":565,"props":5152,"children":5153},{"__ignoreMap":8},[5154,5162,5169,5189,5218,5293,5345,5352,5388,5438,5504],{"type":29,"tag":901,"props":5155,"children":5156},{"class":903,"line":904},[5157],{"type":29,"tag":901,"props":5158,"children":5159},{"style":908},[5160],{"type":35,"value":5161},"# Violation du DIP — le module de haut niveau dépend du module de bas niveau\n",{"type":29,"tag":901,"props":5163,"children":5164},{"class":903,"line":463},[5165],{"type":29,"tag":901,"props":5166,"children":5167},{"emptyLinePlaceholder":13},[5168],{"type":35,"value":974},{"type":29,"tag":901,"props":5170,"children":5171},{"class":903,"line":469},[5172,5177,5183],{"type":29,"tag":901,"props":5173,"children":5174},{"style":917},[5175],{"type":35,"value":5176},"class",{"type":29,"tag":901,"props":5178,"children":5180},{"style":5179},"--shiki-default:#E5C890;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[5181],{"type":35,"value":5182}," OrderService",{"type":29,"tag":901,"props":5184,"children":5186},{"style":5185},"--shiki-default:#949CBB;--shiki-dark:#E1E4E8",[5187],{"type":35,"value":5188},":\n",{"type":29,"tag":901,"props":5190,"children":5191},{"class":903,"line":968},[5192,5197,5203,5207,5213],{"type":29,"tag":901,"props":5193,"children":5194},{"style":917},[5195],{"type":35,"value":5196},"    def",{"type":29,"tag":901,"props":5198,"children":5200},{"style":5199},"--shiki-default:#99D1DB;--shiki-default-font-style:italic;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit",[5201],{"type":35,"value":5202}," __init__",{"type":29,"tag":901,"props":5204,"children":5205},{"style":5185},[5206],{"type":35,"value":3080},{"type":29,"tag":901,"props":5208,"children":5210},{"style":5209},"--shiki-default:#E78284;--shiki-default-font-style:italic;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit",[5211],{"type":35,"value":5212},"self",{"type":29,"tag":901,"props":5214,"children":5215},{"style":5185},[5216],{"type":35,"value":5217},"):\n",{"type":29,"tag":901,"props":5219,"children":5220},{"class":903,"line":977},[5221,5227,5231,5236,5240,5246,5250,5256,5260,5265,5269,5274,5278,5284,5288],{"type":29,"tag":901,"props":5222,"children":5224},{"style":5223},"--shiki-default:#E78284;--shiki-default-font-style:italic;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit",[5225],{"type":35,"value":5226},"        self",{"type":29,"tag":901,"props":5228,"children":5229},{"style":5185},[5230],{"type":35,"value":342},{"type":29,"tag":901,"props":5232,"children":5233},{"style":923},[5234],{"type":35,"value":5235},"db ",{"type":29,"tag":901,"props":5237,"children":5238},{"style":947},[5239],{"type":35,"value":2227},{"type":29,"tag":901,"props":5241,"children":5243},{"style":5242},"--shiki-default:#8CAAEE;--shiki-dark:#E1E4E8",[5244],{"type":35,"value":5245}," PostgreSQLDatabase",{"type":29,"tag":901,"props":5247,"children":5248},{"style":5185},[5249],{"type":35,"value":3080},{"type":29,"tag":901,"props":5251,"children":5253},{"style":5252},"--shiki-default:#EA999C;--shiki-default-font-style:italic;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit",[5254],{"type":35,"value":5255},"host",{"type":29,"tag":901,"props":5257,"children":5258},{"style":947},[5259],{"type":35,"value":2227},{"type":29,"tag":901,"props":5261,"children":5262},{"style":2236},[5263],{"type":35,"value":5264},"\"localhost\"",{"type":29,"tag":901,"props":5266,"children":5267},{"style":5185},[5268],{"type":35,"value":3663},{"type":29,"tag":901,"props":5270,"children":5271},{"style":5252},[5272],{"type":35,"value":5273}," port",{"type":29,"tag":901,"props":5275,"children":5276},{"style":947},[5277],{"type":35,"value":2227},{"type":29,"tag":901,"props":5279,"children":5281},{"style":5280},"--shiki-default:#EF9F76;--shiki-dark:#79B8FF",[5282],{"type":35,"value":5283},"5432",{"type":29,"tag":901,"props":5285,"children":5286},{"style":5185},[5287],{"type":35,"value":2881},{"type":29,"tag":901,"props":5289,"children":5290},{"style":908},[5291],{"type":35,"value":5292},"  # dépendance directe\n",{"type":29,"tag":901,"props":5294,"children":5295},{"class":903,"line":986},[5296,5300,5304,5309,5313,5318,5322,5327,5331,5336,5340],{"type":29,"tag":901,"props":5297,"children":5298},{"style":5223},[5299],{"type":35,"value":5226},{"type":29,"tag":901,"props":5301,"children":5302},{"style":5185},[5303],{"type":35,"value":342},{"type":29,"tag":901,"props":5305,"children":5306},{"style":923},[5307],{"type":35,"value":5308},"email ",{"type":29,"tag":901,"props":5310,"children":5311},{"style":947},[5312],{"type":35,"value":2227},{"type":29,"tag":901,"props":5314,"children":5315},{"style":5242},[5316],{"type":35,"value":5317}," SendgridEmailClient",{"type":29,"tag":901,"props":5319,"children":5320},{"style":5185},[5321],{"type":35,"value":3080},{"type":29,"tag":901,"props":5323,"children":5324},{"style":5252},[5325],{"type":35,"value":5326},"api_key",{"type":29,"tag":901,"props":5328,"children":5329},{"style":947},[5330],{"type":35,"value":2227},{"type":29,"tag":901,"props":5332,"children":5333},{"style":2236},[5334],{"type":35,"value":5335},"\"...\"",{"type":29,"tag":901,"props":5337,"children":5338},{"style":5185},[5339],{"type":35,"value":2881},{"type":29,"tag":901,"props":5341,"children":5342},{"style":908},[5343],{"type":35,"value":5344},"              # dépendance directe\n",{"type":29,"tag":901,"props":5346,"children":5347},{"class":903,"line":1007},[5348],{"type":29,"tag":901,"props":5349,"children":5350},{"emptyLinePlaceholder":13},[5351],{"type":35,"value":974},{"type":29,"tag":901,"props":5353,"children":5355},{"class":903,"line":5354},8,[5356,5360,5366,5370,5374,5378,5384],{"type":29,"tag":901,"props":5357,"children":5358},{"style":917},[5359],{"type":35,"value":5196},{"type":29,"tag":901,"props":5361,"children":5363},{"style":5362},"--shiki-default:#8CAAEE;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[5364],{"type":35,"value":5365}," create_order",{"type":29,"tag":901,"props":5367,"children":5368},{"style":5185},[5369],{"type":35,"value":3080},{"type":29,"tag":901,"props":5371,"children":5372},{"style":5209},[5373],{"type":35,"value":5212},{"type":29,"tag":901,"props":5375,"children":5376},{"style":5185},[5377],{"type":35,"value":3663},{"type":29,"tag":901,"props":5379,"children":5381},{"style":5380},"--shiki-default:#EA999C;--shiki-default-font-style:italic;--shiki-dark:#E1E4E8;--shiki-dark-font-style:inherit",[5382],{"type":35,"value":5383}," order_data",{"type":29,"tag":901,"props":5385,"children":5386},{"style":5185},[5387],{"type":35,"value":5217},{"type":29,"tag":901,"props":5389,"children":5391},{"class":903,"line":5390},9,[5392,5397,5401,5406,5410,5415,5419,5424,5428,5433],{"type":29,"tag":901,"props":5393,"children":5394},{"style":923},[5395],{"type":35,"value":5396},"        order_id ",{"type":29,"tag":901,"props":5398,"children":5399},{"style":947},[5400],{"type":35,"value":2227},{"type":29,"tag":901,"props":5402,"children":5403},{"style":5223},[5404],{"type":35,"value":5405}," self",{"type":29,"tag":901,"props":5407,"children":5408},{"style":5185},[5409],{"type":35,"value":342},{"type":29,"tag":901,"props":5411,"children":5412},{"style":923},[5413],{"type":35,"value":5414},"db",{"type":29,"tag":901,"props":5416,"children":5417},{"style":5185},[5418],{"type":35,"value":342},{"type":29,"tag":901,"props":5420,"children":5421},{"style":5242},[5422],{"type":35,"value":5423},"save",{"type":29,"tag":901,"props":5425,"children":5426},{"style":5185},[5427],{"type":35,"value":3080},{"type":29,"tag":901,"props":5429,"children":5430},{"style":923},[5431],{"type":35,"value":5432},"order_data",{"type":29,"tag":901,"props":5434,"children":5435},{"style":5185},[5436],{"type":35,"value":5437},")\n",{"type":29,"tag":901,"props":5439,"children":5441},{"class":903,"line":5440},10,[5442,5446,5450,5454,5458,5463,5467,5471,5476,5481,5486,5490,5495,5500],{"type":29,"tag":901,"props":5443,"children":5444},{"style":5223},[5445],{"type":35,"value":5226},{"type":29,"tag":901,"props":5447,"children":5448},{"style":5185},[5449],{"type":35,"value":342},{"type":29,"tag":901,"props":5451,"children":5452},{"style":923},[5453],{"type":35,"value":2250},{"type":29,"tag":901,"props":5455,"children":5456},{"style":5185},[5457],{"type":35,"value":342},{"type":29,"tag":901,"props":5459,"children":5460},{"style":5242},[5461],{"type":35,"value":5462},"send_confirmation",{"type":29,"tag":901,"props":5464,"children":5465},{"style":5185},[5466],{"type":35,"value":3080},{"type":29,"tag":901,"props":5468,"children":5469},{"style":5380},[5470],{"type":35,"value":5432},{"type":29,"tag":901,"props":5472,"children":5473},{"style":5185},[5474],{"type":35,"value":5475},"[",{"type":29,"tag":901,"props":5477,"children":5478},{"style":2236},[5479],{"type":35,"value":5480},"\"",{"type":29,"tag":901,"props":5482,"children":5484},{"style":5483},"--shiki-default:#A6D189;--shiki-default-font-style:italic;--shiki-dark:#9ECBFF;--shiki-dark-font-style:inherit",[5485],{"type":35,"value":2250},{"type":29,"tag":901,"props":5487,"children":5488},{"style":2236},[5489],{"type":35,"value":5480},{"type":29,"tag":901,"props":5491,"children":5492},{"style":5185},[5493],{"type":35,"value":5494},"],",{"type":29,"tag":901,"props":5496,"children":5497},{"style":923},[5498],{"type":35,"value":5499}," order_id",{"type":29,"tag":901,"props":5501,"children":5502},{"style":5185},[5503],{"type":35,"value":5437},{"type":29,"tag":901,"props":5505,"children":5507},{"class":903,"line":5506},11,[5508,5513],{"type":29,"tag":901,"props":5509,"children":5510},{"style":917},[5511],{"type":35,"value":5512},"        return",{"type":29,"tag":901,"props":5514,"children":5515},{"style":923},[5516],{"type":35,"value":5517}," order_id\n",{"type":29,"tag":37,"props":5519,"children":5520},{},[5521],{"type":29,"tag":65,"props":5522,"children":5523},{},[5524],{"type":35,"value":5525},"Ce que ça coûte concrètement :",{"type":29,"tag":1080,"props":5527,"children":5528},{},[5529,5542,5552,5562],{"type":29,"tag":1084,"props":5530,"children":5531},{},[5532,5534,5540],{"type":35,"value":5533},"Impossible de tester ",{"type":29,"tag":565,"props":5535,"children":5537},{"className":5536},[],[5538],{"type":35,"value":5539},"OrderService",{"type":35,"value":5541}," sans une vraie base de données PostgreSQL et un compte Sendgrid",{"type":29,"tag":1084,"props":5543,"children":5544},{},[5545,5547],{"type":35,"value":5546},"Changer de base de données oblige à modifier ",{"type":29,"tag":565,"props":5548,"children":5550},{"className":5549},[],[5551],{"type":35,"value":5539},{"type":29,"tag":1084,"props":5553,"children":5554},{},[5555,5557],{"type":35,"value":5556},"Changer d'email provider oblige à modifier ",{"type":29,"tag":565,"props":5558,"children":5560},{"className":5559},[],[5561],{"type":35,"value":5539},{"type":29,"tag":1084,"props":5563,"children":5564},{},[5565,5570],{"type":29,"tag":565,"props":5566,"children":5568},{"className":5567},[],[5569],{"type":35,"value":5539},{"type":35,"value":5571}," connaît des détails d'implémentation (host, port, api_key) qui n'ont rien à voir avec la logique métier de commande",{"type":29,"tag":76,"props":5573,"children":5574},{},[],{"type":29,"tag":80,"props":5576,"children":5578},{"id":5577},"le-principe-inverser-la-direction-des-dépendances",[5579],{"type":35,"value":5580},"Le principe : inverser la direction des dépendances",{"type":29,"tag":37,"props":5582,"children":5583},{},[5584,5586,5591,5593,5599,5601,5607,5609,5615,5617,5623],{"type":35,"value":5585},"La solution DIP : ",{"type":29,"tag":565,"props":5587,"children":5589},{"className":5588},[],[5590],{"type":35,"value":5539},{"type":35,"value":5592}," ne dépend pas de ",{"type":29,"tag":565,"props":5594,"children":5596},{"className":5595},[],[5597],{"type":35,"value":5598},"PostgreSQLDatabase",{"type":35,"value":5600}," ni de ",{"type":29,"tag":565,"props":5602,"children":5604},{"className":5603},[],[5605],{"type":35,"value":5606},"SendgridEmailClient",{"type":35,"value":5608},". Il dépend d'abstractions (",{"type":29,"tag":565,"props":5610,"children":5612},{"className":5611},[],[5613],{"type":35,"value":5614},"OrderRepository",{"type":35,"value":5616},", ",{"type":29,"tag":565,"props":5618,"children":5620},{"className":5619},[],[5621],{"type":35,"value":5622},"EmailNotifier",{"type":35,"value":5624},") que les implémentations concrètes respectent.",{"type":29,"tag":651,"props":5626,"children":5628},{"code":5627},"Sans DIP :\nOrderService → PostgreSQLDatabase\nOrderService → SendgridEmailClient\n\nAvec DIP :\nOrderService → OrderRepository (abstraction) ← PostgreSQLOrderRepository (implémentation)\nOrderService → EmailNotifier (abstraction)   ← SendgridEmailNotifier (implémentation)\n",[5629],{"type":29,"tag":565,"props":5630,"children":5631},{"__ignoreMap":8},[5632],{"type":35,"value":5627},{"type":29,"tag":37,"props":5634,"children":5635},{},[5636],{"type":35,"value":5637},"La flèche s'inverse : l'implémentation concrète dépend de l'abstraction, pas l'inverse.",{"type":29,"tag":76,"props":5639,"children":5640},{},[],{"type":29,"tag":80,"props":5642,"children":5644},{"id":5643},"exemple-1-python-injection-par-constructeur",[5645],{"type":35,"value":5646},"Exemple 1 : Python, injection par constructeur",{"type":29,"tag":651,"props":5648,"children":5650},{"code":5649,"language":2202,"meta":8,"className":2200,"style":8},"from abc import ABC, abstractmethod\n\nclass OrderRepository(ABC):\n    @abstractmethod\n    def save(self, order_data: dict) -> str:\n        pass\n\nclass EmailNotifier(ABC):\n    @abstractmethod\n    def send_confirmation(self, email: str, order_id: str) -> None:\n        pass\n\n# Le module de haut niveau — dépend uniquement des abstractions\nclass OrderService:\n    def __init__(self, repository: OrderRepository, notifier: EmailNotifier):\n        self.repository = repository\n        self.notifier = notifier\n\n    def create_order(self, order_data: dict) -> str:\n        order_id = self.repository.save(order_data)\n        self.notifier.send_confirmation(order_data[\"email\"], order_id)\n        return order_id\n\n# Les implémentations concrètes\nclass PostgreSQLOrderRepository(OrderRepository):\n    def save(self, order_data: dict) -> str:\n        return self.db.execute(\"INSERT INTO orders ...\", order_data)\n\nclass SendgridEmailNotifier(EmailNotifier):\n    def send_confirmation(self, email: str, order_id: str) -> None:\n        self.client.send(to=email, template=\"order_confirmation\", data={\"order_id\": order_id})\n\n# Composition à la racine de l'application\ndef create_order_service():\n    repository = PostgreSQLOrderRepository(db)\n    notifier = SendgridEmailNotifier(api_key=os.getenv(\"SENDGRID_KEY\"))\n    return OrderService(repository, notifier)\n",[5651],{"type":29,"tag":565,"props":5652,"children":5653},{"__ignoreMap":8},[5654,5687,5694,5719,5728,5785,5793,5800,5824,5831,5902,5909,5917,5926,5942,6001,6027,6053,6061,6113,6158,6219,6231,6239,6248,6273,6325,6375,6383,6408,6475,6570,6577,6586,6604,6632,6688],{"type":29,"tag":901,"props":5655,"children":5656},{"class":903,"line":904},[5657,5662,5667,5672,5678,5682],{"type":29,"tag":901,"props":5658,"children":5659},{"style":917},[5660],{"type":35,"value":5661},"from",{"type":29,"tag":901,"props":5663,"children":5664},{"style":923},[5665],{"type":35,"value":5666}," abc ",{"type":29,"tag":901,"props":5668,"children":5669},{"style":917},[5670],{"type":35,"value":5671},"import",{"type":29,"tag":901,"props":5673,"children":5675},{"style":5674},"--shiki-default:#C6D0F5;--shiki-dark:#79B8FF",[5676],{"type":35,"value":5677}," ABC",{"type":29,"tag":901,"props":5679,"children":5680},{"style":5185},[5681],{"type":35,"value":3663},{"type":29,"tag":901,"props":5683,"children":5684},{"style":923},[5685],{"type":35,"value":5686}," abstractmethod\n",{"type":29,"tag":901,"props":5688,"children":5689},{"class":903,"line":463},[5690],{"type":29,"tag":901,"props":5691,"children":5692},{"emptyLinePlaceholder":13},[5693],{"type":35,"value":974},{"type":29,"tag":901,"props":5695,"children":5696},{"class":903,"line":469},[5697,5701,5706,5710,5715],{"type":29,"tag":901,"props":5698,"children":5699},{"style":917},[5700],{"type":35,"value":5176},{"type":29,"tag":901,"props":5702,"children":5703},{"style":5179},[5704],{"type":35,"value":5705}," OrderRepository",{"type":29,"tag":901,"props":5707,"children":5708},{"style":5185},[5709],{"type":35,"value":3080},{"type":29,"tag":901,"props":5711,"children":5712},{"style":5674},[5713],{"type":35,"value":5714},"ABC",{"type":29,"tag":901,"props":5716,"children":5717},{"style":5185},[5718],{"type":35,"value":5217},{"type":29,"tag":901,"props":5720,"children":5721},{"class":903,"line":968},[5722],{"type":29,"tag":901,"props":5723,"children":5725},{"style":5724},"--shiki-default:#EF9F76;--shiki-default-font-style:italic;--shiki-dark:#B392F0;--shiki-dark-font-style:inherit",[5726],{"type":35,"value":5727},"    @abstractmethod\n",{"type":29,"tag":901,"props":5729,"children":5730},{"class":903,"line":977},[5731,5735,5740,5744,5748,5752,5756,5761,5767,5771,5776,5781],{"type":29,"tag":901,"props":5732,"children":5733},{"style":917},[5734],{"type":35,"value":5196},{"type":29,"tag":901,"props":5736,"children":5737},{"style":5362},[5738],{"type":35,"value":5739}," save",{"type":29,"tag":901,"props":5741,"children":5742},{"style":5185},[5743],{"type":35,"value":3080},{"type":29,"tag":901,"props":5745,"children":5746},{"style":5209},[5747],{"type":35,"value":5212},{"type":29,"tag":901,"props":5749,"children":5750},{"style":5185},[5751],{"type":35,"value":3663},{"type":29,"tag":901,"props":5753,"children":5754},{"style":5380},[5755],{"type":35,"value":5383},{"type":29,"tag":901,"props":5757,"children":5758},{"style":5185},[5759],{"type":35,"value":5760},":",{"type":29,"tag":901,"props":5762,"children":5764},{"style":5763},"--shiki-default:#EF9F76;--shiki-default-font-style:italic;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit",[5765],{"type":35,"value":5766}," dict",{"type":29,"tag":901,"props":5768,"children":5769},{"style":5185},[5770],{"type":35,"value":2881},{"type":29,"tag":901,"props":5772,"children":5773},{"style":5185},[5774],{"type":35,"value":5775}," ->",{"type":29,"tag":901,"props":5777,"children":5778},{"style":5763},[5779],{"type":35,"value":5780}," str",{"type":29,"tag":901,"props":5782,"children":5783},{"style":5185},[5784],{"type":35,"value":5188},{"type":29,"tag":901,"props":5786,"children":5787},{"class":903,"line":986},[5788],{"type":29,"tag":901,"props":5789,"children":5790},{"style":917},[5791],{"type":35,"value":5792},"        pass\n",{"type":29,"tag":901,"props":5794,"children":5795},{"class":903,"line":1007},[5796],{"type":29,"tag":901,"props":5797,"children":5798},{"emptyLinePlaceholder":13},[5799],{"type":35,"value":974},{"type":29,"tag":901,"props":5801,"children":5802},{"class":903,"line":5354},[5803,5807,5812,5816,5820],{"type":29,"tag":901,"props":5804,"children":5805},{"style":917},[5806],{"type":35,"value":5176},{"type":29,"tag":901,"props":5808,"children":5809},{"style":5179},[5810],{"type":35,"value":5811}," EmailNotifier",{"type":29,"tag":901,"props":5813,"children":5814},{"style":5185},[5815],{"type":35,"value":3080},{"type":29,"tag":901,"props":5817,"children":5818},{"style":5674},[5819],{"type":35,"value":5714},{"type":29,"tag":901,"props":5821,"children":5822},{"style":5185},[5823],{"type":35,"value":5217},{"type":29,"tag":901,"props":5825,"children":5826},{"class":903,"line":5390},[5827],{"type":29,"tag":901,"props":5828,"children":5829},{"style":5724},[5830],{"type":35,"value":5727},{"type":29,"tag":901,"props":5832,"children":5833},{"class":903,"line":5440},[5834,5838,5843,5847,5851,5855,5860,5864,5868,5872,5876,5880,5884,5888,5892,5898],{"type":29,"tag":901,"props":5835,"children":5836},{"style":917},[5837],{"type":35,"value":5196},{"type":29,"tag":901,"props":5839,"children":5840},{"style":5362},[5841],{"type":35,"value":5842}," send_confirmation",{"type":29,"tag":901,"props":5844,"children":5845},{"style":5185},[5846],{"type":35,"value":3080},{"type":29,"tag":901,"props":5848,"children":5849},{"style":5209},[5850],{"type":35,"value":5212},{"type":29,"tag":901,"props":5852,"children":5853},{"style":5185},[5854],{"type":35,"value":3663},{"type":29,"tag":901,"props":5856,"children":5857},{"style":5380},[5858],{"type":35,"value":5859}," email",{"type":29,"tag":901,"props":5861,"children":5862},{"style":5185},[5863],{"type":35,"value":5760},{"type":29,"tag":901,"props":5865,"children":5866},{"style":5763},[5867],{"type":35,"value":5780},{"type":29,"tag":901,"props":5869,"children":5870},{"style":5185},[5871],{"type":35,"value":3663},{"type":29,"tag":901,"props":5873,"children":5874},{"style":5380},[5875],{"type":35,"value":5499},{"type":29,"tag":901,"props":5877,"children":5878},{"style":5185},[5879],{"type":35,"value":5760},{"type":29,"tag":901,"props":5881,"children":5882},{"style":5763},[5883],{"type":35,"value":5780},{"type":29,"tag":901,"props":5885,"children":5886},{"style":5185},[5887],{"type":35,"value":2881},{"type":29,"tag":901,"props":5889,"children":5890},{"style":5185},[5891],{"type":35,"value":5775},{"type":29,"tag":901,"props":5893,"children":5895},{"style":5894},"--shiki-default:#CA9EE6;--shiki-dark:#79B8FF",[5896],{"type":35,"value":5897}," None",{"type":29,"tag":901,"props":5899,"children":5900},{"style":5185},[5901],{"type":35,"value":5188},{"type":29,"tag":901,"props":5903,"children":5904},{"class":903,"line":5506},[5905],{"type":29,"tag":901,"props":5906,"children":5907},{"style":917},[5908],{"type":35,"value":5792},{"type":29,"tag":901,"props":5910,"children":5912},{"class":903,"line":5911},12,[5913],{"type":29,"tag":901,"props":5914,"children":5915},{"emptyLinePlaceholder":13},[5916],{"type":35,"value":974},{"type":29,"tag":901,"props":5918,"children":5920},{"class":903,"line":5919},13,[5921],{"type":29,"tag":901,"props":5922,"children":5923},{"style":908},[5924],{"type":35,"value":5925},"# Le module de haut niveau — dépend uniquement des abstractions\n",{"type":29,"tag":901,"props":5927,"children":5929},{"class":903,"line":5928},14,[5930,5934,5938],{"type":29,"tag":901,"props":5931,"children":5932},{"style":917},[5933],{"type":35,"value":5176},{"type":29,"tag":901,"props":5935,"children":5936},{"style":5179},[5937],{"type":35,"value":5182},{"type":29,"tag":901,"props":5939,"children":5940},{"style":5185},[5941],{"type":35,"value":5188},{"type":29,"tag":901,"props":5943,"children":5945},{"class":903,"line":5944},15,[5946,5950,5954,5958,5962,5966,5971,5975,5980,5984,5989,5993,5997],{"type":29,"tag":901,"props":5947,"children":5948},{"style":917},[5949],{"type":35,"value":5196},{"type":29,"tag":901,"props":5951,"children":5952},{"style":5199},[5953],{"type":35,"value":5202},{"type":29,"tag":901,"props":5955,"children":5956},{"style":5185},[5957],{"type":35,"value":3080},{"type":29,"tag":901,"props":5959,"children":5960},{"style":5209},[5961],{"type":35,"value":5212},{"type":29,"tag":901,"props":5963,"children":5964},{"style":5185},[5965],{"type":35,"value":3663},{"type":29,"tag":901,"props":5967,"children":5968},{"style":5380},[5969],{"type":35,"value":5970}," repository",{"type":29,"tag":901,"props":5972,"children":5973},{"style":5185},[5974],{"type":35,"value":5760},{"type":29,"tag":901,"props":5976,"children":5978},{"style":5977},"--shiki-default:#EA999C;--shiki-dark:#E1E4E8",[5979],{"type":35,"value":5705},{"type":29,"tag":901,"props":5981,"children":5982},{"style":5185},[5983],{"type":35,"value":3663},{"type":29,"tag":901,"props":5985,"children":5986},{"style":5380},[5987],{"type":35,"value":5988}," notifier",{"type":29,"tag":901,"props":5990,"children":5991},{"style":5185},[5992],{"type":35,"value":5760},{"type":29,"tag":901,"props":5994,"children":5995},{"style":5977},[5996],{"type":35,"value":5811},{"type":29,"tag":901,"props":5998,"children":5999},{"style":5185},[6000],{"type":35,"value":5217},{"type":29,"tag":901,"props":6002,"children":6004},{"class":903,"line":6003},16,[6005,6009,6013,6018,6022],{"type":29,"tag":901,"props":6006,"children":6007},{"style":5223},[6008],{"type":35,"value":5226},{"type":29,"tag":901,"props":6010,"children":6011},{"style":5185},[6012],{"type":35,"value":342},{"type":29,"tag":901,"props":6014,"children":6015},{"style":923},[6016],{"type":35,"value":6017},"repository ",{"type":29,"tag":901,"props":6019,"children":6020},{"style":947},[6021],{"type":35,"value":2227},{"type":29,"tag":901,"props":6023,"children":6024},{"style":923},[6025],{"type":35,"value":6026}," repository\n",{"type":29,"tag":901,"props":6028,"children":6030},{"class":903,"line":6029},17,[6031,6035,6039,6044,6048],{"type":29,"tag":901,"props":6032,"children":6033},{"style":5223},[6034],{"type":35,"value":5226},{"type":29,"tag":901,"props":6036,"children":6037},{"style":5185},[6038],{"type":35,"value":342},{"type":29,"tag":901,"props":6040,"children":6041},{"style":923},[6042],{"type":35,"value":6043},"notifier ",{"type":29,"tag":901,"props":6045,"children":6046},{"style":947},[6047],{"type":35,"value":2227},{"type":29,"tag":901,"props":6049,"children":6050},{"style":923},[6051],{"type":35,"value":6052}," notifier\n",{"type":29,"tag":901,"props":6054,"children":6056},{"class":903,"line":6055},18,[6057],{"type":29,"tag":901,"props":6058,"children":6059},{"emptyLinePlaceholder":13},[6060],{"type":35,"value":974},{"type":29,"tag":901,"props":6062,"children":6064},{"class":903,"line":6063},19,[6065,6069,6073,6077,6081,6085,6089,6093,6097,6101,6105,6109],{"type":29,"tag":901,"props":6066,"children":6067},{"style":917},[6068],{"type":35,"value":5196},{"type":29,"tag":901,"props":6070,"children":6071},{"style":5362},[6072],{"type":35,"value":5365},{"type":29,"tag":901,"props":6074,"children":6075},{"style":5185},[6076],{"type":35,"value":3080},{"type":29,"tag":901,"props":6078,"children":6079},{"style":5209},[6080],{"type":35,"value":5212},{"type":29,"tag":901,"props":6082,"children":6083},{"style":5185},[6084],{"type":35,"value":3663},{"type":29,"tag":901,"props":6086,"children":6087},{"style":5380},[6088],{"type":35,"value":5383},{"type":29,"tag":901,"props":6090,"children":6091},{"style":5185},[6092],{"type":35,"value":5760},{"type":29,"tag":901,"props":6094,"children":6095},{"style":5763},[6096],{"type":35,"value":5766},{"type":29,"tag":901,"props":6098,"children":6099},{"style":5185},[6100],{"type":35,"value":2881},{"type":29,"tag":901,"props":6102,"children":6103},{"style":5185},[6104],{"type":35,"value":5775},{"type":29,"tag":901,"props":6106,"children":6107},{"style":5763},[6108],{"type":35,"value":5780},{"type":29,"tag":901,"props":6110,"children":6111},{"style":5185},[6112],{"type":35,"value":5188},{"type":29,"tag":901,"props":6114,"children":6116},{"class":903,"line":6115},20,[6117,6121,6125,6129,6133,6138,6142,6146,6150,6154],{"type":29,"tag":901,"props":6118,"children":6119},{"style":923},[6120],{"type":35,"value":5396},{"type":29,"tag":901,"props":6122,"children":6123},{"style":947},[6124],{"type":35,"value":2227},{"type":29,"tag":901,"props":6126,"children":6127},{"style":5223},[6128],{"type":35,"value":5405},{"type":29,"tag":901,"props":6130,"children":6131},{"style":5185},[6132],{"type":35,"value":342},{"type":29,"tag":901,"props":6134,"children":6135},{"style":923},[6136],{"type":35,"value":6137},"repository",{"type":29,"tag":901,"props":6139,"children":6140},{"style":5185},[6141],{"type":35,"value":342},{"type":29,"tag":901,"props":6143,"children":6144},{"style":5242},[6145],{"type":35,"value":5423},{"type":29,"tag":901,"props":6147,"children":6148},{"style":5185},[6149],{"type":35,"value":3080},{"type":29,"tag":901,"props":6151,"children":6152},{"style":923},[6153],{"type":35,"value":5432},{"type":29,"tag":901,"props":6155,"children":6156},{"style":5185},[6157],{"type":35,"value":5437},{"type":29,"tag":901,"props":6159,"children":6161},{"class":903,"line":6160},21,[6162,6166,6170,6175,6179,6183,6187,6191,6195,6199,6203,6207,6211,6215],{"type":29,"tag":901,"props":6163,"children":6164},{"style":5223},[6165],{"type":35,"value":5226},{"type":29,"tag":901,"props":6167,"children":6168},{"style":5185},[6169],{"type":35,"value":342},{"type":29,"tag":901,"props":6171,"children":6172},{"style":923},[6173],{"type":35,"value":6174},"notifier",{"type":29,"tag":901,"props":6176,"children":6177},{"style":5185},[6178],{"type":35,"value":342},{"type":29,"tag":901,"props":6180,"children":6181},{"style":5242},[6182],{"type":35,"value":5462},{"type":29,"tag":901,"props":6184,"children":6185},{"style":5185},[6186],{"type":35,"value":3080},{"type":29,"tag":901,"props":6188,"children":6189},{"style":5380},[6190],{"type":35,"value":5432},{"type":29,"tag":901,"props":6192,"children":6193},{"style":5185},[6194],{"type":35,"value":5475},{"type":29,"tag":901,"props":6196,"children":6197},{"style":2236},[6198],{"type":35,"value":5480},{"type":29,"tag":901,"props":6200,"children":6201},{"style":5483},[6202],{"type":35,"value":2250},{"type":29,"tag":901,"props":6204,"children":6205},{"style":2236},[6206],{"type":35,"value":5480},{"type":29,"tag":901,"props":6208,"children":6209},{"style":5185},[6210],{"type":35,"value":5494},{"type":29,"tag":901,"props":6212,"children":6213},{"style":923},[6214],{"type":35,"value":5499},{"type":29,"tag":901,"props":6216,"children":6217},{"style":5185},[6218],{"type":35,"value":5437},{"type":29,"tag":901,"props":6220,"children":6222},{"class":903,"line":6221},22,[6223,6227],{"type":29,"tag":901,"props":6224,"children":6225},{"style":917},[6226],{"type":35,"value":5512},{"type":29,"tag":901,"props":6228,"children":6229},{"style":923},[6230],{"type":35,"value":5517},{"type":29,"tag":901,"props":6232,"children":6234},{"class":903,"line":6233},23,[6235],{"type":29,"tag":901,"props":6236,"children":6237},{"emptyLinePlaceholder":13},[6238],{"type":35,"value":974},{"type":29,"tag":901,"props":6240,"children":6242},{"class":903,"line":6241},24,[6243],{"type":29,"tag":901,"props":6244,"children":6245},{"style":908},[6246],{"type":35,"value":6247},"# Les implémentations concrètes\n",{"type":29,"tag":901,"props":6249,"children":6251},{"class":903,"line":6250},25,[6252,6256,6261,6265,6269],{"type":29,"tag":901,"props":6253,"children":6254},{"style":917},[6255],{"type":35,"value":5176},{"type":29,"tag":901,"props":6257,"children":6258},{"style":5179},[6259],{"type":35,"value":6260}," PostgreSQLOrderRepository",{"type":29,"tag":901,"props":6262,"children":6263},{"style":5185},[6264],{"type":35,"value":3080},{"type":29,"tag":901,"props":6266,"children":6267},{"style":5179},[6268],{"type":35,"value":5614},{"type":29,"tag":901,"props":6270,"children":6271},{"style":5185},[6272],{"type":35,"value":5217},{"type":29,"tag":901,"props":6274,"children":6276},{"class":903,"line":6275},26,[6277,6281,6285,6289,6293,6297,6301,6305,6309,6313,6317,6321],{"type":29,"tag":901,"props":6278,"children":6279},{"style":917},[6280],{"type":35,"value":5196},{"type":29,"tag":901,"props":6282,"children":6283},{"style":5362},[6284],{"type":35,"value":5739},{"type":29,"tag":901,"props":6286,"children":6287},{"style":5185},[6288],{"type":35,"value":3080},{"type":29,"tag":901,"props":6290,"children":6291},{"style":5209},[6292],{"type":35,"value":5212},{"type":29,"tag":901,"props":6294,"children":6295},{"style":5185},[6296],{"type":35,"value":3663},{"type":29,"tag":901,"props":6298,"children":6299},{"style":5380},[6300],{"type":35,"value":5383},{"type":29,"tag":901,"props":6302,"children":6303},{"style":5185},[6304],{"type":35,"value":5760},{"type":29,"tag":901,"props":6306,"children":6307},{"style":5763},[6308],{"type":35,"value":5766},{"type":29,"tag":901,"props":6310,"children":6311},{"style":5185},[6312],{"type":35,"value":2881},{"type":29,"tag":901,"props":6314,"children":6315},{"style":5185},[6316],{"type":35,"value":5775},{"type":29,"tag":901,"props":6318,"children":6319},{"style":5763},[6320],{"type":35,"value":5780},{"type":29,"tag":901,"props":6322,"children":6323},{"style":5185},[6324],{"type":35,"value":5188},{"type":29,"tag":901,"props":6326,"children":6328},{"class":903,"line":6327},27,[6329,6333,6337,6341,6345,6349,6354,6358,6363,6367,6371],{"type":29,"tag":901,"props":6330,"children":6331},{"style":917},[6332],{"type":35,"value":5512},{"type":29,"tag":901,"props":6334,"children":6335},{"style":5223},[6336],{"type":35,"value":5405},{"type":29,"tag":901,"props":6338,"children":6339},{"style":5185},[6340],{"type":35,"value":342},{"type":29,"tag":901,"props":6342,"children":6343},{"style":923},[6344],{"type":35,"value":5414},{"type":29,"tag":901,"props":6346,"children":6347},{"style":5185},[6348],{"type":35,"value":342},{"type":29,"tag":901,"props":6350,"children":6351},{"style":5242},[6352],{"type":35,"value":6353},"execute",{"type":29,"tag":901,"props":6355,"children":6356},{"style":5185},[6357],{"type":35,"value":3080},{"type":29,"tag":901,"props":6359,"children":6360},{"style":2236},[6361],{"type":35,"value":6362},"\"INSERT INTO orders ...\"",{"type":29,"tag":901,"props":6364,"children":6365},{"style":5185},[6366],{"type":35,"value":3663},{"type":29,"tag":901,"props":6368,"children":6369},{"style":923},[6370],{"type":35,"value":5383},{"type":29,"tag":901,"props":6372,"children":6373},{"style":5185},[6374],{"type":35,"value":5437},{"type":29,"tag":901,"props":6376,"children":6378},{"class":903,"line":6377},28,[6379],{"type":29,"tag":901,"props":6380,"children":6381},{"emptyLinePlaceholder":13},[6382],{"type":35,"value":974},{"type":29,"tag":901,"props":6384,"children":6386},{"class":903,"line":6385},29,[6387,6391,6396,6400,6404],{"type":29,"tag":901,"props":6388,"children":6389},{"style":917},[6390],{"type":35,"value":5176},{"type":29,"tag":901,"props":6392,"children":6393},{"style":5179},[6394],{"type":35,"value":6395}," SendgridEmailNotifier",{"type":29,"tag":901,"props":6397,"children":6398},{"style":5185},[6399],{"type":35,"value":3080},{"type":29,"tag":901,"props":6401,"children":6402},{"style":5179},[6403],{"type":35,"value":5622},{"type":29,"tag":901,"props":6405,"children":6406},{"style":5185},[6407],{"type":35,"value":5217},{"type":29,"tag":901,"props":6409,"children":6410},{"class":903,"line":5085},[6411,6415,6419,6423,6427,6431,6435,6439,6443,6447,6451,6455,6459,6463,6467,6471],{"type":29,"tag":901,"props":6412,"children":6413},{"style":917},[6414],{"type":35,"value":5196},{"type":29,"tag":901,"props":6416,"children":6417},{"style":5362},[6418],{"type":35,"value":5842},{"type":29,"tag":901,"props":6420,"children":6421},{"style":5185},[6422],{"type":35,"value":3080},{"type":29,"tag":901,"props":6424,"children":6425},{"style":5209},[6426],{"type":35,"value":5212},{"type":29,"tag":901,"props":6428,"children":6429},{"style":5185},[6430],{"type":35,"value":3663},{"type":29,"tag":901,"props":6432,"children":6433},{"style":5380},[6434],{"type":35,"value":5859},{"type":29,"tag":901,"props":6436,"children":6437},{"style":5185},[6438],{"type":35,"value":5760},{"type":29,"tag":901,"props":6440,"children":6441},{"style":5763},[6442],{"type":35,"value":5780},{"type":29,"tag":901,"props":6444,"children":6445},{"style":5185},[6446],{"type":35,"value":3663},{"type":29,"tag":901,"props":6448,"children":6449},{"style":5380},[6450],{"type":35,"value":5499},{"type":29,"tag":901,"props":6452,"children":6453},{"style":5185},[6454],{"type":35,"value":5760},{"type":29,"tag":901,"props":6456,"children":6457},{"style":5763},[6458],{"type":35,"value":5780},{"type":29,"tag":901,"props":6460,"children":6461},{"style":5185},[6462],{"type":35,"value":2881},{"type":29,"tag":901,"props":6464,"children":6465},{"style":5185},[6466],{"type":35,"value":5775},{"type":29,"tag":901,"props":6468,"children":6469},{"style":5894},[6470],{"type":35,"value":5897},{"type":29,"tag":901,"props":6472,"children":6473},{"style":5185},[6474],{"type":35,"value":5188},{"type":29,"tag":901,"props":6476,"children":6477},{"class":903,"line":4573},[6478,6482,6486,6491,6495,6500,6504,6509,6513,6517,6521,6526,6530,6535,6539,6544,6548,6552,6557,6561,6565],{"type":29,"tag":901,"props":6479,"children":6480},{"style":5223},[6481],{"type":35,"value":5226},{"type":29,"tag":901,"props":6483,"children":6484},{"style":5185},[6485],{"type":35,"value":342},{"type":29,"tag":901,"props":6487,"children":6488},{"style":923},[6489],{"type":35,"value":6490},"client",{"type":29,"tag":901,"props":6492,"children":6493},{"style":5185},[6494],{"type":35,"value":342},{"type":29,"tag":901,"props":6496,"children":6497},{"style":5242},[6498],{"type":35,"value":6499},"send",{"type":29,"tag":901,"props":6501,"children":6502},{"style":5185},[6503],{"type":35,"value":3080},{"type":29,"tag":901,"props":6505,"children":6506},{"style":5252},[6507],{"type":35,"value":6508},"to",{"type":29,"tag":901,"props":6510,"children":6511},{"style":947},[6512],{"type":35,"value":2227},{"type":29,"tag":901,"props":6514,"children":6515},{"style":923},[6516],{"type":35,"value":2250},{"type":29,"tag":901,"props":6518,"children":6519},{"style":5185},[6520],{"type":35,"value":3663},{"type":29,"tag":901,"props":6522,"children":6523},{"style":5252},[6524],{"type":35,"value":6525}," template",{"type":29,"tag":901,"props":6527,"children":6528},{"style":947},[6529],{"type":35,"value":2227},{"type":29,"tag":901,"props":6531,"children":6532},{"style":2236},[6533],{"type":35,"value":6534},"\"order_confirmation\"",{"type":29,"tag":901,"props":6536,"children":6537},{"style":5185},[6538],{"type":35,"value":3663},{"type":29,"tag":901,"props":6540,"children":6541},{"style":5252},[6542],{"type":35,"value":6543}," data",{"type":29,"tag":901,"props":6545,"children":6546},{"style":947},[6547],{"type":35,"value":2227},{"type":29,"tag":901,"props":6549,"children":6550},{"style":5185},[6551],{"type":35,"value":2245},{"type":29,"tag":901,"props":6553,"children":6554},{"style":2236},[6555],{"type":35,"value":6556},"\"order_id\"",{"type":29,"tag":901,"props":6558,"children":6559},{"style":5185},[6560],{"type":35,"value":5760},{"type":29,"tag":901,"props":6562,"children":6563},{"style":923},[6564],{"type":35,"value":5499},{"type":29,"tag":901,"props":6566,"children":6567},{"style":5185},[6568],{"type":35,"value":6569},"})\n",{"type":29,"tag":901,"props":6571,"children":6572},{"class":903,"line":4109},[6573],{"type":29,"tag":901,"props":6574,"children":6575},{"emptyLinePlaceholder":13},[6576],{"type":35,"value":974},{"type":29,"tag":901,"props":6578,"children":6580},{"class":903,"line":6579},33,[6581],{"type":29,"tag":901,"props":6582,"children":6583},{"style":908},[6584],{"type":35,"value":6585},"# Composition à la racine de l'application\n",{"type":29,"tag":901,"props":6587,"children":6588},{"class":903,"line":1274},[6589,6594,6599],{"type":29,"tag":901,"props":6590,"children":6591},{"style":917},[6592],{"type":35,"value":6593},"def",{"type":29,"tag":901,"props":6595,"children":6596},{"style":5362},[6597],{"type":35,"value":6598}," create_order_service",{"type":29,"tag":901,"props":6600,"children":6601},{"style":5185},[6602],{"type":35,"value":6603},"():\n",{"type":29,"tag":901,"props":6605,"children":6606},{"class":903,"line":487},[6607,6612,6616,6620,6624,6628],{"type":29,"tag":901,"props":6608,"children":6609},{"style":923},[6610],{"type":35,"value":6611},"    repository ",{"type":29,"tag":901,"props":6613,"children":6614},{"style":947},[6615],{"type":35,"value":2227},{"type":29,"tag":901,"props":6617,"children":6618},{"style":5242},[6619],{"type":35,"value":6260},{"type":29,"tag":901,"props":6621,"children":6622},{"style":5185},[6623],{"type":35,"value":3080},{"type":29,"tag":901,"props":6625,"children":6626},{"style":923},[6627],{"type":35,"value":5414},{"type":29,"tag":901,"props":6629,"children":6630},{"style":5185},[6631],{"type":35,"value":5437},{"type":29,"tag":901,"props":6633,"children":6634},{"class":903,"line":11},[6635,6640,6644,6648,6652,6656,6660,6665,6669,6674,6678,6683],{"type":29,"tag":901,"props":6636,"children":6637},{"style":923},[6638],{"type":35,"value":6639},"    notifier ",{"type":29,"tag":901,"props":6641,"children":6642},{"style":947},[6643],{"type":35,"value":2227},{"type":29,"tag":901,"props":6645,"children":6646},{"style":5242},[6647],{"type":35,"value":6395},{"type":29,"tag":901,"props":6649,"children":6650},{"style":5185},[6651],{"type":35,"value":3080},{"type":29,"tag":901,"props":6653,"children":6654},{"style":5252},[6655],{"type":35,"value":5326},{"type":29,"tag":901,"props":6657,"children":6658},{"style":947},[6659],{"type":35,"value":2227},{"type":29,"tag":901,"props":6661,"children":6662},{"style":923},[6663],{"type":35,"value":6664},"os",{"type":29,"tag":901,"props":6666,"children":6667},{"style":5185},[6668],{"type":35,"value":342},{"type":29,"tag":901,"props":6670,"children":6671},{"style":5242},[6672],{"type":35,"value":6673},"getenv",{"type":29,"tag":901,"props":6675,"children":6676},{"style":5185},[6677],{"type":35,"value":3080},{"type":29,"tag":901,"props":6679,"children":6680},{"style":2236},[6681],{"type":35,"value":6682},"\"SENDGRID_KEY\"",{"type":29,"tag":901,"props":6684,"children":6685},{"style":5185},[6686],{"type":35,"value":6687},"))\n",{"type":29,"tag":901,"props":6689,"children":6690},{"class":903,"line":2121},[6691,6696,6700,6704,6708,6712,6716],{"type":29,"tag":901,"props":6692,"children":6693},{"style":917},[6694],{"type":35,"value":6695},"    return",{"type":29,"tag":901,"props":6697,"children":6698},{"style":5242},[6699],{"type":35,"value":5182},{"type":29,"tag":901,"props":6701,"children":6702},{"style":5185},[6703],{"type":35,"value":3080},{"type":29,"tag":901,"props":6705,"children":6706},{"style":923},[6707],{"type":35,"value":6137},{"type":29,"tag":901,"props":6709,"children":6710},{"style":5185},[6711],{"type":35,"value":3663},{"type":29,"tag":901,"props":6713,"children":6714},{"style":923},[6715],{"type":35,"value":5988},{"type":29,"tag":901,"props":6717,"children":6718},{"style":5185},[6719],{"type":35,"value":5437},{"type":29,"tag":37,"props":6721,"children":6722},{},[6723],{"type":29,"tag":65,"props":6724,"children":6725},{},[6726],{"type":35,"value":6727},"Le gain pour les tests :",{"type":29,"tag":651,"props":6729,"children":6731},{"code":6730,"language":2202,"meta":8,"className":2200,"style":8},"# Test sans base de données ni Sendgrid — s'exécute en millisecondes\nclass InMemoryOrderRepository(OrderRepository):\n    def __init__(self):\n        self.orders = {}\n\n    def save(self, order_data: dict) -> str:\n        order_id = str(uuid.uuid4())\n        self.orders[order_id] = order_data\n        return order_id\n\ndef test_create_order():\n    repository = InMemoryOrderRepository()\n    notifier = MockEmailNotifier()\n    service = OrderService(repository, notifier)\n\n    order_id = service.create_order({\"email\": \"user@example.com\", \"items\": [...]})\n\n    assert order_id in repository.orders\n    assert len(notifier.sent_confirmations) == 1\n",[6732],{"type":29,"tag":565,"props":6733,"children":6734},{"__ignoreMap":8},[6735,6743,6767,6790,6815,6822,6873,6911,6950,6961,6968,6984,7004,7024,7060,7067,7140,7147,7178],{"type":29,"tag":901,"props":6736,"children":6737},{"class":903,"line":904},[6738],{"type":29,"tag":901,"props":6739,"children":6740},{"style":908},[6741],{"type":35,"value":6742},"# Test sans base de données ni Sendgrid — s'exécute en millisecondes\n",{"type":29,"tag":901,"props":6744,"children":6745},{"class":903,"line":463},[6746,6750,6755,6759,6763],{"type":29,"tag":901,"props":6747,"children":6748},{"style":917},[6749],{"type":35,"value":5176},{"type":29,"tag":901,"props":6751,"children":6752},{"style":5179},[6753],{"type":35,"value":6754}," InMemoryOrderRepository",{"type":29,"tag":901,"props":6756,"children":6757},{"style":5185},[6758],{"type":35,"value":3080},{"type":29,"tag":901,"props":6760,"children":6761},{"style":5179},[6762],{"type":35,"value":5614},{"type":29,"tag":901,"props":6764,"children":6765},{"style":5185},[6766],{"type":35,"value":5217},{"type":29,"tag":901,"props":6768,"children":6769},{"class":903,"line":469},[6770,6774,6778,6782,6786],{"type":29,"tag":901,"props":6771,"children":6772},{"style":917},[6773],{"type":35,"value":5196},{"type":29,"tag":901,"props":6775,"children":6776},{"style":5199},[6777],{"type":35,"value":5202},{"type":29,"tag":901,"props":6779,"children":6780},{"style":5185},[6781],{"type":35,"value":3080},{"type":29,"tag":901,"props":6783,"children":6784},{"style":5209},[6785],{"type":35,"value":5212},{"type":29,"tag":901,"props":6787,"children":6788},{"style":5185},[6789],{"type":35,"value":5217},{"type":29,"tag":901,"props":6791,"children":6792},{"class":903,"line":968},[6793,6797,6801,6806,6810],{"type":29,"tag":901,"props":6794,"children":6795},{"style":5223},[6796],{"type":35,"value":5226},{"type":29,"tag":901,"props":6798,"children":6799},{"style":5185},[6800],{"type":35,"value":342},{"type":29,"tag":901,"props":6802,"children":6803},{"style":923},[6804],{"type":35,"value":6805},"orders ",{"type":29,"tag":901,"props":6807,"children":6808},{"style":947},[6809],{"type":35,"value":2227},{"type":29,"tag":901,"props":6811,"children":6812},{"style":5185},[6813],{"type":35,"value":6814}," {}\n",{"type":29,"tag":901,"props":6816,"children":6817},{"class":903,"line":977},[6818],{"type":29,"tag":901,"props":6819,"children":6820},{"emptyLinePlaceholder":13},[6821],{"type":35,"value":974},{"type":29,"tag":901,"props":6823,"children":6824},{"class":903,"line":986},[6825,6829,6833,6837,6841,6845,6849,6853,6857,6861,6865,6869],{"type":29,"tag":901,"props":6826,"children":6827},{"style":917},[6828],{"type":35,"value":5196},{"type":29,"tag":901,"props":6830,"children":6831},{"style":5362},[6832],{"type":35,"value":5739},{"type":29,"tag":901,"props":6834,"children":6835},{"style":5185},[6836],{"type":35,"value":3080},{"type":29,"tag":901,"props":6838,"children":6839},{"style":5209},[6840],{"type":35,"value":5212},{"type":29,"tag":901,"props":6842,"children":6843},{"style":5185},[6844],{"type":35,"value":3663},{"type":29,"tag":901,"props":6846,"children":6847},{"style":5380},[6848],{"type":35,"value":5383},{"type":29,"tag":901,"props":6850,"children":6851},{"style":5185},[6852],{"type":35,"value":5760},{"type":29,"tag":901,"props":6854,"children":6855},{"style":5763},[6856],{"type":35,"value":5766},{"type":29,"tag":901,"props":6858,"children":6859},{"style":5185},[6860],{"type":35,"value":2881},{"type":29,"tag":901,"props":6862,"children":6863},{"style":5185},[6864],{"type":35,"value":5775},{"type":29,"tag":901,"props":6866,"children":6867},{"style":5763},[6868],{"type":35,"value":5780},{"type":29,"tag":901,"props":6870,"children":6871},{"style":5185},[6872],{"type":35,"value":5188},{"type":29,"tag":901,"props":6874,"children":6875},{"class":903,"line":1007},[6876,6880,6884,6888,6892,6897,6901,6906],{"type":29,"tag":901,"props":6877,"children":6878},{"style":923},[6879],{"type":35,"value":5396},{"type":29,"tag":901,"props":6881,"children":6882},{"style":947},[6883],{"type":35,"value":2227},{"type":29,"tag":901,"props":6885,"children":6886},{"style":5763},[6887],{"type":35,"value":5780},{"type":29,"tag":901,"props":6889,"children":6890},{"style":5185},[6891],{"type":35,"value":3080},{"type":29,"tag":901,"props":6893,"children":6894},{"style":923},[6895],{"type":35,"value":6896},"uuid",{"type":29,"tag":901,"props":6898,"children":6899},{"style":5185},[6900],{"type":35,"value":342},{"type":29,"tag":901,"props":6902,"children":6903},{"style":5242},[6904],{"type":35,"value":6905},"uuid4",{"type":29,"tag":901,"props":6907,"children":6908},{"style":5185},[6909],{"type":35,"value":6910},"())\n",{"type":29,"tag":901,"props":6912,"children":6913},{"class":903,"line":5354},[6914,6918,6922,6926,6930,6935,6940,6945],{"type":29,"tag":901,"props":6915,"children":6916},{"style":5223},[6917],{"type":35,"value":5226},{"type":29,"tag":901,"props":6919,"children":6920},{"style":5185},[6921],{"type":35,"value":342},{"type":29,"tag":901,"props":6923,"children":6924},{"style":5380},[6925],{"type":35,"value":570},{"type":29,"tag":901,"props":6927,"children":6928},{"style":5185},[6929],{"type":35,"value":5475},{"type":29,"tag":901,"props":6931,"children":6932},{"style":5380},[6933],{"type":35,"value":6934},"order_id",{"type":29,"tag":901,"props":6936,"children":6937},{"style":5185},[6938],{"type":35,"value":6939},"]",{"type":29,"tag":901,"props":6941,"children":6942},{"style":947},[6943],{"type":35,"value":6944}," =",{"type":29,"tag":901,"props":6946,"children":6947},{"style":923},[6948],{"type":35,"value":6949}," order_data\n",{"type":29,"tag":901,"props":6951,"children":6952},{"class":903,"line":5390},[6953,6957],{"type":29,"tag":901,"props":6954,"children":6955},{"style":917},[6956],{"type":35,"value":5512},{"type":29,"tag":901,"props":6958,"children":6959},{"style":923},[6960],{"type":35,"value":5517},{"type":29,"tag":901,"props":6962,"children":6963},{"class":903,"line":5440},[6964],{"type":29,"tag":901,"props":6965,"children":6966},{"emptyLinePlaceholder":13},[6967],{"type":35,"value":974},{"type":29,"tag":901,"props":6969,"children":6970},{"class":903,"line":5506},[6971,6975,6980],{"type":29,"tag":901,"props":6972,"children":6973},{"style":917},[6974],{"type":35,"value":6593},{"type":29,"tag":901,"props":6976,"children":6977},{"style":5362},[6978],{"type":35,"value":6979}," test_create_order",{"type":29,"tag":901,"props":6981,"children":6982},{"style":5185},[6983],{"type":35,"value":6603},{"type":29,"tag":901,"props":6985,"children":6986},{"class":903,"line":5911},[6987,6991,6995,6999],{"type":29,"tag":901,"props":6988,"children":6989},{"style":923},[6990],{"type":35,"value":6611},{"type":29,"tag":901,"props":6992,"children":6993},{"style":947},[6994],{"type":35,"value":2227},{"type":29,"tag":901,"props":6996,"children":6997},{"style":5242},[6998],{"type":35,"value":6754},{"type":29,"tag":901,"props":7000,"children":7001},{"style":5185},[7002],{"type":35,"value":7003},"()\n",{"type":29,"tag":901,"props":7005,"children":7006},{"class":903,"line":5919},[7007,7011,7015,7020],{"type":29,"tag":901,"props":7008,"children":7009},{"style":923},[7010],{"type":35,"value":6639},{"type":29,"tag":901,"props":7012,"children":7013},{"style":947},[7014],{"type":35,"value":2227},{"type":29,"tag":901,"props":7016,"children":7017},{"style":5242},[7018],{"type":35,"value":7019}," MockEmailNotifier",{"type":29,"tag":901,"props":7021,"children":7022},{"style":5185},[7023],{"type":35,"value":7003},{"type":29,"tag":901,"props":7025,"children":7026},{"class":903,"line":5928},[7027,7032,7036,7040,7044,7048,7052,7056],{"type":29,"tag":901,"props":7028,"children":7029},{"style":923},[7030],{"type":35,"value":7031},"    service ",{"type":29,"tag":901,"props":7033,"children":7034},{"style":947},[7035],{"type":35,"value":2227},{"type":29,"tag":901,"props":7037,"children":7038},{"style":5242},[7039],{"type":35,"value":5182},{"type":29,"tag":901,"props":7041,"children":7042},{"style":5185},[7043],{"type":35,"value":3080},{"type":29,"tag":901,"props":7045,"children":7046},{"style":923},[7047],{"type":35,"value":6137},{"type":29,"tag":901,"props":7049,"children":7050},{"style":5185},[7051],{"type":35,"value":3663},{"type":29,"tag":901,"props":7053,"children":7054},{"style":923},[7055],{"type":35,"value":5988},{"type":29,"tag":901,"props":7057,"children":7058},{"style":5185},[7059],{"type":35,"value":5437},{"type":29,"tag":901,"props":7061,"children":7062},{"class":903,"line":5944},[7063],{"type":29,"tag":901,"props":7064,"children":7065},{"emptyLinePlaceholder":13},[7066],{"type":35,"value":974},{"type":29,"tag":901,"props":7068,"children":7069},{"class":903,"line":6003},[7070,7075,7079,7084,7088,7093,7098,7103,7107,7112,7116,7121,7125,7130,7135],{"type":29,"tag":901,"props":7071,"children":7072},{"style":923},[7073],{"type":35,"value":7074},"    order_id ",{"type":29,"tag":901,"props":7076,"children":7077},{"style":947},[7078],{"type":35,"value":2227},{"type":29,"tag":901,"props":7080,"children":7081},{"style":923},[7082],{"type":35,"value":7083}," service",{"type":29,"tag":901,"props":7085,"children":7086},{"style":5185},[7087],{"type":35,"value":342},{"type":29,"tag":901,"props":7089,"children":7090},{"style":5242},[7091],{"type":35,"value":7092},"create_order",{"type":29,"tag":901,"props":7094,"children":7095},{"style":5185},[7096],{"type":35,"value":7097},"({",{"type":29,"tag":901,"props":7099,"children":7100},{"style":2236},[7101],{"type":35,"value":7102},"\"email\"",{"type":29,"tag":901,"props":7104,"children":7105},{"style":5185},[7106],{"type":35,"value":5760},{"type":29,"tag":901,"props":7108,"children":7109},{"style":2236},[7110],{"type":35,"value":7111}," \"user@example.com\"",{"type":29,"tag":901,"props":7113,"children":7114},{"style":5185},[7115],{"type":35,"value":3663},{"type":29,"tag":901,"props":7117,"children":7118},{"style":2236},[7119],{"type":35,"value":7120}," \"items\"",{"type":29,"tag":901,"props":7122,"children":7123},{"style":5185},[7124],{"type":35,"value":5760},{"type":29,"tag":901,"props":7126,"children":7127},{"style":5185},[7128],{"type":35,"value":7129}," [",{"type":29,"tag":901,"props":7131,"children":7132},{"style":5674},[7133],{"type":35,"value":7134},"...",{"type":29,"tag":901,"props":7136,"children":7137},{"style":5185},[7138],{"type":35,"value":7139},"]})\n",{"type":29,"tag":901,"props":7141,"children":7142},{"class":903,"line":6029},[7143],{"type":29,"tag":901,"props":7144,"children":7145},{"emptyLinePlaceholder":13},[7146],{"type":35,"value":974},{"type":29,"tag":901,"props":7148,"children":7149},{"class":903,"line":6055},[7150,7155,7160,7165,7169,7173],{"type":29,"tag":901,"props":7151,"children":7152},{"style":917},[7153],{"type":35,"value":7154},"    assert",{"type":29,"tag":901,"props":7156,"children":7157},{"style":923},[7158],{"type":35,"value":7159}," order_id ",{"type":29,"tag":901,"props":7161,"children":7162},{"style":917},[7163],{"type":35,"value":7164},"in",{"type":29,"tag":901,"props":7166,"children":7167},{"style":923},[7168],{"type":35,"value":5970},{"type":29,"tag":901,"props":7170,"children":7171},{"style":5185},[7172],{"type":35,"value":342},{"type":29,"tag":901,"props":7174,"children":7175},{"style":923},[7176],{"type":35,"value":7177},"orders\n",{"type":29,"tag":901,"props":7179,"children":7180},{"class":903,"line":6063},[7181,7185,7190,7194,7198,7202,7207,7211,7216],{"type":29,"tag":901,"props":7182,"children":7183},{"style":917},[7184],{"type":35,"value":7154},{"type":29,"tag":901,"props":7186,"children":7187},{"style":5763},[7188],{"type":35,"value":7189}," len",{"type":29,"tag":901,"props":7191,"children":7192},{"style":5185},[7193],{"type":35,"value":3080},{"type":29,"tag":901,"props":7195,"children":7196},{"style":923},[7197],{"type":35,"value":6174},{"type":29,"tag":901,"props":7199,"children":7200},{"style":5185},[7201],{"type":35,"value":342},{"type":29,"tag":901,"props":7203,"children":7204},{"style":923},[7205],{"type":35,"value":7206},"sent_confirmations",{"type":29,"tag":901,"props":7208,"children":7209},{"style":5185},[7210],{"type":35,"value":2881},{"type":29,"tag":901,"props":7212,"children":7213},{"style":947},[7214],{"type":35,"value":7215}," ==",{"type":29,"tag":901,"props":7217,"children":7218},{"style":5280},[7219],{"type":35,"value":7220}," 1\n",{"type":29,"tag":176,"props":7222,"children":7224},{"cta":178,"href":179,"title":7223,"type":181},"Votre codebase est difficile à tester parce que les dépendances sont fortement couplées ?",[7225],{"type":29,"tag":37,"props":7226,"children":7227},{},[7228],{"type":35,"value":7229},"Introduire le DIP dans un codebase existant nécessite une stratégie progressive, pas un refactoring massif qui bloque toute l'équipe. En 30 minutes, on peut identifier les zones de couplage les plus problématiques et définir un plan de refactoring réaliste avec des gains mesurables.",{"type":29,"tag":76,"props":7231,"children":7232},{},[],{"type":29,"tag":80,"props":7234,"children":7236},{"id":7235},"exemple-2-typescript-interfaces-et-injection-par-framework",[7237],{"type":35,"value":7238},"Exemple 2 : TypeScript, interfaces et injection par framework",{"type":29,"tag":651,"props":7240,"children":7244},{"code":7241,"language":7242,"meta":8,"className":7243,"style":8},"// Les abstractions (interfaces TypeScript)\ninterface OrderRepository {\n    save(orderData: OrderData): Promise\u003Cstring>;\n    findById(orderId: string): Promise\u003COrder | null>;\n}\n\ninterface PaymentGateway {\n    charge(amount: number, currency: string, paymentMethod: string): Promise\u003CPaymentResult>;\n}\n\n// Le module de haut niveau\nclass OrderService {\n    constructor(\n        private readonly repository: OrderRepository,\n        private readonly payment: PaymentGateway\n    ) {}\n\n    async createPaidOrder(orderData: OrderData): Promise\u003COrder> {\n        const paymentResult = await this.payment.charge(\n            orderData.total,\n            orderData.currency,\n            orderData.paymentMethodId\n        );\n\n        if (!paymentResult.success) {\n            throw new PaymentFailedError(paymentResult.errorCode);\n        }\n\n        const orderId = await this.repository.save({\n            ...orderData,\n            paymentId: paymentResult.transactionId,\n            status: 'paid'\n        });\n\n        return this.repository.findById(orderId);\n    }\n}\n\n// Test — sans Stripe, sans base de données\ndescribe('OrderService', () => {\n    it('should create order with successful payment', async () => {\n        const mockRepository: OrderRepository = {\n            save: jest.fn().mockResolvedValue('order-123'),\n            findById: jest.fn().mockResolvedValue({ id: 'order-123', status: 'paid' })\n        };\n\n        const mockPayment: PaymentGateway = {\n            charge: jest.fn().mockResolvedValue({ success: true, transactionId: 'txn-456' })\n        };\n\n        const service = new OrderService(mockRepository, mockPayment);\n        const order = await service.createPaidOrder({ total: 1000, currency: 'EUR' });\n\n        expect(order.status).toBe('paid');\n    });\n});\n","typescript","language-typescript shiki shiki-themes catppuccin-frappe github-dark",[7245],{"type":29,"tag":565,"props":7246,"children":7247},{"__ignoreMap":8},[7248,7256,7273,7333,7399,7407,7414,7430,7519,7526,7533,7541,7556,7569,7599,7624,7636,7643,7700,7751,7772,7792,7808,7820,7827,7864,7901,7909,7916,7964,7980,8009,8026,8042,8049,8086,8094,8101,8109,8118,8154,8193,8222,8280,8366,8375,8383,8412,8497,8505,8513,8555,8640,8648,8697,8714],{"type":29,"tag":901,"props":7249,"children":7250},{"class":903,"line":904},[7251],{"type":29,"tag":901,"props":7252,"children":7253},{"style":908},[7254],{"type":35,"value":7255},"// Les abstractions (interfaces TypeScript)\n",{"type":29,"tag":901,"props":7257,"children":7258},{"class":903,"line":463},[7259,7264,7268],{"type":29,"tag":901,"props":7260,"children":7261},{"style":917},[7262],{"type":35,"value":7263},"interface",{"type":29,"tag":901,"props":7265,"children":7266},{"style":5179},[7267],{"type":35,"value":5705},{"type":29,"tag":901,"props":7269,"children":7270},{"style":5185},[7271],{"type":35,"value":7272}," {\n",{"type":29,"tag":901,"props":7274,"children":7275},{"class":903,"line":469},[7276,7281,7285,7290,7294,7299,7303,7307,7312,7318,7323,7328],{"type":29,"tag":901,"props":7277,"children":7278},{"style":5362},[7279],{"type":35,"value":7280},"    save",{"type":29,"tag":901,"props":7282,"children":7283},{"style":5185},[7284],{"type":35,"value":3080},{"type":29,"tag":901,"props":7286,"children":7287},{"style":5252},[7288],{"type":35,"value":7289},"orderData",{"type":29,"tag":901,"props":7291,"children":7292},{"style":947},[7293],{"type":35,"value":5760},{"type":29,"tag":901,"props":7295,"children":7296},{"style":5179},[7297],{"type":35,"value":7298}," OrderData",{"type":29,"tag":901,"props":7300,"children":7301},{"style":5185},[7302],{"type":35,"value":2881},{"type":29,"tag":901,"props":7304,"children":7305},{"style":947},[7306],{"type":35,"value":5760},{"type":29,"tag":901,"props":7308,"children":7309},{"style":5179},[7310],{"type":35,"value":7311}," Promise",{"type":29,"tag":901,"props":7313,"children":7315},{"style":7314},"--shiki-default:#99D1DB;--shiki-dark:#E1E4E8",[7316],{"type":35,"value":7317},"\u003C",{"type":29,"tag":901,"props":7319,"children":7320},{"style":5894},[7321],{"type":35,"value":7322},"string",{"type":29,"tag":901,"props":7324,"children":7325},{"style":7314},[7326],{"type":35,"value":7327},">",{"type":29,"tag":901,"props":7329,"children":7330},{"style":5185},[7331],{"type":35,"value":7332},";\n",{"type":29,"tag":901,"props":7334,"children":7335},{"class":903,"line":968},[7336,7341,7345,7350,7354,7359,7363,7367,7371,7375,7380,7385,7391,7395],{"type":29,"tag":901,"props":7337,"children":7338},{"style":5362},[7339],{"type":35,"value":7340},"    findById",{"type":29,"tag":901,"props":7342,"children":7343},{"style":5185},[7344],{"type":35,"value":3080},{"type":29,"tag":901,"props":7346,"children":7347},{"style":5252},[7348],{"type":35,"value":7349},"orderId",{"type":29,"tag":901,"props":7351,"children":7352},{"style":947},[7353],{"type":35,"value":5760},{"type":29,"tag":901,"props":7355,"children":7356},{"style":5894},[7357],{"type":35,"value":7358}," string",{"type":29,"tag":901,"props":7360,"children":7361},{"style":5185},[7362],{"type":35,"value":2881},{"type":29,"tag":901,"props":7364,"children":7365},{"style":947},[7366],{"type":35,"value":5760},{"type":29,"tag":901,"props":7368,"children":7369},{"style":5179},[7370],{"type":35,"value":7311},{"type":29,"tag":901,"props":7372,"children":7373},{"style":7314},[7374],{"type":35,"value":7317},{"type":29,"tag":901,"props":7376,"children":7377},{"style":5179},[7378],{"type":35,"value":7379},"Order",{"type":29,"tag":901,"props":7381,"children":7382},{"style":947},[7383],{"type":35,"value":7384}," |",{"type":29,"tag":901,"props":7386,"children":7388},{"style":7387},"--shiki-default:#CA9EE6;--shiki-default-font-style:italic;--shiki-dark:#79B8FF;--shiki-dark-font-style:inherit",[7389],{"type":35,"value":7390}," null",{"type":29,"tag":901,"props":7392,"children":7393},{"style":7314},[7394],{"type":35,"value":7327},{"type":29,"tag":901,"props":7396,"children":7397},{"style":5185},[7398],{"type":35,"value":7332},{"type":29,"tag":901,"props":7400,"children":7401},{"class":903,"line":977},[7402],{"type":29,"tag":901,"props":7403,"children":7404},{"style":5185},[7405],{"type":35,"value":7406},"}\n",{"type":29,"tag":901,"props":7408,"children":7409},{"class":903,"line":986},[7410],{"type":29,"tag":901,"props":7411,"children":7412},{"emptyLinePlaceholder":13},[7413],{"type":35,"value":974},{"type":29,"tag":901,"props":7415,"children":7416},{"class":903,"line":1007},[7417,7421,7426],{"type":29,"tag":901,"props":7418,"children":7419},{"style":917},[7420],{"type":35,"value":7263},{"type":29,"tag":901,"props":7422,"children":7423},{"style":5179},[7424],{"type":35,"value":7425}," PaymentGateway",{"type":29,"tag":901,"props":7427,"children":7428},{"style":5185},[7429],{"type":35,"value":7272},{"type":29,"tag":901,"props":7431,"children":7432},{"class":903,"line":5354},[7433,7438,7442,7447,7451,7456,7460,7465,7469,7473,7477,7482,7486,7490,7494,7498,7502,7506,7511,7515],{"type":29,"tag":901,"props":7434,"children":7435},{"style":5362},[7436],{"type":35,"value":7437},"    charge",{"type":29,"tag":901,"props":7439,"children":7440},{"style":5185},[7441],{"type":35,"value":3080},{"type":29,"tag":901,"props":7443,"children":7444},{"style":5252},[7445],{"type":35,"value":7446},"amount",{"type":29,"tag":901,"props":7448,"children":7449},{"style":947},[7450],{"type":35,"value":5760},{"type":29,"tag":901,"props":7452,"children":7453},{"style":5894},[7454],{"type":35,"value":7455}," number",{"type":29,"tag":901,"props":7457,"children":7458},{"style":5185},[7459],{"type":35,"value":3663},{"type":29,"tag":901,"props":7461,"children":7462},{"style":5252},[7463],{"type":35,"value":7464}," currency",{"type":29,"tag":901,"props":7466,"children":7467},{"style":947},[7468],{"type":35,"value":5760},{"type":29,"tag":901,"props":7470,"children":7471},{"style":5894},[7472],{"type":35,"value":7358},{"type":29,"tag":901,"props":7474,"children":7475},{"style":5185},[7476],{"type":35,"value":3663},{"type":29,"tag":901,"props":7478,"children":7479},{"style":5252},[7480],{"type":35,"value":7481}," paymentMethod",{"type":29,"tag":901,"props":7483,"children":7484},{"style":947},[7485],{"type":35,"value":5760},{"type":29,"tag":901,"props":7487,"children":7488},{"style":5894},[7489],{"type":35,"value":7358},{"type":29,"tag":901,"props":7491,"children":7492},{"style":5185},[7493],{"type":35,"value":2881},{"type":29,"tag":901,"props":7495,"children":7496},{"style":947},[7497],{"type":35,"value":5760},{"type":29,"tag":901,"props":7499,"children":7500},{"style":5179},[7501],{"type":35,"value":7311},{"type":29,"tag":901,"props":7503,"children":7504},{"style":7314},[7505],{"type":35,"value":7317},{"type":29,"tag":901,"props":7507,"children":7508},{"style":5179},[7509],{"type":35,"value":7510},"PaymentResult",{"type":29,"tag":901,"props":7512,"children":7513},{"style":7314},[7514],{"type":35,"value":7327},{"type":29,"tag":901,"props":7516,"children":7517},{"style":5185},[7518],{"type":35,"value":7332},{"type":29,"tag":901,"props":7520,"children":7521},{"class":903,"line":5390},[7522],{"type":29,"tag":901,"props":7523,"children":7524},{"style":5185},[7525],{"type":35,"value":7406},{"type":29,"tag":901,"props":7527,"children":7528},{"class":903,"line":5440},[7529],{"type":29,"tag":901,"props":7530,"children":7531},{"emptyLinePlaceholder":13},[7532],{"type":35,"value":974},{"type":29,"tag":901,"props":7534,"children":7535},{"class":903,"line":5506},[7536],{"type":29,"tag":901,"props":7537,"children":7538},{"style":908},[7539],{"type":35,"value":7540},"// Le module de haut niveau\n",{"type":29,"tag":901,"props":7542,"children":7543},{"class":903,"line":5911},[7544,7548,7552],{"type":29,"tag":901,"props":7545,"children":7546},{"style":917},[7547],{"type":35,"value":5176},{"type":29,"tag":901,"props":7549,"children":7550},{"style":5179},[7551],{"type":35,"value":5182},{"type":29,"tag":901,"props":7553,"children":7554},{"style":5185},[7555],{"type":35,"value":7272},{"type":29,"tag":901,"props":7557,"children":7558},{"class":903,"line":5919},[7559,7564],{"type":29,"tag":901,"props":7560,"children":7561},{"style":917},[7562],{"type":35,"value":7563},"    constructor",{"type":29,"tag":901,"props":7565,"children":7566},{"style":5185},[7567],{"type":35,"value":7568},"(\n",{"type":29,"tag":901,"props":7570,"children":7571},{"class":903,"line":5928},[7572,7577,7582,7586,7590,7594],{"type":29,"tag":901,"props":7573,"children":7574},{"style":917},[7575],{"type":35,"value":7576},"        private",{"type":29,"tag":901,"props":7578,"children":7579},{"style":917},[7580],{"type":35,"value":7581}," readonly",{"type":29,"tag":901,"props":7583,"children":7584},{"style":5252},[7585],{"type":35,"value":5970},{"type":29,"tag":901,"props":7587,"children":7588},{"style":947},[7589],{"type":35,"value":5760},{"type":29,"tag":901,"props":7591,"children":7592},{"style":5179},[7593],{"type":35,"value":5705},{"type":29,"tag":901,"props":7595,"children":7596},{"style":5185},[7597],{"type":35,"value":7598},",\n",{"type":29,"tag":901,"props":7600,"children":7601},{"class":903,"line":5944},[7602,7606,7610,7615,7619],{"type":29,"tag":901,"props":7603,"children":7604},{"style":917},[7605],{"type":35,"value":7576},{"type":29,"tag":901,"props":7607,"children":7608},{"style":917},[7609],{"type":35,"value":7581},{"type":29,"tag":901,"props":7611,"children":7612},{"style":5252},[7613],{"type":35,"value":7614}," payment",{"type":29,"tag":901,"props":7616,"children":7617},{"style":947},[7618],{"type":35,"value":5760},{"type":29,"tag":901,"props":7620,"children":7621},{"style":5179},[7622],{"type":35,"value":7623}," PaymentGateway\n",{"type":29,"tag":901,"props":7625,"children":7626},{"class":903,"line":6003},[7627,7632],{"type":29,"tag":901,"props":7628,"children":7629},{"style":5185},[7630],{"type":35,"value":7631},"    )",{"type":29,"tag":901,"props":7633,"children":7634},{"style":5185},[7635],{"type":35,"value":6814},{"type":29,"tag":901,"props":7637,"children":7638},{"class":903,"line":6029},[7639],{"type":29,"tag":901,"props":7640,"children":7641},{"emptyLinePlaceholder":13},[7642],{"type":35,"value":974},{"type":29,"tag":901,"props":7644,"children":7645},{"class":903,"line":6055},[7646,7651,7656,7660,7664,7668,7672,7676,7680,7684,7688,7692,7696],{"type":29,"tag":901,"props":7647,"children":7648},{"style":917},[7649],{"type":35,"value":7650},"    async",{"type":29,"tag":901,"props":7652,"children":7653},{"style":5362},[7654],{"type":35,"value":7655}," createPaidOrder",{"type":29,"tag":901,"props":7657,"children":7658},{"style":5185},[7659],{"type":35,"value":3080},{"type":29,"tag":901,"props":7661,"children":7662},{"style":5252},[7663],{"type":35,"value":7289},{"type":29,"tag":901,"props":7665,"children":7666},{"style":947},[7667],{"type":35,"value":5760},{"type":29,"tag":901,"props":7669,"children":7670},{"style":5179},[7671],{"type":35,"value":7298},{"type":29,"tag":901,"props":7673,"children":7674},{"style":5185},[7675],{"type":35,"value":2881},{"type":29,"tag":901,"props":7677,"children":7678},{"style":947},[7679],{"type":35,"value":5760},{"type":29,"tag":901,"props":7681,"children":7682},{"style":5179},[7683],{"type":35,"value":7311},{"type":29,"tag":901,"props":7685,"children":7686},{"style":7314},[7687],{"type":35,"value":7317},{"type":29,"tag":901,"props":7689,"children":7690},{"style":5179},[7691],{"type":35,"value":7379},{"type":29,"tag":901,"props":7693,"children":7694},{"style":7314},[7695],{"type":35,"value":7327},{"type":29,"tag":901,"props":7697,"children":7698},{"style":5185},[7699],{"type":35,"value":7272},{"type":29,"tag":901,"props":7701,"children":7702},{"class":903,"line":6063},[7703,7708,7713,7717,7722,7728,7733,7738,7742,7747],{"type":29,"tag":901,"props":7704,"children":7705},{"style":917},[7706],{"type":35,"value":7707},"        const",{"type":29,"tag":901,"props":7709,"children":7710},{"style":5674},[7711],{"type":35,"value":7712}," paymentResult",{"type":29,"tag":901,"props":7714,"children":7715},{"style":947},[7716],{"type":35,"value":6944},{"type":29,"tag":901,"props":7718,"children":7719},{"style":917},[7720],{"type":35,"value":7721}," await",{"type":29,"tag":901,"props":7723,"children":7725},{"style":7724},"--shiki-default:#E78284;--shiki-dark:#79B8FF",[7726],{"type":35,"value":7727}," this",{"type":29,"tag":901,"props":7729,"children":7731},{"style":7730},"--shiki-default:#81C8BE;--shiki-dark:#E1E4E8",[7732],{"type":35,"value":342},{"type":29,"tag":901,"props":7734,"children":7735},{"style":923},[7736],{"type":35,"value":7737},"payment",{"type":29,"tag":901,"props":7739,"children":7740},{"style":7730},[7741],{"type":35,"value":342},{"type":29,"tag":901,"props":7743,"children":7744},{"style":5362},[7745],{"type":35,"value":7746},"charge",{"type":29,"tag":901,"props":7748,"children":7749},{"style":923},[7750],{"type":35,"value":7568},{"type":29,"tag":901,"props":7752,"children":7753},{"class":903,"line":6115},[7754,7759,7763,7768],{"type":29,"tag":901,"props":7755,"children":7756},{"style":923},[7757],{"type":35,"value":7758},"            orderData",{"type":29,"tag":901,"props":7760,"children":7761},{"style":7730},[7762],{"type":35,"value":342},{"type":29,"tag":901,"props":7764,"children":7765},{"style":923},[7766],{"type":35,"value":7767},"total",{"type":29,"tag":901,"props":7769,"children":7770},{"style":5185},[7771],{"type":35,"value":7598},{"type":29,"tag":901,"props":7773,"children":7774},{"class":903,"line":6160},[7775,7779,7783,7788],{"type":29,"tag":901,"props":7776,"children":7777},{"style":923},[7778],{"type":35,"value":7758},{"type":29,"tag":901,"props":7780,"children":7781},{"style":7730},[7782],{"type":35,"value":342},{"type":29,"tag":901,"props":7784,"children":7785},{"style":923},[7786],{"type":35,"value":7787},"currency",{"type":29,"tag":901,"props":7789,"children":7790},{"style":5185},[7791],{"type":35,"value":7598},{"type":29,"tag":901,"props":7793,"children":7794},{"class":903,"line":6221},[7795,7799,7803],{"type":29,"tag":901,"props":7796,"children":7797},{"style":923},[7798],{"type":35,"value":7758},{"type":29,"tag":901,"props":7800,"children":7801},{"style":7730},[7802],{"type":35,"value":342},{"type":29,"tag":901,"props":7804,"children":7805},{"style":923},[7806],{"type":35,"value":7807},"paymentMethodId\n",{"type":29,"tag":901,"props":7809,"children":7810},{"class":903,"line":6233},[7811,7816],{"type":29,"tag":901,"props":7812,"children":7813},{"style":923},[7814],{"type":35,"value":7815},"        )",{"type":29,"tag":901,"props":7817,"children":7818},{"style":5185},[7819],{"type":35,"value":7332},{"type":29,"tag":901,"props":7821,"children":7822},{"class":903,"line":6241},[7823],{"type":29,"tag":901,"props":7824,"children":7825},{"emptyLinePlaceholder":13},[7826],{"type":35,"value":974},{"type":29,"tag":901,"props":7828,"children":7829},{"class":903,"line":6250},[7830,7835,7840,7845,7850,7854,7859],{"type":29,"tag":901,"props":7831,"children":7832},{"style":917},[7833],{"type":35,"value":7834},"        if",{"type":29,"tag":901,"props":7836,"children":7837},{"style":923},[7838],{"type":35,"value":7839}," (",{"type":29,"tag":901,"props":7841,"children":7842},{"style":947},[7843],{"type":35,"value":7844},"!",{"type":29,"tag":901,"props":7846,"children":7847},{"style":923},[7848],{"type":35,"value":7849},"paymentResult",{"type":29,"tag":901,"props":7851,"children":7852},{"style":7730},[7853],{"type":35,"value":342},{"type":29,"tag":901,"props":7855,"children":7856},{"style":923},[7857],{"type":35,"value":7858},"success) ",{"type":29,"tag":901,"props":7860,"children":7861},{"style":5185},[7862],{"type":35,"value":7863},"{\n",{"type":29,"tag":901,"props":7865,"children":7866},{"class":903,"line":6275},[7867,7872,7878,7883,7888,7892,7897],{"type":29,"tag":901,"props":7868,"children":7869},{"style":917},[7870],{"type":35,"value":7871},"            throw",{"type":29,"tag":901,"props":7873,"children":7875},{"style":7874},"--shiki-default:#CA9EE6;--shiki-default-font-weight:bold;--shiki-dark:#F97583;--shiki-dark-font-weight:inherit",[7876],{"type":35,"value":7877}," new",{"type":29,"tag":901,"props":7879,"children":7880},{"style":5362},[7881],{"type":35,"value":7882}," PaymentFailedError",{"type":29,"tag":901,"props":7884,"children":7885},{"style":923},[7886],{"type":35,"value":7887},"(paymentResult",{"type":29,"tag":901,"props":7889,"children":7890},{"style":7730},[7891],{"type":35,"value":342},{"type":29,"tag":901,"props":7893,"children":7894},{"style":923},[7895],{"type":35,"value":7896},"errorCode)",{"type":29,"tag":901,"props":7898,"children":7899},{"style":5185},[7900],{"type":35,"value":7332},{"type":29,"tag":901,"props":7902,"children":7903},{"class":903,"line":6327},[7904],{"type":29,"tag":901,"props":7905,"children":7906},{"style":5185},[7907],{"type":35,"value":7908},"        }\n",{"type":29,"tag":901,"props":7910,"children":7911},{"class":903,"line":6377},[7912],{"type":29,"tag":901,"props":7913,"children":7914},{"emptyLinePlaceholder":13},[7915],{"type":35,"value":974},{"type":29,"tag":901,"props":7917,"children":7918},{"class":903,"line":6385},[7919,7923,7928,7932,7936,7940,7944,7948,7952,7956,7960],{"type":29,"tag":901,"props":7920,"children":7921},{"style":917},[7922],{"type":35,"value":7707},{"type":29,"tag":901,"props":7924,"children":7925},{"style":5674},[7926],{"type":35,"value":7927}," orderId",{"type":29,"tag":901,"props":7929,"children":7930},{"style":947},[7931],{"type":35,"value":6944},{"type":29,"tag":901,"props":7933,"children":7934},{"style":917},[7935],{"type":35,"value":7721},{"type":29,"tag":901,"props":7937,"children":7938},{"style":7724},[7939],{"type":35,"value":7727},{"type":29,"tag":901,"props":7941,"children":7942},{"style":7730},[7943],{"type":35,"value":342},{"type":29,"tag":901,"props":7945,"children":7946},{"style":923},[7947],{"type":35,"value":6137},{"type":29,"tag":901,"props":7949,"children":7950},{"style":7730},[7951],{"type":35,"value":342},{"type":29,"tag":901,"props":7953,"children":7954},{"style":5362},[7955],{"type":35,"value":5423},{"type":29,"tag":901,"props":7957,"children":7958},{"style":923},[7959],{"type":35,"value":3080},{"type":29,"tag":901,"props":7961,"children":7962},{"style":5185},[7963],{"type":35,"value":7863},{"type":29,"tag":901,"props":7965,"children":7966},{"class":903,"line":5085},[7967,7972,7976],{"type":29,"tag":901,"props":7968,"children":7969},{"style":947},[7970],{"type":35,"value":7971},"            ...",{"type":29,"tag":901,"props":7973,"children":7974},{"style":923},[7975],{"type":35,"value":7289},{"type":29,"tag":901,"props":7977,"children":7978},{"style":5185},[7979],{"type":35,"value":7598},{"type":29,"tag":901,"props":7981,"children":7982},{"class":903,"line":4573},[7983,7988,7992,7996,8000,8005],{"type":29,"tag":901,"props":7984,"children":7985},{"style":923},[7986],{"type":35,"value":7987},"            paymentId",{"type":29,"tag":901,"props":7989,"children":7990},{"style":7730},[7991],{"type":35,"value":5760},{"type":29,"tag":901,"props":7993,"children":7994},{"style":923},[7995],{"type":35,"value":7712},{"type":29,"tag":901,"props":7997,"children":7998},{"style":7730},[7999],{"type":35,"value":342},{"type":29,"tag":901,"props":8001,"children":8002},{"style":923},[8003],{"type":35,"value":8004},"transactionId",{"type":29,"tag":901,"props":8006,"children":8007},{"style":5185},[8008],{"type":35,"value":7598},{"type":29,"tag":901,"props":8010,"children":8011},{"class":903,"line":4109},[8012,8017,8021],{"type":29,"tag":901,"props":8013,"children":8014},{"style":923},[8015],{"type":35,"value":8016},"            status",{"type":29,"tag":901,"props":8018,"children":8019},{"style":7730},[8020],{"type":35,"value":5760},{"type":29,"tag":901,"props":8022,"children":8023},{"style":2236},[8024],{"type":35,"value":8025}," 'paid'\n",{"type":29,"tag":901,"props":8027,"children":8028},{"class":903,"line":6579},[8029,8034,8038],{"type":29,"tag":901,"props":8030,"children":8031},{"style":5185},[8032],{"type":35,"value":8033},"        }",{"type":29,"tag":901,"props":8035,"children":8036},{"style":923},[8037],{"type":35,"value":2881},{"type":29,"tag":901,"props":8039,"children":8040},{"style":5185},[8041],{"type":35,"value":7332},{"type":29,"tag":901,"props":8043,"children":8044},{"class":903,"line":1274},[8045],{"type":29,"tag":901,"props":8046,"children":8047},{"emptyLinePlaceholder":13},[8048],{"type":35,"value":974},{"type":29,"tag":901,"props":8050,"children":8051},{"class":903,"line":487},[8052,8056,8060,8064,8068,8072,8077,8082],{"type":29,"tag":901,"props":8053,"children":8054},{"style":917},[8055],{"type":35,"value":5512},{"type":29,"tag":901,"props":8057,"children":8058},{"style":7724},[8059],{"type":35,"value":7727},{"type":29,"tag":901,"props":8061,"children":8062},{"style":7730},[8063],{"type":35,"value":342},{"type":29,"tag":901,"props":8065,"children":8066},{"style":923},[8067],{"type":35,"value":6137},{"type":29,"tag":901,"props":8069,"children":8070},{"style":7730},[8071],{"type":35,"value":342},{"type":29,"tag":901,"props":8073,"children":8074},{"style":5362},[8075],{"type":35,"value":8076},"findById",{"type":29,"tag":901,"props":8078,"children":8079},{"style":923},[8080],{"type":35,"value":8081},"(orderId)",{"type":29,"tag":901,"props":8083,"children":8084},{"style":5185},[8085],{"type":35,"value":7332},{"type":29,"tag":901,"props":8087,"children":8088},{"class":903,"line":11},[8089],{"type":29,"tag":901,"props":8090,"children":8091},{"style":5185},[8092],{"type":35,"value":8093},"    }\n",{"type":29,"tag":901,"props":8095,"children":8096},{"class":903,"line":2121},[8097],{"type":29,"tag":901,"props":8098,"children":8099},{"style":5185},[8100],{"type":35,"value":7406},{"type":29,"tag":901,"props":8102,"children":8104},{"class":903,"line":8103},38,[8105],{"type":29,"tag":901,"props":8106,"children":8107},{"emptyLinePlaceholder":13},[8108],{"type":35,"value":974},{"type":29,"tag":901,"props":8110,"children":8112},{"class":903,"line":8111},39,[8113],{"type":29,"tag":901,"props":8114,"children":8115},{"style":908},[8116],{"type":35,"value":8117},"// Test — sans Stripe, sans base de données\n",{"type":29,"tag":901,"props":8119,"children":8121},{"class":903,"line":8120},40,[8122,8127,8131,8136,8140,8145,8150],{"type":29,"tag":901,"props":8123,"children":8124},{"style":5362},[8125],{"type":35,"value":8126},"describe",{"type":29,"tag":901,"props":8128,"children":8129},{"style":923},[8130],{"type":35,"value":3080},{"type":29,"tag":901,"props":8132,"children":8133},{"style":2236},[8134],{"type":35,"value":8135},"'OrderService'",{"type":29,"tag":901,"props":8137,"children":8138},{"style":5185},[8139],{"type":35,"value":3663},{"type":29,"tag":901,"props":8141,"children":8142},{"style":5185},[8143],{"type":35,"value":8144}," ()",{"type":29,"tag":901,"props":8146,"children":8147},{"style":947},[8148],{"type":35,"value":8149}," =>",{"type":29,"tag":901,"props":8151,"children":8152},{"style":5185},[8153],{"type":35,"value":7272},{"type":29,"tag":901,"props":8155,"children":8157},{"class":903,"line":8156},41,[8158,8163,8167,8172,8176,8181,8185,8189],{"type":29,"tag":901,"props":8159,"children":8160},{"style":5362},[8161],{"type":35,"value":8162},"    it",{"type":29,"tag":901,"props":8164,"children":8165},{"style":923},[8166],{"type":35,"value":3080},{"type":29,"tag":901,"props":8168,"children":8169},{"style":2236},[8170],{"type":35,"value":8171},"'should create order with successful payment'",{"type":29,"tag":901,"props":8173,"children":8174},{"style":5185},[8175],{"type":35,"value":3663},{"type":29,"tag":901,"props":8177,"children":8178},{"style":917},[8179],{"type":35,"value":8180}," async",{"type":29,"tag":901,"props":8182,"children":8183},{"style":5185},[8184],{"type":35,"value":8144},{"type":29,"tag":901,"props":8186,"children":8187},{"style":947},[8188],{"type":35,"value":8149},{"type":29,"tag":901,"props":8190,"children":8191},{"style":5185},[8192],{"type":35,"value":7272},{"type":29,"tag":901,"props":8194,"children":8196},{"class":903,"line":8195},42,[8197,8201,8206,8210,8214,8218],{"type":29,"tag":901,"props":8198,"children":8199},{"style":917},[8200],{"type":35,"value":7707},{"type":29,"tag":901,"props":8202,"children":8203},{"style":5674},[8204],{"type":35,"value":8205}," mockRepository",{"type":29,"tag":901,"props":8207,"children":8208},{"style":947},[8209],{"type":35,"value":5760},{"type":29,"tag":901,"props":8211,"children":8212},{"style":5179},[8213],{"type":35,"value":5705},{"type":29,"tag":901,"props":8215,"children":8216},{"style":947},[8217],{"type":35,"value":6944},{"type":29,"tag":901,"props":8219,"children":8220},{"style":5185},[8221],{"type":35,"value":7272},{"type":29,"tag":901,"props":8223,"children":8225},{"class":903,"line":8224},43,[8226,8231,8235,8240,8244,8249,8254,8258,8263,8267,8272,8276],{"type":29,"tag":901,"props":8227,"children":8228},{"style":923},[8229],{"type":35,"value":8230},"            save",{"type":29,"tag":901,"props":8232,"children":8233},{"style":7730},[8234],{"type":35,"value":5760},{"type":29,"tag":901,"props":8236,"children":8237},{"style":923},[8238],{"type":35,"value":8239}," jest",{"type":29,"tag":901,"props":8241,"children":8242},{"style":7730},[8243],{"type":35,"value":342},{"type":29,"tag":901,"props":8245,"children":8246},{"style":5362},[8247],{"type":35,"value":8248},"fn",{"type":29,"tag":901,"props":8250,"children":8251},{"style":923},[8252],{"type":35,"value":8253},"()",{"type":29,"tag":901,"props":8255,"children":8256},{"style":7730},[8257],{"type":35,"value":342},{"type":29,"tag":901,"props":8259,"children":8260},{"style":5362},[8261],{"type":35,"value":8262},"mockResolvedValue",{"type":29,"tag":901,"props":8264,"children":8265},{"style":923},[8266],{"type":35,"value":3080},{"type":29,"tag":901,"props":8268,"children":8269},{"style":2236},[8270],{"type":35,"value":8271},"'order-123'",{"type":29,"tag":901,"props":8273,"children":8274},{"style":923},[8275],{"type":35,"value":2881},{"type":29,"tag":901,"props":8277,"children":8278},{"style":5185},[8279],{"type":35,"value":7598},{"type":29,"tag":901,"props":8281,"children":8283},{"class":903,"line":8282},44,[8284,8289,8293,8297,8301,8305,8309,8313,8317,8321,8325,8330,8334,8339,8343,8348,8352,8357,8362],{"type":29,"tag":901,"props":8285,"children":8286},{"style":923},[8287],{"type":35,"value":8288},"            findById",{"type":29,"tag":901,"props":8290,"children":8291},{"style":7730},[8292],{"type":35,"value":5760},{"type":29,"tag":901,"props":8294,"children":8295},{"style":923},[8296],{"type":35,"value":8239},{"type":29,"tag":901,"props":8298,"children":8299},{"style":7730},[8300],{"type":35,"value":342},{"type":29,"tag":901,"props":8302,"children":8303},{"style":5362},[8304],{"type":35,"value":8248},{"type":29,"tag":901,"props":8306,"children":8307},{"style":923},[8308],{"type":35,"value":8253},{"type":29,"tag":901,"props":8310,"children":8311},{"style":7730},[8312],{"type":35,"value":342},{"type":29,"tag":901,"props":8314,"children":8315},{"style":5362},[8316],{"type":35,"value":8262},{"type":29,"tag":901,"props":8318,"children":8319},{"style":923},[8320],{"type":35,"value":3080},{"type":29,"tag":901,"props":8322,"children":8323},{"style":5185},[8324],{"type":35,"value":2245},{"type":29,"tag":901,"props":8326,"children":8327},{"style":923},[8328],{"type":35,"value":8329}," id",{"type":29,"tag":901,"props":8331,"children":8332},{"style":7730},[8333],{"type":35,"value":5760},{"type":29,"tag":901,"props":8335,"children":8336},{"style":2236},[8337],{"type":35,"value":8338}," 'order-123'",{"type":29,"tag":901,"props":8340,"children":8341},{"style":5185},[8342],{"type":35,"value":3663},{"type":29,"tag":901,"props":8344,"children":8345},{"style":923},[8346],{"type":35,"value":8347}," status",{"type":29,"tag":901,"props":8349,"children":8350},{"style":7730},[8351],{"type":35,"value":5760},{"type":29,"tag":901,"props":8353,"children":8354},{"style":2236},[8355],{"type":35,"value":8356}," 'paid'",{"type":29,"tag":901,"props":8358,"children":8359},{"style":5185},[8360],{"type":35,"value":8361}," }",{"type":29,"tag":901,"props":8363,"children":8364},{"style":923},[8365],{"type":35,"value":5437},{"type":29,"tag":901,"props":8367,"children":8369},{"class":903,"line":8368},45,[8370],{"type":29,"tag":901,"props":8371,"children":8372},{"style":5185},[8373],{"type":35,"value":8374},"        };\n",{"type":29,"tag":901,"props":8376,"children":8378},{"class":903,"line":8377},46,[8379],{"type":29,"tag":901,"props":8380,"children":8381},{"emptyLinePlaceholder":13},[8382],{"type":35,"value":974},{"type":29,"tag":901,"props":8384,"children":8386},{"class":903,"line":8385},47,[8387,8391,8396,8400,8404,8408],{"type":29,"tag":901,"props":8388,"children":8389},{"style":917},[8390],{"type":35,"value":7707},{"type":29,"tag":901,"props":8392,"children":8393},{"style":5674},[8394],{"type":35,"value":8395}," mockPayment",{"type":29,"tag":901,"props":8397,"children":8398},{"style":947},[8399],{"type":35,"value":5760},{"type":29,"tag":901,"props":8401,"children":8402},{"style":5179},[8403],{"type":35,"value":7425},{"type":29,"tag":901,"props":8405,"children":8406},{"style":947},[8407],{"type":35,"value":6944},{"type":29,"tag":901,"props":8409,"children":8410},{"style":5185},[8411],{"type":35,"value":7272},{"type":29,"tag":901,"props":8413,"children":8415},{"class":903,"line":8414},48,[8416,8421,8425,8429,8433,8437,8441,8445,8449,8453,8457,8462,8466,8471,8475,8480,8484,8489,8493],{"type":29,"tag":901,"props":8417,"children":8418},{"style":923},[8419],{"type":35,"value":8420},"            charge",{"type":29,"tag":901,"props":8422,"children":8423},{"style":7730},[8424],{"type":35,"value":5760},{"type":29,"tag":901,"props":8426,"children":8427},{"style":923},[8428],{"type":35,"value":8239},{"type":29,"tag":901,"props":8430,"children":8431},{"style":7730},[8432],{"type":35,"value":342},{"type":29,"tag":901,"props":8434,"children":8435},{"style":5362},[8436],{"type":35,"value":8248},{"type":29,"tag":901,"props":8438,"children":8439},{"style":923},[8440],{"type":35,"value":8253},{"type":29,"tag":901,"props":8442,"children":8443},{"style":7730},[8444],{"type":35,"value":342},{"type":29,"tag":901,"props":8446,"children":8447},{"style":5362},[8448],{"type":35,"value":8262},{"type":29,"tag":901,"props":8450,"children":8451},{"style":923},[8452],{"type":35,"value":3080},{"type":29,"tag":901,"props":8454,"children":8455},{"style":5185},[8456],{"type":35,"value":2245},{"type":29,"tag":901,"props":8458,"children":8459},{"style":923},[8460],{"type":35,"value":8461}," success",{"type":29,"tag":901,"props":8463,"children":8464},{"style":7730},[8465],{"type":35,"value":5760},{"type":29,"tag":901,"props":8467,"children":8468},{"style":5280},[8469],{"type":35,"value":8470}," true",{"type":29,"tag":901,"props":8472,"children":8473},{"style":5185},[8474],{"type":35,"value":3663},{"type":29,"tag":901,"props":8476,"children":8477},{"style":923},[8478],{"type":35,"value":8479}," transactionId",{"type":29,"tag":901,"props":8481,"children":8482},{"style":7730},[8483],{"type":35,"value":5760},{"type":29,"tag":901,"props":8485,"children":8486},{"style":2236},[8487],{"type":35,"value":8488}," 'txn-456'",{"type":29,"tag":901,"props":8490,"children":8491},{"style":5185},[8492],{"type":35,"value":8361},{"type":29,"tag":901,"props":8494,"children":8495},{"style":923},[8496],{"type":35,"value":5437},{"type":29,"tag":901,"props":8498,"children":8500},{"class":903,"line":8499},49,[8501],{"type":29,"tag":901,"props":8502,"children":8503},{"style":5185},[8504],{"type":35,"value":8374},{"type":29,"tag":901,"props":8506,"children":8508},{"class":903,"line":8507},50,[8509],{"type":29,"tag":901,"props":8510,"children":8511},{"emptyLinePlaceholder":13},[8512],{"type":35,"value":974},{"type":29,"tag":901,"props":8514,"children":8516},{"class":903,"line":8515},51,[8517,8521,8525,8529,8533,8537,8542,8546,8551],{"type":29,"tag":901,"props":8518,"children":8519},{"style":917},[8520],{"type":35,"value":7707},{"type":29,"tag":901,"props":8522,"children":8523},{"style":5674},[8524],{"type":35,"value":7083},{"type":29,"tag":901,"props":8526,"children":8527},{"style":947},[8528],{"type":35,"value":6944},{"type":29,"tag":901,"props":8530,"children":8531},{"style":7874},[8532],{"type":35,"value":7877},{"type":29,"tag":901,"props":8534,"children":8535},{"style":5362},[8536],{"type":35,"value":5182},{"type":29,"tag":901,"props":8538,"children":8539},{"style":923},[8540],{"type":35,"value":8541},"(mockRepository",{"type":29,"tag":901,"props":8543,"children":8544},{"style":5185},[8545],{"type":35,"value":3663},{"type":29,"tag":901,"props":8547,"children":8548},{"style":923},[8549],{"type":35,"value":8550}," mockPayment)",{"type":29,"tag":901,"props":8552,"children":8553},{"style":5185},[8554],{"type":35,"value":7332},{"type":29,"tag":901,"props":8556,"children":8558},{"class":903,"line":8557},52,[8559,8563,8568,8572,8576,8580,8584,8589,8593,8597,8602,8606,8611,8615,8619,8623,8628,8632,8636],{"type":29,"tag":901,"props":8560,"children":8561},{"style":917},[8562],{"type":35,"value":7707},{"type":29,"tag":901,"props":8564,"children":8565},{"style":5674},[8566],{"type":35,"value":8567}," order",{"type":29,"tag":901,"props":8569,"children":8570},{"style":947},[8571],{"type":35,"value":6944},{"type":29,"tag":901,"props":8573,"children":8574},{"style":917},[8575],{"type":35,"value":7721},{"type":29,"tag":901,"props":8577,"children":8578},{"style":923},[8579],{"type":35,"value":7083},{"type":29,"tag":901,"props":8581,"children":8582},{"style":7730},[8583],{"type":35,"value":342},{"type":29,"tag":901,"props":8585,"children":8586},{"style":5362},[8587],{"type":35,"value":8588},"createPaidOrder",{"type":29,"tag":901,"props":8590,"children":8591},{"style":923},[8592],{"type":35,"value":3080},{"type":29,"tag":901,"props":8594,"children":8595},{"style":5185},[8596],{"type":35,"value":2245},{"type":29,"tag":901,"props":8598,"children":8599},{"style":923},[8600],{"type":35,"value":8601}," total",{"type":29,"tag":901,"props":8603,"children":8604},{"style":7730},[8605],{"type":35,"value":5760},{"type":29,"tag":901,"props":8607,"children":8608},{"style":5280},[8609],{"type":35,"value":8610}," 1000",{"type":29,"tag":901,"props":8612,"children":8613},{"style":5185},[8614],{"type":35,"value":3663},{"type":29,"tag":901,"props":8616,"children":8617},{"style":923},[8618],{"type":35,"value":7464},{"type":29,"tag":901,"props":8620,"children":8621},{"style":7730},[8622],{"type":35,"value":5760},{"type":29,"tag":901,"props":8624,"children":8625},{"style":2236},[8626],{"type":35,"value":8627}," 'EUR'",{"type":29,"tag":901,"props":8629,"children":8630},{"style":5185},[8631],{"type":35,"value":8361},{"type":29,"tag":901,"props":8633,"children":8634},{"style":923},[8635],{"type":35,"value":2881},{"type":29,"tag":901,"props":8637,"children":8638},{"style":5185},[8639],{"type":35,"value":7332},{"type":29,"tag":901,"props":8641,"children":8643},{"class":903,"line":8642},53,[8644],{"type":29,"tag":901,"props":8645,"children":8646},{"emptyLinePlaceholder":13},[8647],{"type":35,"value":974},{"type":29,"tag":901,"props":8649,"children":8651},{"class":903,"line":8650},54,[8652,8657,8662,8666,8671,8675,8680,8684,8689,8693],{"type":29,"tag":901,"props":8653,"children":8654},{"style":5362},[8655],{"type":35,"value":8656},"        expect",{"type":29,"tag":901,"props":8658,"children":8659},{"style":923},[8660],{"type":35,"value":8661},"(order",{"type":29,"tag":901,"props":8663,"children":8664},{"style":7730},[8665],{"type":35,"value":342},{"type":29,"tag":901,"props":8667,"children":8668},{"style":923},[8669],{"type":35,"value":8670},"status)",{"type":29,"tag":901,"props":8672,"children":8673},{"style":7730},[8674],{"type":35,"value":342},{"type":29,"tag":901,"props":8676,"children":8677},{"style":5362},[8678],{"type":35,"value":8679},"toBe",{"type":29,"tag":901,"props":8681,"children":8682},{"style":923},[8683],{"type":35,"value":3080},{"type":29,"tag":901,"props":8685,"children":8686},{"style":2236},[8687],{"type":35,"value":8688},"'paid'",{"type":29,"tag":901,"props":8690,"children":8691},{"style":923},[8692],{"type":35,"value":2881},{"type":29,"tag":901,"props":8694,"children":8695},{"style":5185},[8696],{"type":35,"value":7332},{"type":29,"tag":901,"props":8698,"children":8700},{"class":903,"line":8699},55,[8701,8706,8710],{"type":29,"tag":901,"props":8702,"children":8703},{"style":5185},[8704],{"type":35,"value":8705},"    }",{"type":29,"tag":901,"props":8707,"children":8708},{"style":923},[8709],{"type":35,"value":2881},{"type":29,"tag":901,"props":8711,"children":8712},{"style":5185},[8713],{"type":35,"value":7332},{"type":29,"tag":901,"props":8715,"children":8717},{"class":903,"line":8716},56,[8718,8722,8726],{"type":29,"tag":901,"props":8719,"children":8720},{"style":5185},[8721],{"type":35,"value":2255},{"type":29,"tag":901,"props":8723,"children":8724},{"style":923},[8725],{"type":35,"value":2881},{"type":29,"tag":901,"props":8727,"children":8728},{"style":5185},[8729],{"type":35,"value":7332},{"type":29,"tag":37,"props":8731,"children":8732},{},[8733,8738],{"type":29,"tag":65,"props":8734,"children":8735},{},[8736],{"type":35,"value":8737},"L'avantage TypeScript :",{"type":35,"value":8739}," les interfaces sont vérifiées à la compilation. Si une implémentation ne respecte pas l'interface, le compilateur rejette le code avant même l'exécution.",{"type":29,"tag":76,"props":8741,"children":8742},{},[],{"type":29,"tag":80,"props":8744,"children":8746},{"id":8745},"exemple-3-java-le-dip-avec-spring",[8747],{"type":35,"value":8748},"Exemple 3 : Java, le DIP avec Spring",{"type":29,"tag":651,"props":8750,"children":8754},{"code":8751,"language":8752,"meta":8,"className":8753,"style":8},"// L'abstraction\npublic interface NotificationService {\n    void sendOrderConfirmation(String userId, String orderId);\n    void sendShippingUpdate(String userId, String orderId, String trackingCode);\n}\n\n// Le module de haut niveau (service métier)\n@Service\npublic class OrderFulfillmentService {\n\n    private final OrderRepository orderRepository;\n    private final NotificationService notificationService;\n\n    public OrderFulfillmentService(\n            OrderRepository orderRepository,\n            NotificationService notificationService) {\n        this.orderRepository = orderRepository;\n        this.notificationService = notificationService;\n    }\n\n    public void fulfillOrder(String orderId) {\n        Order order = orderRepository.findById(orderId)\n            .orElseThrow(() -> new OrderNotFoundException(orderId));\n\n        order.setStatus(OrderStatus.FULFILLING);\n        orderRepository.save(order);\n\n        notificationService.sendOrderConfirmation(order.getUserId(), orderId);\n    }\n}\n\n// Implémentation de test\n@Service\n@Profile(\"test\")\npublic class MockNotificationService implements NotificationService {\n\n    private final List\u003CString> sentNotifications = new ArrayList\u003C>();\n\n    @Override\n    public void sendOrderConfirmation(String userId, String orderId) {\n        sentNotifications.add(\"confirmation:\" + userId + \":\" + orderId);\n    }\n}\n","java","language-java shiki shiki-themes catppuccin-frappe github-dark",[8755],{"type":29,"tag":565,"props":8756,"children":8757},{"__ignoreMap":8},[8758,8766,8788,8834,8887,8894,8901,8909,8924,8945,8952,8978,9002,9009,9025,9041,9061,9090,9118,9125,9132,9169,9210,9254,9261,9300,9329,9336,9383,9390,9397,9404,9412,9423,9448,9477,9484,9535,9542,9555,9602,9660,9667],{"type":29,"tag":901,"props":8759,"children":8760},{"class":903,"line":904},[8761],{"type":29,"tag":901,"props":8762,"children":8763},{"style":908},[8764],{"type":35,"value":8765},"// L'abstraction\n",{"type":29,"tag":901,"props":8767,"children":8768},{"class":903,"line":463},[8769,8774,8779,8784],{"type":29,"tag":901,"props":8770,"children":8771},{"style":917},[8772],{"type":35,"value":8773},"public",{"type":29,"tag":901,"props":8775,"children":8776},{"style":917},[8777],{"type":35,"value":8778}," interface",{"type":29,"tag":901,"props":8780,"children":8781},{"style":5179},[8782],{"type":35,"value":8783}," NotificationService",{"type":29,"tag":901,"props":8785,"children":8786},{"style":5185},[8787],{"type":35,"value":7272},{"type":29,"tag":901,"props":8789,"children":8790},{"class":903,"line":469},[8791,8796,8801,8805,8811,8816,8820,8825,8829],{"type":29,"tag":901,"props":8792,"children":8793},{"style":917},[8794],{"type":35,"value":8795},"    void",{"type":29,"tag":901,"props":8797,"children":8798},{"style":5362},[8799],{"type":35,"value":8800}," sendOrderConfirmation",{"type":29,"tag":901,"props":8802,"children":8803},{"style":5185},[8804],{"type":35,"value":3080},{"type":29,"tag":901,"props":8806,"children":8808},{"style":8807},"--shiki-default:#CA9EE6;--shiki-dark:#E1E4E8",[8809],{"type":35,"value":8810},"String",{"type":29,"tag":901,"props":8812,"children":8813},{"style":5252},[8814],{"type":35,"value":8815}," userId",{"type":29,"tag":901,"props":8817,"children":8818},{"style":5185},[8819],{"type":35,"value":3663},{"type":29,"tag":901,"props":8821,"children":8822},{"style":8807},[8823],{"type":35,"value":8824}," String",{"type":29,"tag":901,"props":8826,"children":8827},{"style":5252},[8828],{"type":35,"value":7927},{"type":29,"tag":901,"props":8830,"children":8831},{"style":5185},[8832],{"type":35,"value":8833},");\n",{"type":29,"tag":901,"props":8835,"children":8836},{"class":903,"line":968},[8837,8841,8846,8850,8854,8858,8862,8866,8870,8874,8878,8883],{"type":29,"tag":901,"props":8838,"children":8839},{"style":917},[8840],{"type":35,"value":8795},{"type":29,"tag":901,"props":8842,"children":8843},{"style":5362},[8844],{"type":35,"value":8845}," sendShippingUpdate",{"type":29,"tag":901,"props":8847,"children":8848},{"style":5185},[8849],{"type":35,"value":3080},{"type":29,"tag":901,"props":8851,"children":8852},{"style":8807},[8853],{"type":35,"value":8810},{"type":29,"tag":901,"props":8855,"children":8856},{"style":5252},[8857],{"type":35,"value":8815},{"type":29,"tag":901,"props":8859,"children":8860},{"style":5185},[8861],{"type":35,"value":3663},{"type":29,"tag":901,"props":8863,"children":8864},{"style":8807},[8865],{"type":35,"value":8824},{"type":29,"tag":901,"props":8867,"children":8868},{"style":5252},[8869],{"type":35,"value":7927},{"type":29,"tag":901,"props":8871,"children":8872},{"style":5185},[8873],{"type":35,"value":3663},{"type":29,"tag":901,"props":8875,"children":8876},{"style":8807},[8877],{"type":35,"value":8824},{"type":29,"tag":901,"props":8879,"children":8880},{"style":5252},[8881],{"type":35,"value":8882}," trackingCode",{"type":29,"tag":901,"props":8884,"children":8885},{"style":5185},[8886],{"type":35,"value":8833},{"type":29,"tag":901,"props":8888,"children":8889},{"class":903,"line":977},[8890],{"type":29,"tag":901,"props":8891,"children":8892},{"style":5185},[8893],{"type":35,"value":7406},{"type":29,"tag":901,"props":8895,"children":8896},{"class":903,"line":986},[8897],{"type":29,"tag":901,"props":8898,"children":8899},{"emptyLinePlaceholder":13},[8900],{"type":35,"value":974},{"type":29,"tag":901,"props":8902,"children":8903},{"class":903,"line":1007},[8904],{"type":29,"tag":901,"props":8905,"children":8906},{"style":908},[8907],{"type":35,"value":8908},"// Le module de haut niveau (service métier)\n",{"type":29,"tag":901,"props":8910,"children":8911},{"class":903,"line":5354},[8912,8918],{"type":29,"tag":901,"props":8913,"children":8915},{"style":8914},"--shiki-default:#EF9F76;--shiki-dark:#E1E4E8",[8916],{"type":35,"value":8917},"@",{"type":29,"tag":901,"props":8919,"children":8921},{"style":8920},"--shiki-default:#EF9F76;--shiki-dark:#F97583",[8922],{"type":35,"value":8923},"Service\n",{"type":29,"tag":901,"props":8925,"children":8926},{"class":903,"line":5390},[8927,8931,8936,8941],{"type":29,"tag":901,"props":8928,"children":8929},{"style":917},[8930],{"type":35,"value":8773},{"type":29,"tag":901,"props":8932,"children":8933},{"style":917},[8934],{"type":35,"value":8935}," class",{"type":29,"tag":901,"props":8937,"children":8938},{"style":5179},[8939],{"type":35,"value":8940}," OrderFulfillmentService",{"type":29,"tag":901,"props":8942,"children":8943},{"style":5185},[8944],{"type":35,"value":7272},{"type":29,"tag":901,"props":8946,"children":8947},{"class":903,"line":5440},[8948],{"type":29,"tag":901,"props":8949,"children":8950},{"emptyLinePlaceholder":13},[8951],{"type":35,"value":974},{"type":29,"tag":901,"props":8953,"children":8954},{"class":903,"line":5506},[8955,8960,8965,8969,8974],{"type":29,"tag":901,"props":8956,"children":8957},{"style":917},[8958],{"type":35,"value":8959},"    private",{"type":29,"tag":901,"props":8961,"children":8962},{"style":917},[8963],{"type":35,"value":8964}," final",{"type":29,"tag":901,"props":8966,"children":8967},{"style":8807},[8968],{"type":35,"value":5705},{"type":29,"tag":901,"props":8970,"children":8971},{"style":923},[8972],{"type":35,"value":8973}," orderRepository",{"type":29,"tag":901,"props":8975,"children":8976},{"style":5185},[8977],{"type":35,"value":7332},{"type":29,"tag":901,"props":8979,"children":8980},{"class":903,"line":5911},[8981,8985,8989,8993,8998],{"type":29,"tag":901,"props":8982,"children":8983},{"style":917},[8984],{"type":35,"value":8959},{"type":29,"tag":901,"props":8986,"children":8987},{"style":917},[8988],{"type":35,"value":8964},{"type":29,"tag":901,"props":8990,"children":8991},{"style":8807},[8992],{"type":35,"value":8783},{"type":29,"tag":901,"props":8994,"children":8995},{"style":923},[8996],{"type":35,"value":8997}," notificationService",{"type":29,"tag":901,"props":8999,"children":9000},{"style":5185},[9001],{"type":35,"value":7332},{"type":29,"tag":901,"props":9003,"children":9004},{"class":903,"line":5919},[9005],{"type":29,"tag":901,"props":9006,"children":9007},{"emptyLinePlaceholder":13},[9008],{"type":35,"value":974},{"type":29,"tag":901,"props":9010,"children":9011},{"class":903,"line":5928},[9012,9017,9021],{"type":29,"tag":901,"props":9013,"children":9014},{"style":917},[9015],{"type":35,"value":9016},"    public",{"type":29,"tag":901,"props":9018,"children":9019},{"style":5362},[9020],{"type":35,"value":8940},{"type":29,"tag":901,"props":9022,"children":9023},{"style":5185},[9024],{"type":35,"value":7568},{"type":29,"tag":901,"props":9026,"children":9027},{"class":903,"line":5944},[9028,9033,9037],{"type":29,"tag":901,"props":9029,"children":9030},{"style":8807},[9031],{"type":35,"value":9032},"            OrderRepository",{"type":29,"tag":901,"props":9034,"children":9035},{"style":5252},[9036],{"type":35,"value":8973},{"type":29,"tag":901,"props":9038,"children":9039},{"style":5185},[9040],{"type":35,"value":7598},{"type":29,"tag":901,"props":9042,"children":9043},{"class":903,"line":6003},[9044,9049,9053,9057],{"type":29,"tag":901,"props":9045,"children":9046},{"style":8807},[9047],{"type":35,"value":9048},"            NotificationService",{"type":29,"tag":901,"props":9050,"children":9051},{"style":5252},[9052],{"type":35,"value":8997},{"type":29,"tag":901,"props":9054,"children":9055},{"style":5185},[9056],{"type":35,"value":2881},{"type":29,"tag":901,"props":9058,"children":9059},{"style":5185},[9060],{"type":35,"value":7272},{"type":29,"tag":901,"props":9062,"children":9063},{"class":903,"line":6029},[9064,9069,9073,9078,9082,9086],{"type":29,"tag":901,"props":9065,"children":9066},{"style":7724},[9067],{"type":35,"value":9068},"        this",{"type":29,"tag":901,"props":9070,"children":9071},{"style":5185},[9072],{"type":35,"value":342},{"type":29,"tag":901,"props":9074,"children":9075},{"style":923},[9076],{"type":35,"value":9077},"orderRepository ",{"type":29,"tag":901,"props":9079,"children":9080},{"style":947},[9081],{"type":35,"value":2227},{"type":29,"tag":901,"props":9083,"children":9084},{"style":923},[9085],{"type":35,"value":8973},{"type":29,"tag":901,"props":9087,"children":9088},{"style":5185},[9089],{"type":35,"value":7332},{"type":29,"tag":901,"props":9091,"children":9092},{"class":903,"line":6055},[9093,9097,9101,9106,9110,9114],{"type":29,"tag":901,"props":9094,"children":9095},{"style":7724},[9096],{"type":35,"value":9068},{"type":29,"tag":901,"props":9098,"children":9099},{"style":5185},[9100],{"type":35,"value":342},{"type":29,"tag":901,"props":9102,"children":9103},{"style":923},[9104],{"type":35,"value":9105},"notificationService ",{"type":29,"tag":901,"props":9107,"children":9108},{"style":947},[9109],{"type":35,"value":2227},{"type":29,"tag":901,"props":9111,"children":9112},{"style":923},[9113],{"type":35,"value":8997},{"type":29,"tag":901,"props":9115,"children":9116},{"style":5185},[9117],{"type":35,"value":7332},{"type":29,"tag":901,"props":9119,"children":9120},{"class":903,"line":6063},[9121],{"type":29,"tag":901,"props":9122,"children":9123},{"style":5185},[9124],{"type":35,"value":8093},{"type":29,"tag":901,"props":9126,"children":9127},{"class":903,"line":6115},[9128],{"type":29,"tag":901,"props":9129,"children":9130},{"emptyLinePlaceholder":13},[9131],{"type":35,"value":974},{"type":29,"tag":901,"props":9133,"children":9134},{"class":903,"line":6160},[9135,9139,9144,9149,9153,9157,9161,9165],{"type":29,"tag":901,"props":9136,"children":9137},{"style":917},[9138],{"type":35,"value":9016},{"type":29,"tag":901,"props":9140,"children":9141},{"style":917},[9142],{"type":35,"value":9143}," void",{"type":29,"tag":901,"props":9145,"children":9146},{"style":5362},[9147],{"type":35,"value":9148}," fulfillOrder",{"type":29,"tag":901,"props":9150,"children":9151},{"style":5185},[9152],{"type":35,"value":3080},{"type":29,"tag":901,"props":9154,"children":9155},{"style":8807},[9156],{"type":35,"value":8810},{"type":29,"tag":901,"props":9158,"children":9159},{"style":5252},[9160],{"type":35,"value":7927},{"type":29,"tag":901,"props":9162,"children":9163},{"style":5185},[9164],{"type":35,"value":2881},{"type":29,"tag":901,"props":9166,"children":9167},{"style":5185},[9168],{"type":35,"value":7272},{"type":29,"tag":901,"props":9170,"children":9171},{"class":903,"line":6221},[9172,9177,9182,9186,9190,9194,9198,9202,9206],{"type":29,"tag":901,"props":9173,"children":9174},{"style":8807},[9175],{"type":35,"value":9176},"        Order",{"type":29,"tag":901,"props":9178,"children":9179},{"style":923},[9180],{"type":35,"value":9181}," order ",{"type":29,"tag":901,"props":9183,"children":9184},{"style":947},[9185],{"type":35,"value":2227},{"type":29,"tag":901,"props":9187,"children":9188},{"style":923},[9189],{"type":35,"value":8973},{"type":29,"tag":901,"props":9191,"children":9192},{"style":5185},[9193],{"type":35,"value":342},{"type":29,"tag":901,"props":9195,"children":9196},{"style":5362},[9197],{"type":35,"value":8076},{"type":29,"tag":901,"props":9199,"children":9200},{"style":5185},[9201],{"type":35,"value":3080},{"type":29,"tag":901,"props":9203,"children":9204},{"style":923},[9205],{"type":35,"value":7349},{"type":29,"tag":901,"props":9207,"children":9208},{"style":5185},[9209],{"type":35,"value":5437},{"type":29,"tag":901,"props":9211,"children":9212},{"class":903,"line":6233},[9213,9218,9223,9228,9232,9236,9241,9245,9249],{"type":29,"tag":901,"props":9214,"children":9215},{"style":5185},[9216],{"type":35,"value":9217},"            .",{"type":29,"tag":901,"props":9219,"children":9220},{"style":5362},[9221],{"type":35,"value":9222},"orElseThrow",{"type":29,"tag":901,"props":9224,"children":9225},{"style":5185},[9226],{"type":35,"value":9227},"(()",{"type":29,"tag":901,"props":9229,"children":9230},{"style":917},[9231],{"type":35,"value":5775},{"type":29,"tag":901,"props":9233,"children":9234},{"style":917},[9235],{"type":35,"value":7877},{"type":29,"tag":901,"props":9237,"children":9238},{"style":5362},[9239],{"type":35,"value":9240}," OrderNotFoundException",{"type":29,"tag":901,"props":9242,"children":9243},{"style":5185},[9244],{"type":35,"value":3080},{"type":29,"tag":901,"props":9246,"children":9247},{"style":923},[9248],{"type":35,"value":7349},{"type":29,"tag":901,"props":9250,"children":9251},{"style":5185},[9252],{"type":35,"value":9253},"));\n",{"type":29,"tag":901,"props":9255,"children":9256},{"class":903,"line":6241},[9257],{"type":29,"tag":901,"props":9258,"children":9259},{"emptyLinePlaceholder":13},[9260],{"type":35,"value":974},{"type":29,"tag":901,"props":9262,"children":9263},{"class":903,"line":6250},[9264,9269,9273,9278,9282,9287,9291,9296],{"type":29,"tag":901,"props":9265,"children":9266},{"style":923},[9267],{"type":35,"value":9268},"        order",{"type":29,"tag":901,"props":9270,"children":9271},{"style":5185},[9272],{"type":35,"value":342},{"type":29,"tag":901,"props":9274,"children":9275},{"style":5362},[9276],{"type":35,"value":9277},"setStatus",{"type":29,"tag":901,"props":9279,"children":9280},{"style":5185},[9281],{"type":35,"value":3080},{"type":29,"tag":901,"props":9283,"children":9284},{"style":923},[9285],{"type":35,"value":9286},"OrderStatus",{"type":29,"tag":901,"props":9288,"children":9289},{"style":5185},[9290],{"type":35,"value":342},{"type":29,"tag":901,"props":9292,"children":9293},{"style":923},[9294],{"type":35,"value":9295},"FULFILLING",{"type":29,"tag":901,"props":9297,"children":9298},{"style":5185},[9299],{"type":35,"value":8833},{"type":29,"tag":901,"props":9301,"children":9302},{"class":903,"line":6275},[9303,9308,9312,9316,9320,9325],{"type":29,"tag":901,"props":9304,"children":9305},{"style":923},[9306],{"type":35,"value":9307},"        orderRepository",{"type":29,"tag":901,"props":9309,"children":9310},{"style":5185},[9311],{"type":35,"value":342},{"type":29,"tag":901,"props":9313,"children":9314},{"style":5362},[9315],{"type":35,"value":5423},{"type":29,"tag":901,"props":9317,"children":9318},{"style":5185},[9319],{"type":35,"value":3080},{"type":29,"tag":901,"props":9321,"children":9322},{"style":923},[9323],{"type":35,"value":9324},"order",{"type":29,"tag":901,"props":9326,"children":9327},{"style":5185},[9328],{"type":35,"value":8833},{"type":29,"tag":901,"props":9330,"children":9331},{"class":903,"line":6327},[9332],{"type":29,"tag":901,"props":9333,"children":9334},{"emptyLinePlaceholder":13},[9335],{"type":35,"value":974},{"type":29,"tag":901,"props":9337,"children":9338},{"class":903,"line":6377},[9339,9344,9348,9353,9357,9361,9365,9370,9375,9379],{"type":29,"tag":901,"props":9340,"children":9341},{"style":923},[9342],{"type":35,"value":9343},"        notificationService",{"type":29,"tag":901,"props":9345,"children":9346},{"style":5185},[9347],{"type":35,"value":342},{"type":29,"tag":901,"props":9349,"children":9350},{"style":5362},[9351],{"type":35,"value":9352},"sendOrderConfirmation",{"type":29,"tag":901,"props":9354,"children":9355},{"style":5185},[9356],{"type":35,"value":3080},{"type":29,"tag":901,"props":9358,"children":9359},{"style":923},[9360],{"type":35,"value":9324},{"type":29,"tag":901,"props":9362,"children":9363},{"style":5185},[9364],{"type":35,"value":342},{"type":29,"tag":901,"props":9366,"children":9367},{"style":5362},[9368],{"type":35,"value":9369},"getUserId",{"type":29,"tag":901,"props":9371,"children":9372},{"style":5185},[9373],{"type":35,"value":9374},"(),",{"type":29,"tag":901,"props":9376,"children":9377},{"style":923},[9378],{"type":35,"value":7927},{"type":29,"tag":901,"props":9380,"children":9381},{"style":5185},[9382],{"type":35,"value":8833},{"type":29,"tag":901,"props":9384,"children":9385},{"class":903,"line":6385},[9386],{"type":29,"tag":901,"props":9387,"children":9388},{"style":5185},[9389],{"type":35,"value":8093},{"type":29,"tag":901,"props":9391,"children":9392},{"class":903,"line":5085},[9393],{"type":29,"tag":901,"props":9394,"children":9395},{"style":5185},[9396],{"type":35,"value":7406},{"type":29,"tag":901,"props":9398,"children":9399},{"class":903,"line":4573},[9400],{"type":29,"tag":901,"props":9401,"children":9402},{"emptyLinePlaceholder":13},[9403],{"type":35,"value":974},{"type":29,"tag":901,"props":9405,"children":9406},{"class":903,"line":4109},[9407],{"type":29,"tag":901,"props":9408,"children":9409},{"style":908},[9410],{"type":35,"value":9411},"// Implémentation de test\n",{"type":29,"tag":901,"props":9413,"children":9414},{"class":903,"line":6579},[9415,9419],{"type":29,"tag":901,"props":9416,"children":9417},{"style":8914},[9418],{"type":35,"value":8917},{"type":29,"tag":901,"props":9420,"children":9421},{"style":8920},[9422],{"type":35,"value":8923},{"type":29,"tag":901,"props":9424,"children":9425},{"class":903,"line":1274},[9426,9430,9435,9439,9444],{"type":29,"tag":901,"props":9427,"children":9428},{"style":8914},[9429],{"type":35,"value":8917},{"type":29,"tag":901,"props":9431,"children":9432},{"style":8920},[9433],{"type":35,"value":9434},"Profile",{"type":29,"tag":901,"props":9436,"children":9437},{"style":5185},[9438],{"type":35,"value":3080},{"type":29,"tag":901,"props":9440,"children":9441},{"style":2236},[9442],{"type":35,"value":9443},"\"test\"",{"type":29,"tag":901,"props":9445,"children":9446},{"style":5185},[9447],{"type":35,"value":5437},{"type":29,"tag":901,"props":9449,"children":9450},{"class":903,"line":487},[9451,9455,9459,9464,9469,9473],{"type":29,"tag":901,"props":9452,"children":9453},{"style":917},[9454],{"type":35,"value":8773},{"type":29,"tag":901,"props":9456,"children":9457},{"style":917},[9458],{"type":35,"value":8935},{"type":29,"tag":901,"props":9460,"children":9461},{"style":5179},[9462],{"type":35,"value":9463}," MockNotificationService",{"type":29,"tag":901,"props":9465,"children":9466},{"style":917},[9467],{"type":35,"value":9468}," implements",{"type":29,"tag":901,"props":9470,"children":9471},{"style":5179},[9472],{"type":35,"value":8783},{"type":29,"tag":901,"props":9474,"children":9475},{"style":5185},[9476],{"type":35,"value":7272},{"type":29,"tag":901,"props":9478,"children":9479},{"class":903,"line":11},[9480],{"type":29,"tag":901,"props":9481,"children":9482},{"emptyLinePlaceholder":13},[9483],{"type":35,"value":974},{"type":29,"tag":901,"props":9485,"children":9486},{"class":903,"line":2121},[9487,9491,9495,9500,9504,9508,9512,9517,9521,9525,9530],{"type":29,"tag":901,"props":9488,"children":9489},{"style":917},[9490],{"type":35,"value":8959},{"type":29,"tag":901,"props":9492,"children":9493},{"style":917},[9494],{"type":35,"value":8964},{"type":29,"tag":901,"props":9496,"children":9497},{"style":8807},[9498],{"type":35,"value":9499}," List",{"type":29,"tag":901,"props":9501,"children":9502},{"style":5185},[9503],{"type":35,"value":7317},{"type":29,"tag":901,"props":9505,"children":9506},{"style":917},[9507],{"type":35,"value":8810},{"type":29,"tag":901,"props":9509,"children":9510},{"style":5185},[9511],{"type":35,"value":7327},{"type":29,"tag":901,"props":9513,"children":9514},{"style":923},[9515],{"type":35,"value":9516}," sentNotifications ",{"type":29,"tag":901,"props":9518,"children":9519},{"style":947},[9520],{"type":35,"value":2227},{"type":29,"tag":901,"props":9522,"children":9523},{"style":917},[9524],{"type":35,"value":7877},{"type":29,"tag":901,"props":9526,"children":9527},{"style":8807},[9528],{"type":35,"value":9529}," ArrayList",{"type":29,"tag":901,"props":9531,"children":9532},{"style":5185},[9533],{"type":35,"value":9534},"\u003C>();\n",{"type":29,"tag":901,"props":9536,"children":9537},{"class":903,"line":8103},[9538],{"type":29,"tag":901,"props":9539,"children":9540},{"emptyLinePlaceholder":13},[9541],{"type":35,"value":974},{"type":29,"tag":901,"props":9543,"children":9544},{"class":903,"line":8111},[9545,9550],{"type":29,"tag":901,"props":9546,"children":9547},{"style":8914},[9548],{"type":35,"value":9549},"    @",{"type":29,"tag":901,"props":9551,"children":9552},{"style":8920},[9553],{"type":35,"value":9554},"Override\n",{"type":29,"tag":901,"props":9556,"children":9557},{"class":903,"line":8120},[9558,9562,9566,9570,9574,9578,9582,9586,9590,9594,9598],{"type":29,"tag":901,"props":9559,"children":9560},{"style":917},[9561],{"type":35,"value":9016},{"type":29,"tag":901,"props":9563,"children":9564},{"style":917},[9565],{"type":35,"value":9143},{"type":29,"tag":901,"props":9567,"children":9568},{"style":5362},[9569],{"type":35,"value":8800},{"type":29,"tag":901,"props":9571,"children":9572},{"style":5185},[9573],{"type":35,"value":3080},{"type":29,"tag":901,"props":9575,"children":9576},{"style":8807},[9577],{"type":35,"value":8810},{"type":29,"tag":901,"props":9579,"children":9580},{"style":5252},[9581],{"type":35,"value":8815},{"type":29,"tag":901,"props":9583,"children":9584},{"style":5185},[9585],{"type":35,"value":3663},{"type":29,"tag":901,"props":9587,"children":9588},{"style":8807},[9589],{"type":35,"value":8824},{"type":29,"tag":901,"props":9591,"children":9592},{"style":5252},[9593],{"type":35,"value":7927},{"type":29,"tag":901,"props":9595,"children":9596},{"style":5185},[9597],{"type":35,"value":2881},{"type":29,"tag":901,"props":9599,"children":9600},{"style":5185},[9601],{"type":35,"value":7272},{"type":29,"tag":901,"props":9603,"children":9604},{"class":903,"line":8156},[9605,9610,9614,9619,9623,9628,9633,9638,9643,9648,9652,9656],{"type":29,"tag":901,"props":9606,"children":9607},{"style":923},[9608],{"type":35,"value":9609},"        sentNotifications",{"type":29,"tag":901,"props":9611,"children":9612},{"style":5185},[9613],{"type":35,"value":342},{"type":29,"tag":901,"props":9615,"children":9616},{"style":5362},[9617],{"type":35,"value":9618},"add",{"type":29,"tag":901,"props":9620,"children":9621},{"style":5185},[9622],{"type":35,"value":3080},{"type":29,"tag":901,"props":9624,"children":9625},{"style":2236},[9626],{"type":35,"value":9627},"\"confirmation:\"",{"type":29,"tag":901,"props":9629,"children":9630},{"style":947},[9631],{"type":35,"value":9632}," +",{"type":29,"tag":901,"props":9634,"children":9635},{"style":923},[9636],{"type":35,"value":9637}," userId ",{"type":29,"tag":901,"props":9639,"children":9640},{"style":947},[9641],{"type":35,"value":9642},"+",{"type":29,"tag":901,"props":9644,"children":9645},{"style":2236},[9646],{"type":35,"value":9647}," \":\"",{"type":29,"tag":901,"props":9649,"children":9650},{"style":947},[9651],{"type":35,"value":9632},{"type":29,"tag":901,"props":9653,"children":9654},{"style":923},[9655],{"type":35,"value":7927},{"type":29,"tag":901,"props":9657,"children":9658},{"style":5185},[9659],{"type":35,"value":8833},{"type":29,"tag":901,"props":9661,"children":9662},{"class":903,"line":8195},[9663],{"type":29,"tag":901,"props":9664,"children":9665},{"style":5185},[9666],{"type":35,"value":8093},{"type":29,"tag":901,"props":9668,"children":9669},{"class":903,"line":8224},[9670],{"type":29,"tag":901,"props":9671,"children":9672},{"style":5185},[9673],{"type":35,"value":7406},{"type":29,"tag":37,"props":9675,"children":9676},{},[9677,9682,9684,9690],{"type":29,"tag":65,"props":9678,"children":9679},{},[9680],{"type":35,"value":9681},"L'avantage Spring :",{"type":35,"value":9683}," ",{"type":29,"tag":565,"props":9685,"children":9687},{"className":9686},[],[9688],{"type":35,"value":9689},"@Profile(\"test\")",{"type":35,"value":9691}," permet d'utiliser automatiquement le mock en environnement de test sans modifier le code métier. Le framework gère le wiring, le code métier reste pur.",{"type":29,"tag":76,"props":9693,"children":9694},{},[],{"type":29,"tag":80,"props":9696,"children":9698},{"id":9697},"quand-appliquer-le-dip-et-quand-ne-pas-le-faire",[9699],{"type":35,"value":9700},"Quand appliquer le DIP, et quand ne pas le faire",{"type":29,"tag":37,"props":9702,"children":9703},{},[9704],{"type":29,"tag":65,"props":9705,"children":9706},{},[9707],{"type":35,"value":9708},"Appliquer le DIP :",{"type":29,"tag":1080,"props":9710,"children":9711},{},[9712,9717,9722],{"type":29,"tag":1084,"props":9713,"children":9714},{},[9715],{"type":35,"value":9716},"Toute dépendance vers un système externe (base de données, API tierce, service d'email, service de paiement, file de message)",{"type":29,"tag":1084,"props":9718,"children":9719},{},[9720],{"type":35,"value":9721},"Toute dépendance vers une infrastructure susceptible de changer",{"type":29,"tag":1084,"props":9723,"children":9724},{},[9725],{"type":35,"value":9726},"Tout code que vous voulez unit-tester sans infrastructure",{"type":29,"tag":37,"props":9728,"children":9729},{},[9730],{"type":29,"tag":65,"props":9731,"children":9732},{},[9733],{"type":35,"value":9734},"Ne pas appliquer le DIP mécaniquement :",{"type":29,"tag":1080,"props":9736,"children":9737},{},[9738,9743,9748],{"type":29,"tag":1084,"props":9739,"children":9740},{},[9741],{"type":35,"value":9742},"Les entités et value objects du domaine (Order, User, Money) : pas de logique d'infrastructure",{"type":29,"tag":1084,"props":9744,"children":9745},{},[9746],{"type":35,"value":9747},"Les utilitaires purs (calculs mathématiques, formatage de dates) : pas d'effet de bord",{"type":29,"tag":1084,"props":9749,"children":9750},{},[9751],{"type":35,"value":9752},"Les dépendances stables et peu susceptibles de changer dans des petits projets",{"type":29,"tag":37,"props":9754,"children":9755},{},[9756,9761,9763,9769],{"type":29,"tag":65,"props":9757,"children":9758},{},[9759],{"type":35,"value":9760},"Le signal",{"type":35,"value":9762}," : si écrire un test unitaire pour votre classe nécessite de démarrer une base de données, une queue de messages, ou de configurer un service externe, appliquez le DIP. Cette question est aussi centrale dans les ",{"type":29,"tag":48,"props":9764,"children":9766},{"href":9765},"/fr/dette-technique/tests-integration-legacy-pieges",[9767],{"type":35,"value":9768},"tests d'intégration sur du code legacy",{"type":35,"value":9770}," : l'absence de DIP est souvent ce qui rend ces tests si difficiles et si fragiles à mettre en place.",{"type":29,"tag":76,"props":9772,"children":9773},{},[],{"type":29,"tag":80,"props":9775,"children":9777},{"id":9776},"faq-sur-le-dependency-inversion-principle",[9778],{"type":35,"value":9779},"FAQ sur le Dependency Inversion Principle",{"type":29,"tag":381,"props":9781,"children":9782},{},[9783,9788],{"type":29,"tag":385,"props":9784,"children":9785},{},[9786],{"type":35,"value":9787},"1. Quelle est la différence entre DIP et Dependency Injection ?",{"type":29,"tag":37,"props":9789,"children":9790},{},[9791],{"type":35,"value":9792},"Le DIP est un principe architectural : les modules doivent dépendre d'abstractions. La Dependency Injection (DI) est une technique d'implémentation du DIP : les dépendances sont fournies de l'extérieur plutôt que créées à l'intérieur. On peut respecter le DIP sans DI (ex : factory pattern). On peut utiliser la DI sans respecter le DIP (ex : injecter une classe concrète sans interface). En pratique, les deux vont généralement ensemble.",{"type":29,"tag":381,"props":9794,"children":9795},{},[9796,9801],{"type":29,"tag":385,"props":9797,"children":9798},{},[9799],{"type":35,"value":9800},"2. Les containers DI (Spring, .NET DI, Angular) font-ils le travail à notre place ?",{"type":29,"tag":37,"props":9802,"children":9803},{},[9804],{"type":35,"value":9805},"Ils automatisent le wiring (qui injecte quoi), mais ne créent pas les abstractions à notre place. Spring injecte les classes concrètes si vous ne créez pas d'interfaces. La discipline architecturale de créer des interfaces pour les dépendances d'infrastructure reste une décision de l'équipe. Le framework ne peut pas la prendre à votre place.",{"type":29,"tag":381,"props":9807,"children":9808},{},[9809,9814],{"type":29,"tag":385,"props":9810,"children":9811},{},[9812],{"type":35,"value":9813},"3. Le DIP ne crée-t-il pas trop d'abstractions ?",{"type":29,"tag":37,"props":9815,"children":9816},{},[9817],{"type":35,"value":9818},"Oui, si mal appliqué. Créer une interface pour chaque classe, même les plus stables, est du sur-engineering. La règle que Martin Fowler formule clairement : créer une abstraction quand il y a au moins 2 implémentations possibles (production + test, provider A + provider B) ou quand la dépendance est vers un système externe. \"Pas d'abstraction prématurée\" s'applique au DIP comme à tout principe.",{"type":29,"tag":381,"props":9820,"children":9821},{},[9822,9827],{"type":29,"tag":385,"props":9823,"children":9824},{},[9825],{"type":35,"value":9826},"4. Comment introduire le DIP progressivement dans un codebase existant ?",{"type":29,"tag":37,"props":9828,"children":9829},{},[9830,9832,9838],{"type":35,"value":9831},"Le strangler fig pattern appliqué au DIP : ne pas refactorer tout le code existant d'un coup. À chaque nouvelle fonctionnalité ou bug fix qui touche une classe avec dépendances directes, extraire l'interface et introduire l'injection. Après 6 mois de cette discipline, les zones les plus actives du codebase respectent le DIP. Les zones stables peuvent rester dans l'état existant si elles ne causent pas de problèmes. Dans un contexte de ",{"type":29,"tag":48,"props":9833,"children":9835},{"href":9834},"/fr/dette-technique/legacy-code-evaluer-risque",[9836],{"type":35,"value":9837},"code legacy fortement couplé",{"type":35,"value":9839},", cette approche progressive est souvent la seule viable sans bloquer les livraisons.",{"type":29,"tag":381,"props":9841,"children":9842},{},[9843,9848],{"type":29,"tag":385,"props":9844,"children":9845},{},[9846],{"type":35,"value":9847},"5. Le DIP s'applique-t-il aux frontends (React, Vue) ?",{"type":29,"tag":37,"props":9849,"children":9850},{},[9851,9853,9859,9861,9867,9869,9875],{"type":35,"value":9852},"Oui. En React : les composants ne doivent pas appeler directement ",{"type":29,"tag":565,"props":9854,"children":9856},{"className":9855},[],[9857],{"type":35,"value":9858},"fetch()",{"type":35,"value":9860}," ou ",{"type":29,"tag":565,"props":9862,"children":9864},{"className":9863},[],[9865],{"type":35,"value":9866},"axios",{"type":35,"value":9868}," : ils doivent dépendre d'une abstraction (un service, un hook custom, un context) qui peut être mockée dans les tests. ",{"type":29,"tag":565,"props":9870,"children":9872},{"className":9871},[],[9873],{"type":35,"value":9874},"useOrderService()",{"type":35,"value":9876}," hook qui cache l'implémentation HTTP, facilement mockable dans les tests. Le DIP s'applique partout où il y a des effets de bord, frontend inclus.",{"type":29,"tag":76,"props":9878,"children":9879},{},[],{"type":29,"tag":176,"props":9881,"children":9882},{"cta":1243,"href":1244,"title":454,"type":455},[9883],{"type":29,"tag":37,"props":9884,"children":9885},{},[9886],{"type":35,"value":9887},"L'Engineering Maturity Self-Assessment couvre le domaine Craft & Conception : évaluez votre niveau sur les principes SOLID, le couplage, et la testabilité. Obtenez un score de maturité et des recommandations concrètes en 10 minutes.",{"type":29,"tag":1252,"props":9889,"children":9890},{},[9891],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":9893},[9894,9895,9896,9897,9898,9899,9900],{"id":5125,"depth":463,"text":5128},{"id":5577,"depth":463,"text":5580},{"id":5643,"depth":463,"text":5646},{"id":7235,"depth":463,"text":7238},{"id":8745,"depth":463,"text":8748},{"id":9697,"depth":463,"text":9700},{"id":9776,"depth":463,"text":9779},"content:fr:architecture-craft:dependency-inversion-pratique.md","fr/architecture-craft/dependency-inversion-pratique.md","fr/architecture-craft/dependency-inversion-pratique",{"_path":4968,"_dir":1271,"_draft":7,"_partial":7,"_locale":8,"title":9905,"description":9906,"id":6385,"date":9907,"listed":13,"nocomments":7,"hidden":7,"categories":9908,"tags":9909,"--cover":9913,"readingTime":9914,"body":9919,"_type":476,"_id":10568,"_source":478,"_file":10569,"_stem":10570,"_extension":481},"Engineering culture : les 6 rituels qui font la différence","La culture ne se proclame pas, elle se construit par des rituels répétés. Les 6 pratiques concrètes qui construisent une culture d'excellence technique sur 12 mois.","2026-03-11",[1271],[9910,9911,18,9912],"Engineering Culture","Rituels","Excellence Technique","covers/articles/engineering-culture-rituels.jpg",{"text":9915,"minutes":9916,"time":9917,"words":9918},"10 min read",9.295,557700,1859,{"type":26,"children":9920,"toc":10558},[9921,9926,9931,9936,9956,9961,9964,9970,9980,9985,9993,10021,10031,10034,10040,10049,10054,10062,10085,10095,10105,10114,10117,10123,10132,10137,10145,10168,10176,10199,10209,10212,10218,10227,10232,10240,10263,10273,10283,10286,10292,10301,10313,10323,10333,10343,10346,10352,10361,10366,10376,10400,10403,10409,10419,10427,10450,10460,10465,10468,10474,10495,10508,10521,10534,10547,10550],{"type":29,"tag":30,"props":9922,"children":9924},{"id":9923},"engineering-culture-les-6-rituels-qui-font-la-différence",[9925],{"type":35,"value":9905},{"type":29,"tag":37,"props":9927,"children":9928},{},[9929],{"type":35,"value":9930},"Dans un client dans le secteur financier où j'accompagnais l'équipe engineering, les valeurs d'entreprise affichaient \"excellence technique\" et \"partage de connaissance\" sur tous les murs. La réalité : chaque développeur gardait sa connaissance pour lui comme un avantage concurrentiel interne, les post-mortems cherchaient des coupables, et personne ne proposait de sujets pour les tech talks parce que personne n'avait jamais vu de tech talk se tenir.",{"type":29,"tag":37,"props":9932,"children":9933},{},[9934],{"type":35,"value":9935},"La culture n'était pas mauvaise parce que les valeurs étaient mauvaises. La culture était mauvaise parce qu'il n'y avait aucun rituel pour les incarner.",{"type":29,"tag":37,"props":9937,"children":9938},{},[9939,9941,9947,9949,9954],{"type":35,"value":9940},"Patrick Lencioni dans ",{"type":29,"tag":9942,"props":9943,"children":9944},"em",{},[9945],{"type":35,"value":9946},"The Five Dysfunctions of a Team",{"type":35,"value":9948}," et les recherches DORA sur l'état du DevOps convergent vers la même conclusion : ",{"type":29,"tag":65,"props":9950,"children":9951},{},[9952],{"type":35,"value":9953},"la performance d'une équipe engineering est davantage fonction de sa culture que de ses outils ou de ses processus",{"type":35,"value":9955},". Dans les 100 000 réponses analysées par le programme DORA chaque année, les équipes elite performers ont toutes en commun des pratiques culturelles spécifiques, pas des valeurs affichées. Des actes répétés.",{"type":29,"tag":37,"props":9957,"children":9958},{},[9959],{"type":35,"value":9960},"Voici les 6 rituels que j'ai implémentés et observés changer des équipes.",{"type":29,"tag":76,"props":9962,"children":9963},{},[],{"type":29,"tag":80,"props":9965,"children":9967},{"id":9966},"rituel-1-le-post-mortem-blameless",[9968],{"type":35,"value":9969},"Rituel 1 : Le post-mortem blameless",{"type":29,"tag":37,"props":9971,"children":9972},{},[9973,9978],{"type":29,"tag":65,"props":9974,"children":9975},{},[9976],{"type":35,"value":9977},"Ce qu'il construit :",{"type":35,"value":9979}," une culture de l'apprentissage collectif et de la sécurité psychologique.",{"type":29,"tag":37,"props":9981,"children":9982},{},[9983],{"type":35,"value":9984},"Après chaque incident en production significatif, l'équipe se réunit dans les 48 heures pour une analyse structurée. L'objectif n'est pas de trouver un coupable : c'est de comprendre le système qui a rendu l'incident possible.",{"type":29,"tag":37,"props":9986,"children":9987},{},[9988],{"type":29,"tag":65,"props":9989,"children":9990},{},[9991],{"type":35,"value":9992},"Format que j'utilise :",{"type":29,"tag":1080,"props":9994,"children":9995},{},[9996,10001,10006,10011,10016],{"type":29,"tag":1084,"props":9997,"children":9998},{},[9999],{"type":35,"value":10000},"45 à 60 minutes maximum",{"type":29,"tag":1084,"props":10002,"children":10003},{},[10004],{"type":35,"value":10005},"Chronologie des événements (pas des personnes)",{"type":29,"tag":1084,"props":10007,"children":10008},{},[10009],{"type":35,"value":10010},"5 Pourquoi pour remonter à la cause racine",{"type":29,"tag":1084,"props":10012,"children":10013},{},[10014],{"type":35,"value":10015},"Actions correctives sur le système (process, monitoring, test), jamais \"être plus vigilant\"",{"type":29,"tag":1084,"props":10017,"children":10018},{},[10019],{"type":35,"value":10020},"Document partagé avec toute l'équipe",{"type":29,"tag":37,"props":10022,"children":10023},{},[10024,10029],{"type":29,"tag":65,"props":10025,"children":10026},{},[10027],{"type":35,"value":10028},"Ce que le \"blameless\" change concrètement :",{"type":35,"value":10030}," quand les incidents sont des opportunités d'apprentissage sans conséquence sur la carrière des personnes, les développeurs signalent les incidents plus tôt, cherchent plus profondément les causes racines, et implémentent des corrections systémiques. La règle absolue : pas de \"c'est la faute de X\". Si quelqu'un a fait une erreur, la question est \"pourquoi le système a-t-il rendu cette erreur possible ?\"",{"type":29,"tag":76,"props":10032,"children":10033},{},[],{"type":29,"tag":80,"props":10035,"children":10037},{"id":10036},"rituel-2-la-tech-talk-mensuelle",[10038],{"type":35,"value":10039},"Rituel 2 : La Tech Talk mensuelle",{"type":29,"tag":37,"props":10041,"children":10042},{},[10043,10047],{"type":29,"tag":65,"props":10044,"children":10045},{},[10046],{"type":35,"value":9977},{"type":35,"value":10048}," une culture du partage de connaissance et de la curiosité intellectuelle.",{"type":29,"tag":37,"props":10050,"children":10051},{},[10052],{"type":35,"value":10053},"Une fois par mois, un membre de l'équipe présente pendant 30 minutes un sujet technique, pas nécessairement lié au projet en cours. Une technologie qu'il explore, un problème qu'il a résolu, un livre qu'il a lu, une conférence qu'il a regardée.",{"type":29,"tag":37,"props":10055,"children":10056},{},[10057],{"type":29,"tag":65,"props":10058,"children":10059},{},[10060],{"type":35,"value":10061},"Pourquoi ce rituel fonctionne :",{"type":29,"tag":1080,"props":10063,"children":10064},{},[10065,10070,10075,10080],{"type":29,"tag":1084,"props":10066,"children":10067},{},[10068],{"type":35,"value":10069},"Il valorise l'apprentissage continu comme norme culturelle, pas comme hobby personnel",{"type":29,"tag":1084,"props":10071,"children":10072},{},[10073],{"type":35,"value":10074},"Il expose l'équipe à des perspectives qu'elle n'aurait pas explorées",{"type":29,"tag":1084,"props":10076,"children":10077},{},[10078],{"type":35,"value":10079},"Il développe les compétences de communication technique des présentateurs",{"type":29,"tag":1084,"props":10081,"children":10082},{},[10083],{"type":35,"value":10084},"Il crée des conversations qui durent au-delà de la session",{"type":29,"tag":37,"props":10086,"children":10087},{},[10088,10093],{"type":29,"tag":65,"props":10089,"children":10090},{},[10091],{"type":35,"value":10092},"Comment je l'instaure :",{"type":35,"value":10094}," je présente en premier. Cela enlève la pression du \"qui va se lancer\" et montre que c'est un espace sans jugement. Après 2 à 3 sessions, une rotation naturelle s'installe. Je ne force jamais : le volontariat maintient la qualité.",{"type":29,"tag":37,"props":10096,"children":10097},{},[10098,10103],{"type":29,"tag":65,"props":10099,"children":10100},{},[10101],{"type":35,"value":10102},"Le seuil de qualité que j'impose :",{"type":35,"value":10104}," pas besoin d'être expert pour présenter. \"J'ai exploré X cette semaine, voici ce que j'ai trouvé intéressant, voici les questions que je n'ai pas encore résolues\" est une Tech Talk de qualité. Parfois meilleure que la présentation d'un expert, parce qu'elle montre le processus d'apprentissage.",{"type":29,"tag":176,"props":10106,"children":10108},{"cta":178,"href":179,"title":10107,"type":181},"Vous voulez construire une culture d'excellence technique mais ne savez pas par quels rituels commencer ?",[10109],{"type":29,"tag":37,"props":10110,"children":10111},{},[10112],{"type":35,"value":10113},"Les rituels qui fonctionnent dépendent de la culture actuelle de l'équipe, de sa taille, et de son contexte. Implanter tous les rituels d'un coup crée de la surcharge et génère du rejet. En 30 minutes, je peux identifier les 2 à 3 rituels les plus impactants pour votre situation et définir un plan d'implémentation réaliste.",{"type":29,"tag":76,"props":10115,"children":10116},{},[],{"type":29,"tag":80,"props":10118,"children":10120},{"id":10119},"rituel-3-la-session-de-code-review-collective",[10121],{"type":35,"value":10122},"Rituel 3 : La session de code review collective",{"type":29,"tag":37,"props":10124,"children":10125},{},[10126,10130],{"type":29,"tag":65,"props":10127,"children":10128},{},[10129],{"type":35,"value":9977},{"type":35,"value":10131}," des standards techniques partagés et une culture de feedback constructif.",{"type":29,"tag":37,"props":10133,"children":10134},{},[10135],{"type":35,"value":10136},"Toutes les 2 semaines, l'équipe passe 45 minutes à reviewer ensemble une PR récente, soit un changement intéressant sur le plan technique, soit une PR qui a suscité des discussions en review asynchrone.",{"type":29,"tag":37,"props":10138,"children":10139},{},[10140],{"type":29,"tag":65,"props":10141,"children":10142},{},[10143],{"type":35,"value":10144},"Ce que ce rituel apprend concrètement :",{"type":29,"tag":1080,"props":10146,"children":10147},{},[10148,10153,10158,10163],{"type":29,"tag":1084,"props":10149,"children":10150},{},[10151],{"type":35,"value":10152},"Comment les seniors pensent quand ils reviewent du code",{"type":29,"tag":1084,"props":10154,"children":10155},{},[10156],{"type":35,"value":10157},"Les standards non écrits que les seniors appliquent intuitivement",{"type":29,"tag":1084,"props":10159,"children":10160},{},[10161],{"type":35,"value":10162},"Comment donner du feedback constructif (en observant les seniors le faire)",{"type":29,"tag":1084,"props":10164,"children":10165},{},[10166],{"type":35,"value":10167},"Les patterns à éviter dans cette base de code spécifique",{"type":29,"tag":37,"props":10169,"children":10170},{},[10171],{"type":29,"tag":65,"props":10172,"children":10173},{},[10174],{"type":35,"value":10175},"Format :",{"type":29,"tag":1080,"props":10177,"children":10178},{},[10179,10184,10189,10194],{"type":29,"tag":1084,"props":10180,"children":10181},{},[10182],{"type":35,"value":10183},"L'auteur présente le contexte (2 min)",{"type":29,"tag":1084,"props":10185,"children":10186},{},[10187],{"type":35,"value":10188},"Review collective en temps réel sur un écran partagé (30 min)",{"type":29,"tag":1084,"props":10190,"children":10191},{},[10192],{"type":35,"value":10193},"Discussion des trade-offs et décisions (10 min)",{"type":29,"tag":1084,"props":10195,"children":10196},{},[10197],{"type":35,"value":10198},"Synthèse des enseignements (5 min)",{"type":29,"tag":37,"props":10200,"children":10201},{},[10202,10207],{"type":29,"tag":65,"props":10203,"children":10204},{},[10205],{"type":35,"value":10206},"Ce que j'observe systématiquement :",{"type":35,"value":10208}," les développeurs juniors exposés à des sessions de review collective progressent significativement plus vite sur la qualité du code que ceux qui reçoivent uniquement des reviews asynchrones. La différence n'est pas dans le contenu du feedback : c'est dans la visibilité du raisonnement du reviewer.",{"type":29,"tag":76,"props":10210,"children":10211},{},[],{"type":29,"tag":80,"props":10213,"children":10215},{"id":10214},"rituel-4-lengineering-retrospective-trimestrielle",[10216],{"type":35,"value":10217},"Rituel 4 : L'Engineering Retrospective trimestrielle",{"type":29,"tag":37,"props":10219,"children":10220},{},[10221,10225],{"type":29,"tag":65,"props":10222,"children":10223},{},[10224],{"type":35,"value":9977},{"type":35,"value":10226}," une culture d'amélioration continue de l'engineering lui-même, séparée de la rétrospective produit.",{"type":29,"tag":37,"props":10228,"children":10229},{},[10230],{"type":35,"value":10231},"Une fois par trimestre, l'équipe consacre 2 heures à évaluer l'état de l'engineering, pas la delivery produit (c'est la rétro Scrum), mais les pratiques techniques elles-mêmes.",{"type":29,"tag":37,"props":10233,"children":10234},{},[10235],{"type":29,"tag":65,"props":10236,"children":10237},{},[10238],{"type":35,"value":10239},"Questions que j'utilise :",{"type":29,"tag":1080,"props":10241,"children":10242},{},[10243,10248,10253,10258],{"type":29,"tag":1084,"props":10244,"children":10245},{},[10246],{"type":35,"value":10247},"Quelles pratiques techniques avons-nous améliorées ce trimestre ?",{"type":29,"tag":1084,"props":10249,"children":10250},{},[10251],{"type":35,"value":10252},"Quelle partie de notre codebase nous ralentit le plus ?",{"type":29,"tag":1084,"props":10254,"children":10255},{},[10256],{"type":35,"value":10257},"Quelle compétence technique manque à l'équipe ?",{"type":29,"tag":1084,"props":10259,"children":10260},{},[10261],{"type":35,"value":10262},"Si on refaisait l'architecture de X aujourd'hui, on ferait quoi différemment ?",{"type":29,"tag":37,"props":10264,"children":10265},{},[10266,10271],{"type":29,"tag":65,"props":10267,"children":10268},{},[10269],{"type":35,"value":10270},"Pourquoi la séparation de la rétro produit est essentielle :",{"type":35,"value":10272}," dans une rétro Scrum classique, les préoccupations produit dominent (fonctionnalités en retard, bugs business, pression du sprint). Les sujets techniques sont traités superficiellement ou pas du tout. La rétro engineering dédiée crée l'espace pour des discussions profondes sur la dette technique, les pratiques, et les compétences.",{"type":29,"tag":37,"props":10274,"children":10275},{},[10276,10281],{"type":29,"tag":65,"props":10277,"children":10278},{},[10279],{"type":35,"value":10280},"Livrable :",{"type":35,"value":10282}," 3 actions d'amélioration technique priorisées pour le prochain trimestre. Trackées comme des stories dans le backlog, pas des intentions qui disparaissent dans un document Wiki.",{"type":29,"tag":76,"props":10284,"children":10285},{},[],{"type":29,"tag":80,"props":10287,"children":10289},{"id":10288},"rituel-5-le-pair-programming-de-découverte",[10290],{"type":35,"value":10291},"Rituel 5 : Le Pair Programming de découverte",{"type":29,"tag":37,"props":10293,"children":10294},{},[10295,10299],{"type":29,"tag":65,"props":10296,"children":10297},{},[10298],{"type":35,"value":9977},{"type":35,"value":10300}," une culture de collaboration et de transfert de connaissance horizontal.",{"type":29,"tag":37,"props":10302,"children":10303},{},[10304,10306,10311],{"type":35,"value":10305},"2 heures par semaine, 2 développeurs travaillent ensemble sur un problème, pas nécessairement pour aller plus vite, mais pour apprendre l'un de l'autre. Le ",{"type":29,"tag":48,"props":10307,"children":10308},{"href":355},[10309],{"type":35,"value":10310},"ROI du pair programming",{"type":35,"value":10312}," est documenté : 15% de défauts en moins sur les tâches complexes.",{"type":29,"tag":37,"props":10314,"children":10315},{},[10316,10321],{"type":29,"tag":65,"props":10317,"children":10318},{},[10319],{"type":35,"value":10320},"La différence avec le pair programming utilitaire :",{"type":35,"value":10322}," ce pair programming est intentionnellement hétérogène (junior + senior, frontend + backend, nouveau + vieux dans l'équipe) et vise le transfert de connaissance autant que le code produit.",{"type":29,"tag":37,"props":10324,"children":10325},{},[10326,10331],{"type":29,"tag":65,"props":10327,"children":10328},{},[10329],{"type":35,"value":10330},"Rotation :",{"type":35,"value":10332}," une nouvelle paire chaque semaine. Sur une équipe de 8, chaque développeur travaille avec un collègue différent toutes les 4 semaines. En 6 mois, chaque développeur a travaillé avec chaque autre membre de l'équipe au moins une fois.",{"type":29,"tag":37,"props":10334,"children":10335},{},[10336,10341],{"type":29,"tag":65,"props":10337,"children":10338},{},[10339],{"type":35,"value":10340},"Ce que ce rituel prévient :",{"type":35,"value":10342}," le knowledge siloing (seul X connaît ce service), l'isolement des développeurs juniors, et les tensions entre les sous-groupes de l'équipe. Dans cette organisation, ce rituel seul a réduit le bus factor sur les services critiques de 1 à 3 en moins de 6 mois.",{"type":29,"tag":76,"props":10344,"children":10345},{},[],{"type":29,"tag":80,"props":10347,"children":10349},{"id":10348},"rituel-6-le-craft-backlog-visible",[10350],{"type":35,"value":10351},"Rituel 6 : Le Craft Backlog visible",{"type":29,"tag":37,"props":10353,"children":10354},{},[10355,10359],{"type":29,"tag":65,"props":10356,"children":10357},{},[10358],{"type":35,"value":9977},{"type":35,"value":10360}," une culture de la qualité et de la viabilité à long terme du code.",{"type":29,"tag":37,"props":10362,"children":10363},{},[10364],{"type":35,"value":10365},"Un backlog visible dédié aux améliorations techniques : remboursement de dette technique, refactoring, mise à jour des dépendances, amélioration de la couverture de tests. Pas dans le backlog produit. Dans un backlog séparé, visible de tout le monde y compris du management.",{"type":29,"tag":37,"props":10367,"children":10368},{},[10369,10374],{"type":29,"tag":65,"props":10370,"children":10371},{},[10372],{"type":35,"value":10373},"Pourquoi la visibilité est clé :",{"type":35,"value":10375}," la dette technique invisible n'est pas prioritarisée. La dette technique visible avec un impact estimé (en temps de développement supplémentaire et en risque business) peut être défendue auprès du leadership.",{"type":29,"tag":37,"props":10377,"children":10378},{},[10379,10384,10386,10391,10393,10398],{"type":29,"tag":65,"props":10380,"children":10381},{},[10382],{"type":35,"value":10383},"La règle du 20% :",{"type":35,"value":10385}," 20% de la capacité de chaque sprint est allouée au craft backlog. Pour obtenir ce budget, consultez le guide pour ",{"type":29,"tag":48,"props":10387,"children":10388},{"href":2071},[10389],{"type":35,"value":10390},"faire approuver un programme de refactoring par le business",{"type":35,"value":10392},". Non-négociable, comme l'investissement dans la sécurité ou les tests. Cette règle doit être défendue par le manager et le CTO auprès du business. Will Larson décrit ce principe dans ",{"type":29,"tag":9942,"props":10394,"children":10395},{},[10396],{"type":35,"value":10397},"An Elegant Puzzle",{"type":35,"value":10399}," : le travail de maintenance du système n'est pas un coût, c'est la condition de la vélocité future.",{"type":29,"tag":76,"props":10401,"children":10402},{},[],{"type":29,"tag":80,"props":10404,"children":10406},{"id":10405},"comment-implémenter-les-6-rituels-sans-créer-de-surcharge",[10407],{"type":35,"value":10408},"Comment implémenter les 6 rituels sans créer de surcharge",{"type":29,"tag":37,"props":10410,"children":10411},{},[10412,10417],{"type":29,"tag":65,"props":10413,"children":10414},{},[10415],{"type":35,"value":10416},"Démarrer par 2, pas 6.",{"type":35,"value":10418}," Implémenter tous les rituels simultanément crée une charge d'organisation excessive et dilue l'attention. Je commence par les 2 rituels les plus adaptés à la situation actuelle de l'équipe.",{"type":29,"tag":37,"props":10420,"children":10421},{},[10422],{"type":29,"tag":65,"props":10423,"children":10424},{},[10425],{"type":35,"value":10426},"Mes recommandations par situation :",{"type":29,"tag":1080,"props":10428,"children":10429},{},[10430,10435,10440,10445],{"type":29,"tag":1084,"props":10431,"children":10432},{},[10433],{"type":35,"value":10434},"Équipe avec peu de sécurité psychologique → Post-mortem blameless + Pair programming de découverte",{"type":29,"tag":1084,"props":10436,"children":10437},{},[10438],{"type":35,"value":10439},"Équipe avec fort knowledge siloing → Pair programming de découverte + Tech Talk mensuelle",{"type":29,"tag":1084,"props":10441,"children":10442},{},[10443],{"type":35,"value":10444},"Équipe avec culture de qualité faible → Code review collective + Craft Backlog visible",{"type":29,"tag":1084,"props":10446,"children":10447},{},[10448],{"type":35,"value":10449},"Équipe en forte croissance → Tech Talk mensuelle + Pair programming de découverte",{"type":29,"tag":37,"props":10451,"children":10452},{},[10453,10458],{"type":29,"tag":65,"props":10454,"children":10455},{},[10456],{"type":35,"value":10457},"Le timing réaliste :",{"type":35,"value":10459}," les rituels prennent 3 à 6 mois pour s'ancrer dans la culture. La première session est souvent maladroite. La cinquième est naturelle. La vingtième fait partie de l'identité de l'équipe.",{"type":29,"tag":37,"props":10461,"children":10462},{},[10463],{"type":35,"value":10464},"Dans ce client, après 12 mois d'implémentation progressive des 6 rituels, les signaux culturels avaient radicalement changé : les incidents étaient signalés plus tôt, la documentation avait augmenté spontanément, et 3 développeurs avaient présenté à des conférences externes, quelque chose qui n'était jamais arrivé avant. La culture ne s'était pas transformée parce qu'on avait changé les valeurs affichées. Elle s'était transformée parce qu'on avait changé les comportements répétés chaque semaine.",{"type":29,"tag":76,"props":10466,"children":10467},{},[],{"type":29,"tag":80,"props":10469,"children":10471},{"id":10470},"faq-sur-les-rituels-de-culture-engineering",[10472],{"type":35,"value":10473},"FAQ sur les rituels de culture engineering",{"type":29,"tag":381,"props":10475,"children":10476},{},[10477,10482],{"type":29,"tag":385,"props":10478,"children":10479},{},[10480],{"type":35,"value":10481},"Comment maintenir les rituels quand l'équipe est sous pression de delivery ?",{"type":29,"tag":37,"props":10483,"children":10484},{},[10485,10487,10493],{"type":35,"value":10486},"C'est précisément sous pression que les rituels sont le plus importants, et le plus menacés. Ma règle : certains rituels sont compressibles (la Tech Talk peut passer à 20 min), aucun n'est supprimable. Un post-mortem annulé envoie le message que l'apprentissage n'est pas prioritaire. La solution : prévoir des formats compressés pour les périodes de pression, pas des annulations. Consultez le ",{"type":29,"tag":48,"props":10488,"children":10490},{"href":10489},"/fr/pratiques-agiles/retrospective-agile-format-efficace",[10491],{"type":35,"value":10492},"format de rétrospective en 5 étapes",{"type":35,"value":10494}," qui génère vraiment du changement. L'habitude survit aux compressions. Elle ne survit pas aux suppressions répétées.",{"type":29,"tag":381,"props":10496,"children":10497},{},[10498,10503],{"type":29,"tag":385,"props":10499,"children":10500},{},[10501],{"type":35,"value":10502},"Ces rituels fonctionnent-ils en équipe distribuée ou full remote ?",{"type":29,"tag":37,"props":10504,"children":10505},{},[10506],{"type":35,"value":10507},"Oui, avec adaptation. Le post-mortem et la review collective fonctionnent en visioconférence. La Tech Talk est souvent plus accessible en remote (enregistrement possible). Le pair programming de découverte nécessite des outils adaptés (Live Share dans VSCode, Tuple). La rétro engineering se fait sur Miro ou Mural. Le craft backlog est naturellement digital. Le pair programming est le seul rituel qui perd en efficacité remote : compenser par des sessions plus courtes mais plus fréquentes.",{"type":29,"tag":381,"props":10509,"children":10510},{},[10511,10516],{"type":29,"tag":385,"props":10512,"children":10513},{},[10514],{"type":35,"value":10515},"Comment mesurer l'impact des rituels sur la culture ?",{"type":29,"tag":37,"props":10517,"children":10518},{},[10519],{"type":35,"value":10520},"Les métriques proxy que j'utilise : fréquence de signalement des incidents (hausse → meilleure sécurité psychologique), nombre de PR commentées par les juniors (hausse → moins de peur du feedback), rotation des knowledge owners sur le codebase (hausse → moins de siloing), nombre de sujets proposés pour les Tech Talks (hausse → curiosité intellectuelle). Ces proxy suffisent pour évaluer la direction.",{"type":29,"tag":381,"props":10522,"children":10523},{},[10524,10529],{"type":29,"tag":385,"props":10525,"children":10526},{},[10527],{"type":35,"value":10528},"Faut-il impliquer le management dans les rituels ?",{"type":29,"tag":37,"props":10530,"children":10531},{},[10532],{"type":35,"value":10533},"La présence du management aux post-mortems blameless est importante : elle signale que la direction soutient la culture d'apprentissage sans recherche de coupable. Pour les Tech Talks et les reviews collectives, la présence est optionnelle, mais l'intérêt démontré (regarder l'enregistrement, commenter) est un signal fort. Le management ne devrait jamais animer les rituels : c'est à l'équipe de se les approprier.",{"type":29,"tag":381,"props":10535,"children":10536},{},[10537,10542],{"type":29,"tag":385,"props":10538,"children":10539},{},[10540],{"type":35,"value":10541},"Que faire si les rituels ne \"prennent pas\" après 3 mois ?",{"type":29,"tag":37,"props":10543,"children":10544},{},[10545],{"type":35,"value":10546},"Trois diagnostics possibles. Le rituel n'adresse pas un problème réel de l'équipe : remplacer par un rituel plus adapté. La facilitation est insuffisante : investir dans la formation du facilitateur ou faire appel à un externe pour les premières sessions. Il y a un problème de sécurité psychologique plus profond (peur de s'exprimer, culture punitive) : les rituels ne peuvent pas fonctionner sans un niveau minimal de confiance. Résoudre d'abord le problème structurel.",{"type":29,"tag":76,"props":10548,"children":10549},{},[],{"type":29,"tag":176,"props":10551,"children":10552},{"cta":1243,"href":1244,"title":454,"type":455},[10553],{"type":29,"tag":37,"props":10554,"children":10555},{},[10556],{"type":35,"value":10557},"L'Engineering Maturity Self-Assessment couvre le domaine Culture Engineering : évaluez la maturité culturelle de votre équipe sur les rituels techniques, les pratiques de collaboration, et l'amélioration continue. Score et recommandations en 10 minutes.",{"title":8,"searchDepth":463,"depth":463,"links":10559},[10560,10561,10562,10563,10564,10565,10566,10567],{"id":9966,"depth":463,"text":9969},{"id":10036,"depth":463,"text":10039},{"id":10119,"depth":463,"text":10122},{"id":10214,"depth":463,"text":10217},{"id":10288,"depth":463,"text":10291},{"id":10348,"depth":463,"text":10351},{"id":10405,"depth":463,"text":10408},{"id":10470,"depth":463,"text":10473},"content:fr:management:engineering-culture-rituels.md","fr/management/engineering-culture-rituels.md","fr/management/engineering-culture-rituels",{"_path":10572,"_dir":2118,"_draft":7,"_partial":7,"_locale":8,"title":10573,"description":10574,"id":6377,"date":10575,"listed":13,"nocomments":7,"hidden":7,"categories":10576,"tags":10577,"--cover":10581,"readingTime":10582,"body":10586,"_type":476,"_id":11760,"_source":478,"_file":11761,"_stem":11762,"_extension":481},"/fr/intelligence-artificielle/ia-documentation-technique-cas-usage","IA et documentation technique : les cas d'usage qui marchent vraiment","L'IA peut automatiser 60% de la documentation technique — mais pas les 60% auxquels on pense en premier. Les cas d'usage validés et ceux à éviter.","2026-03-09",[2118],[10578,2126,10579,10580],"Documentation","Automatisation","Developer Experience","covers/articles/ia-documentation-technique.jpg",{"text":9915,"minutes":10583,"time":10584,"words":10585},9.03,541800,1806,{"type":26,"children":10587,"toc":11749},[10588,10593,10598,10603,10611,10614,10620,10625,10635,10645,10650,10653,10659,10669,10679,10740,10745,10753,10756,10762,10771,10780,11332,11344,11353,11356,11362,11371,11380,11385,11393,11403,11413,11416,11422,11431,11440,11445,11508,11520,11523,11529,11538,11547,11551,11559,11564,11567,11573,11588,11598,11608,11611,11617,11634,11644,11654,11659,11662,11668,11681,11694,11707,11720,11733,11736,11745],{"type":29,"tag":30,"props":10589,"children":10591},{"id":10590},"ia-et-documentation-technique-les-cas-dusage-qui-marchent-vraiment",[10592],{"type":35,"value":10573},{"type":29,"tag":37,"props":10594,"children":10595},{},[10596],{"type":35,"value":10597},"J'accompagnais une équipe de 12 développeurs chez un client dans l'édition logicielle. Leur base de code avait 23 services. Zéro documentation. Les nouvelles recrues passaient 3 semaines à poser des questions aux développeurs seniors, qui, eux, perdaient 30 à 45 minutes par jour à répondre. Un coût invisible mais massif, mesuré quand j'ai fait le calcul avec le CTO.",{"type":29,"tag":37,"props":10599,"children":10600},{},[10601],{"type":35,"value":10602},"Nous avons organisé un sprint de documentation de 2 jours avec assistance Claude. Résultat : 18 services avaient des READMEs et des docs d'API générés. Temps de révision humaine : 30 à 45 minutes par service. Le lead time d'onboarding est passé de 3 semaines à 10 jours. 18 services documentés en 2 jours, contre 18 semaines si fait manuellement.",{"type":29,"tag":37,"props":10604,"children":10605},{},[10606],{"type":29,"tag":65,"props":10607,"children":10608},{},[10609],{"type":35,"value":10610},"L'IA peut automatiser 60% de la documentation technique. Mais pas les 60% auxquels on pense en premier. Les équipes qui espèrent que l'IA va écrire leurs ADR et leur documentation d'architecture sont déçues. Celles qui l'utilisent pour les bons cas d'usage gagnent des heures par semaine.",{"type":29,"tag":76,"props":10612,"children":10613},{},[],{"type":29,"tag":80,"props":10615,"children":10617},{"id":10616},"ce-que-lia-documente-bien-et-ce-quelle-documente-mal",[10618],{"type":35,"value":10619},"Ce que l'IA documente bien, et ce qu'elle documente mal",{"type":29,"tag":37,"props":10621,"children":10622},{},[10623],{"type":35,"value":10624},"J'ai testé et observé suffisamment de déploiements pour établir une règle simple :",{"type":29,"tag":37,"props":10626,"children":10627},{},[10628,10633],{"type":29,"tag":65,"props":10629,"children":10630},{},[10631],{"type":35,"value":10632},"L'IA documente bien le \"quoi\" :",{"type":35,"value":10634}," ce que le code fait, comment appeler une API, quels paramètres une fonction accepte, quelle est la structure d'un objet. Ces informations sont dans le code, l'IA les extrait et les formate.",{"type":29,"tag":37,"props":10636,"children":10637},{},[10638,10643],{"type":29,"tag":65,"props":10639,"children":10640},{},[10641],{"type":35,"value":10642},"L'IA documente mal le \"pourquoi\" :",{"type":35,"value":10644}," pourquoi ce choix d'architecture, pourquoi cette contrainte de performance, pourquoi cette API a été dépréciée. Ces informations ne sont pas dans le code, elles sont dans les cerveaux des développeurs qui ont pris ces décisions.",{"type":29,"tag":37,"props":10646,"children":10647},{},[10648],{"type":35,"value":10649},"La règle d'usage : utilisez l'IA pour documenter le \"quoi\" ; investissez le temps humain sur le \"pourquoi\".",{"type":29,"tag":76,"props":10651,"children":10652},{},[],{"type":29,"tag":80,"props":10654,"children":10656},{"id":10655},"cas-dusage-1-génération-de-documentation-dapi-roi-élevé",[10657],{"type":35,"value":10658},"Cas d'usage 1 : Génération de documentation d'API (ROI élevé)",{"type":29,"tag":37,"props":10660,"children":10661},{},[10662,10667],{"type":29,"tag":65,"props":10663,"children":10664},{},[10665],{"type":35,"value":10666},"Le problème :",{"type":35,"value":10668}," les APIs internes ne sont souvent pas documentées. Chaque développeur qui intègre un nouveau service perd 2 à 4 heures à comprendre les endpoints, les paramètres, et les formats de réponse en lisant le code.",{"type":29,"tag":37,"props":10670,"children":10671},{},[10672,10677],{"type":29,"tag":65,"props":10673,"children":10674},{},[10675],{"type":35,"value":10676},"Ce que l'IA fait :",{"type":35,"value":10678}," à partir du code d'un controller, d'un router Express, ou d'un fichier de routes FastAPI, l'IA génère une documentation structurée (format OpenAPI/Swagger ou Markdown) avec les endpoints, les paramètres, les types, et des exemples.",{"type":29,"tag":651,"props":10680,"children":10682},{"code":10681,"language":2202,"meta":8,"className":2200,"style":8},"# Prompt pour Claude/GPT-4\n\"\"\"\nVoici le code d'un router FastAPI. Génère une documentation OpenAPI complète\navec description de chaque endpoint, paramètres, types, et exemples de requête/réponse.\n\n[coller le code du router]\n\"\"\"\n",[10683],{"type":29,"tag":565,"props":10684,"children":10685},{"__ignoreMap":8},[10686,10694,10702,10710,10718,10725,10733],{"type":29,"tag":901,"props":10687,"children":10688},{"class":903,"line":904},[10689],{"type":29,"tag":901,"props":10690,"children":10691},{"style":908},[10692],{"type":35,"value":10693},"# Prompt pour Claude/GPT-4\n",{"type":29,"tag":901,"props":10695,"children":10696},{"class":903,"line":463},[10697],{"type":29,"tag":901,"props":10698,"children":10699},{"style":2236},[10700],{"type":35,"value":10701},"\"\"\"\n",{"type":29,"tag":901,"props":10703,"children":10704},{"class":903,"line":469},[10705],{"type":29,"tag":901,"props":10706,"children":10707},{"style":2236},[10708],{"type":35,"value":10709},"Voici le code d'un router FastAPI. Génère une documentation OpenAPI complète\n",{"type":29,"tag":901,"props":10711,"children":10712},{"class":903,"line":968},[10713],{"type":29,"tag":901,"props":10714,"children":10715},{"style":2236},[10716],{"type":35,"value":10717},"avec description de chaque endpoint, paramètres, types, et exemples de requête/réponse.\n",{"type":29,"tag":901,"props":10719,"children":10720},{"class":903,"line":977},[10721],{"type":29,"tag":901,"props":10722,"children":10723},{"emptyLinePlaceholder":13},[10724],{"type":35,"value":974},{"type":29,"tag":901,"props":10726,"children":10727},{"class":903,"line":986},[10728],{"type":29,"tag":901,"props":10729,"children":10730},{"style":2236},[10731],{"type":35,"value":10732},"[coller le code du router]\n",{"type":29,"tag":901,"props":10734,"children":10735},{"class":903,"line":1007},[10736],{"type":29,"tag":901,"props":10737,"children":10738},{"style":2236},[10739],{"type":35,"value":10701},{"type":29,"tag":37,"props":10741,"children":10742},{},[10743],{"type":35,"value":10744},"Résultat typique : une documentation OpenAPI utilisable en 5 minutes de génération + 15 minutes de révision humaine pour vérifier l'exactitude et ajouter les informations contextuelles (qui appelle cette API, dans quel flux business, quelles sont les contraintes de rate limiting).",{"type":29,"tag":37,"props":10746,"children":10747},{},[10748],{"type":29,"tag":65,"props":10749,"children":10750},{},[10751],{"type":35,"value":10752},"Gain : 3 à 4 heures de documentation manuelle → 20 minutes.",{"type":29,"tag":76,"props":10754,"children":10755},{},[],{"type":29,"tag":80,"props":10757,"children":10759},{"id":10758},"cas-dusage-2-commentaires-et-docstrings-dans-le-code-roi-moyen",[10760],{"type":35,"value":10761},"Cas d'usage 2 : Commentaires et docstrings dans le code (ROI moyen)",{"type":29,"tag":37,"props":10763,"children":10764},{},[10765,10769],{"type":29,"tag":65,"props":10766,"children":10767},{},[10768],{"type":35,"value":10666},{"type":35,"value":10770}," le code existant n'a pas de commentaires. Les fonctions complexes sont difficiles à comprendre sans connaître le contexte de leur création.",{"type":29,"tag":37,"props":10772,"children":10773},{},[10774,10778],{"type":29,"tag":65,"props":10775,"children":10776},{},[10777],{"type":35,"value":10676},{"type":35,"value":10779}," elle génère des docstrings JSDoc, Python Docstrings, ou JavaDoc pour les fonctions et classes existantes.",{"type":29,"tag":651,"props":10781,"children":10785},{"code":10782,"language":10783,"meta":8,"className":10784,"style":8},"// Avant\nfunction calculateEligibility(user, subscription, promoCode) {\n    if (!user.verified) return { eligible: false, reason: 'NOT_VERIFIED' };\n    if (subscription.status !== 'active') return { eligible: false, reason: 'INACTIVE_SUB' };\n    if (promoCode && promoCode.usageCount >= promoCode.maxUsage) {\n        return { eligible: false, reason: 'PROMO_EXHAUSTED' };\n    }\n    return { eligible: true };\n}\n\n// Après génération IA\n/**\n * Détermine l'éligibilité d'un utilisateur à appliquer un code promo.\n *\n * @param {User} user - L'utilisateur demandant l'application du promo\n * @param {Subscription} subscription - L'abonnement actif de l'utilisateur\n * @param {PromoCode|null} promoCode - Le code promo à valider (peut être null)\n * @returns {{ eligible: boolean, reason?: string }} Résultat de l'éligibilité\n */\n","javascript","language-javascript shiki shiki-themes catppuccin-frappe github-dark",[10786],{"type":29,"tag":565,"props":10787,"children":10788},{"__ignoreMap":8},[10789,10797,10845,10921,10998,11050,11094,11101,11128,11135,11142,11150,11158,11166,11174,11216,11253,11290,11324],{"type":29,"tag":901,"props":10790,"children":10791},{"class":903,"line":904},[10792],{"type":29,"tag":901,"props":10793,"children":10794},{"style":908},[10795],{"type":35,"value":10796},"// Avant\n",{"type":29,"tag":901,"props":10798,"children":10799},{"class":903,"line":463},[10800,10805,10810,10814,10819,10823,10828,10832,10837,10841],{"type":29,"tag":901,"props":10801,"children":10802},{"style":917},[10803],{"type":35,"value":10804},"function",{"type":29,"tag":901,"props":10806,"children":10807},{"style":5362},[10808],{"type":35,"value":10809}," calculateEligibility",{"type":29,"tag":901,"props":10811,"children":10812},{"style":5185},[10813],{"type":35,"value":3080},{"type":29,"tag":901,"props":10815,"children":10816},{"style":5252},[10817],{"type":35,"value":10818},"user",{"type":29,"tag":901,"props":10820,"children":10821},{"style":5185},[10822],{"type":35,"value":3663},{"type":29,"tag":901,"props":10824,"children":10825},{"style":5252},[10826],{"type":35,"value":10827}," subscription",{"type":29,"tag":901,"props":10829,"children":10830},{"style":5185},[10831],{"type":35,"value":3663},{"type":29,"tag":901,"props":10833,"children":10834},{"style":5252},[10835],{"type":35,"value":10836}," promoCode",{"type":29,"tag":901,"props":10838,"children":10839},{"style":5185},[10840],{"type":35,"value":2881},{"type":29,"tag":901,"props":10842,"children":10843},{"style":5185},[10844],{"type":35,"value":7272},{"type":29,"tag":901,"props":10846,"children":10847},{"class":903,"line":469},[10848,10853,10857,10861,10865,10869,10874,10879,10884,10889,10893,10898,10902,10907,10911,10916],{"type":29,"tag":901,"props":10849,"children":10850},{"style":917},[10851],{"type":35,"value":10852},"    if",{"type":29,"tag":901,"props":10854,"children":10855},{"style":923},[10856],{"type":35,"value":7839},{"type":29,"tag":901,"props":10858,"children":10859},{"style":947},[10860],{"type":35,"value":7844},{"type":29,"tag":901,"props":10862,"children":10863},{"style":923},[10864],{"type":35,"value":10818},{"type":29,"tag":901,"props":10866,"children":10867},{"style":7730},[10868],{"type":35,"value":342},{"type":29,"tag":901,"props":10870,"children":10871},{"style":923},[10872],{"type":35,"value":10873},"verified) ",{"type":29,"tag":901,"props":10875,"children":10876},{"style":917},[10877],{"type":35,"value":10878},"return",{"type":29,"tag":901,"props":10880,"children":10881},{"style":5185},[10882],{"type":35,"value":10883}," {",{"type":29,"tag":901,"props":10885,"children":10886},{"style":923},[10887],{"type":35,"value":10888}," eligible",{"type":29,"tag":901,"props":10890,"children":10891},{"style":7730},[10892],{"type":35,"value":5760},{"type":29,"tag":901,"props":10894,"children":10895},{"style":5280},[10896],{"type":35,"value":10897}," false",{"type":29,"tag":901,"props":10899,"children":10900},{"style":5185},[10901],{"type":35,"value":3663},{"type":29,"tag":901,"props":10903,"children":10904},{"style":923},[10905],{"type":35,"value":10906}," reason",{"type":29,"tag":901,"props":10908,"children":10909},{"style":7730},[10910],{"type":35,"value":5760},{"type":29,"tag":901,"props":10912,"children":10913},{"style":2236},[10914],{"type":35,"value":10915}," 'NOT_VERIFIED'",{"type":29,"tag":901,"props":10917,"children":10918},{"style":5185},[10919],{"type":35,"value":10920}," };\n",{"type":29,"tag":901,"props":10922,"children":10923},{"class":903,"line":968},[10924,10928,10933,10937,10942,10947,10952,10957,10961,10965,10969,10973,10977,10981,10985,10989,10994],{"type":29,"tag":901,"props":10925,"children":10926},{"style":917},[10927],{"type":35,"value":10852},{"type":29,"tag":901,"props":10929,"children":10930},{"style":923},[10931],{"type":35,"value":10932}," (subscription",{"type":29,"tag":901,"props":10934,"children":10935},{"style":7730},[10936],{"type":35,"value":342},{"type":29,"tag":901,"props":10938,"children":10939},{"style":923},[10940],{"type":35,"value":10941},"status ",{"type":29,"tag":901,"props":10943,"children":10944},{"style":947},[10945],{"type":35,"value":10946},"!==",{"type":29,"tag":901,"props":10948,"children":10949},{"style":2236},[10950],{"type":35,"value":10951}," 'active'",{"type":29,"tag":901,"props":10953,"children":10954},{"style":923},[10955],{"type":35,"value":10956},") ",{"type":29,"tag":901,"props":10958,"children":10959},{"style":917},[10960],{"type":35,"value":10878},{"type":29,"tag":901,"props":10962,"children":10963},{"style":5185},[10964],{"type":35,"value":10883},{"type":29,"tag":901,"props":10966,"children":10967},{"style":923},[10968],{"type":35,"value":10888},{"type":29,"tag":901,"props":10970,"children":10971},{"style":7730},[10972],{"type":35,"value":5760},{"type":29,"tag":901,"props":10974,"children":10975},{"style":5280},[10976],{"type":35,"value":10897},{"type":29,"tag":901,"props":10978,"children":10979},{"style":5185},[10980],{"type":35,"value":3663},{"type":29,"tag":901,"props":10982,"children":10983},{"style":923},[10984],{"type":35,"value":10906},{"type":29,"tag":901,"props":10986,"children":10987},{"style":7730},[10988],{"type":35,"value":5760},{"type":29,"tag":901,"props":10990,"children":10991},{"style":2236},[10992],{"type":35,"value":10993}," 'INACTIVE_SUB'",{"type":29,"tag":901,"props":10995,"children":10996},{"style":5185},[10997],{"type":35,"value":10920},{"type":29,"tag":901,"props":10999,"children":11000},{"class":903,"line":977},[11001,11005,11010,11015,11019,11023,11028,11033,11037,11041,11046],{"type":29,"tag":901,"props":11002,"children":11003},{"style":917},[11004],{"type":35,"value":10852},{"type":29,"tag":901,"props":11006,"children":11007},{"style":923},[11008],{"type":35,"value":11009}," (promoCode ",{"type":29,"tag":901,"props":11011,"children":11012},{"style":947},[11013],{"type":35,"value":11014},"&&",{"type":29,"tag":901,"props":11016,"children":11017},{"style":923},[11018],{"type":35,"value":10836},{"type":29,"tag":901,"props":11020,"children":11021},{"style":7730},[11022],{"type":35,"value":342},{"type":29,"tag":901,"props":11024,"children":11025},{"style":923},[11026],{"type":35,"value":11027},"usageCount ",{"type":29,"tag":901,"props":11029,"children":11030},{"style":947},[11031],{"type":35,"value":11032},">=",{"type":29,"tag":901,"props":11034,"children":11035},{"style":923},[11036],{"type":35,"value":10836},{"type":29,"tag":901,"props":11038,"children":11039},{"style":7730},[11040],{"type":35,"value":342},{"type":29,"tag":901,"props":11042,"children":11043},{"style":923},[11044],{"type":35,"value":11045},"maxUsage) ",{"type":29,"tag":901,"props":11047,"children":11048},{"style":5185},[11049],{"type":35,"value":7863},{"type":29,"tag":901,"props":11051,"children":11052},{"class":903,"line":986},[11053,11057,11061,11065,11069,11073,11077,11081,11085,11090],{"type":29,"tag":901,"props":11054,"children":11055},{"style":917},[11056],{"type":35,"value":5512},{"type":29,"tag":901,"props":11058,"children":11059},{"style":5185},[11060],{"type":35,"value":10883},{"type":29,"tag":901,"props":11062,"children":11063},{"style":923},[11064],{"type":35,"value":10888},{"type":29,"tag":901,"props":11066,"children":11067},{"style":7730},[11068],{"type":35,"value":5760},{"type":29,"tag":901,"props":11070,"children":11071},{"style":5280},[11072],{"type":35,"value":10897},{"type":29,"tag":901,"props":11074,"children":11075},{"style":5185},[11076],{"type":35,"value":3663},{"type":29,"tag":901,"props":11078,"children":11079},{"style":923},[11080],{"type":35,"value":10906},{"type":29,"tag":901,"props":11082,"children":11083},{"style":7730},[11084],{"type":35,"value":5760},{"type":29,"tag":901,"props":11086,"children":11087},{"style":2236},[11088],{"type":35,"value":11089}," 'PROMO_EXHAUSTED'",{"type":29,"tag":901,"props":11091,"children":11092},{"style":5185},[11093],{"type":35,"value":10920},{"type":29,"tag":901,"props":11095,"children":11096},{"class":903,"line":1007},[11097],{"type":29,"tag":901,"props":11098,"children":11099},{"style":5185},[11100],{"type":35,"value":8093},{"type":29,"tag":901,"props":11102,"children":11103},{"class":903,"line":5354},[11104,11108,11112,11116,11120,11124],{"type":29,"tag":901,"props":11105,"children":11106},{"style":917},[11107],{"type":35,"value":6695},{"type":29,"tag":901,"props":11109,"children":11110},{"style":5185},[11111],{"type":35,"value":10883},{"type":29,"tag":901,"props":11113,"children":11114},{"style":923},[11115],{"type":35,"value":10888},{"type":29,"tag":901,"props":11117,"children":11118},{"style":7730},[11119],{"type":35,"value":5760},{"type":29,"tag":901,"props":11121,"children":11122},{"style":5280},[11123],{"type":35,"value":8470},{"type":29,"tag":901,"props":11125,"children":11126},{"style":5185},[11127],{"type":35,"value":10920},{"type":29,"tag":901,"props":11129,"children":11130},{"class":903,"line":5390},[11131],{"type":29,"tag":901,"props":11132,"children":11133},{"style":5185},[11134],{"type":35,"value":7406},{"type":29,"tag":901,"props":11136,"children":11137},{"class":903,"line":5440},[11138],{"type":29,"tag":901,"props":11139,"children":11140},{"emptyLinePlaceholder":13},[11141],{"type":35,"value":974},{"type":29,"tag":901,"props":11143,"children":11144},{"class":903,"line":5506},[11145],{"type":29,"tag":901,"props":11146,"children":11147},{"style":908},[11148],{"type":35,"value":11149},"// Après génération IA\n",{"type":29,"tag":901,"props":11151,"children":11152},{"class":903,"line":5911},[11153],{"type":29,"tag":901,"props":11154,"children":11155},{"style":908},[11156],{"type":35,"value":11157},"/**\n",{"type":29,"tag":901,"props":11159,"children":11160},{"class":903,"line":5919},[11161],{"type":29,"tag":901,"props":11162,"children":11163},{"style":908},[11164],{"type":35,"value":11165}," * Détermine l'éligibilité d'un utilisateur à appliquer un code promo.\n",{"type":29,"tag":901,"props":11167,"children":11168},{"class":903,"line":5928},[11169],{"type":29,"tag":901,"props":11170,"children":11171},{"style":908},[11172],{"type":35,"value":11173}," *\n",{"type":29,"tag":901,"props":11175,"children":11176},{"class":903,"line":5944},[11177,11182,11187,11192,11197,11202,11206,11211],{"type":29,"tag":901,"props":11178,"children":11179},{"style":908},[11180],{"type":35,"value":11181}," * ",{"type":29,"tag":901,"props":11183,"children":11185},{"style":11184},"--shiki-default:#949CBB;--shiki-dark:#F97583",[11186],{"type":35,"value":8917},{"type":29,"tag":901,"props":11188,"children":11189},{"style":917},[11190],{"type":35,"value":11191},"param",{"type":29,"tag":901,"props":11193,"children":11195},{"style":11194},"--shiki-default:#949CBB;--shiki-dark:#B392F0",[11196],{"type":35,"value":10883},{"type":29,"tag":901,"props":11198,"children":11199},{"style":5179},[11200],{"type":35,"value":11201},"User",{"type":29,"tag":901,"props":11203,"children":11204},{"style":11194},[11205],{"type":35,"value":2255},{"type":29,"tag":901,"props":11207,"children":11208},{"style":5977},[11209],{"type":35,"value":11210}," user",{"type":29,"tag":901,"props":11212,"children":11213},{"style":908},[11214],{"type":35,"value":11215}," - L'utilisateur demandant l'application du promo\n",{"type":29,"tag":901,"props":11217,"children":11218},{"class":903,"line":6003},[11219,11223,11227,11231,11235,11240,11244,11248],{"type":29,"tag":901,"props":11220,"children":11221},{"style":908},[11222],{"type":35,"value":11181},{"type":29,"tag":901,"props":11224,"children":11225},{"style":11184},[11226],{"type":35,"value":8917},{"type":29,"tag":901,"props":11228,"children":11229},{"style":917},[11230],{"type":35,"value":11191},{"type":29,"tag":901,"props":11232,"children":11233},{"style":11194},[11234],{"type":35,"value":10883},{"type":29,"tag":901,"props":11236,"children":11237},{"style":5179},[11238],{"type":35,"value":11239},"Subscription",{"type":29,"tag":901,"props":11241,"children":11242},{"style":11194},[11243],{"type":35,"value":2255},{"type":29,"tag":901,"props":11245,"children":11246},{"style":5977},[11247],{"type":35,"value":10827},{"type":29,"tag":901,"props":11249,"children":11250},{"style":908},[11251],{"type":35,"value":11252}," - L'abonnement actif de l'utilisateur\n",{"type":29,"tag":901,"props":11254,"children":11255},{"class":903,"line":6029},[11256,11260,11264,11268,11272,11277,11281,11285],{"type":29,"tag":901,"props":11257,"children":11258},{"style":908},[11259],{"type":35,"value":11181},{"type":29,"tag":901,"props":11261,"children":11262},{"style":11184},[11263],{"type":35,"value":8917},{"type":29,"tag":901,"props":11265,"children":11266},{"style":917},[11267],{"type":35,"value":11191},{"type":29,"tag":901,"props":11269,"children":11270},{"style":11194},[11271],{"type":35,"value":10883},{"type":29,"tag":901,"props":11273,"children":11274},{"style":5179},[11275],{"type":35,"value":11276},"PromoCode|null",{"type":29,"tag":901,"props":11278,"children":11279},{"style":11194},[11280],{"type":35,"value":2255},{"type":29,"tag":901,"props":11282,"children":11283},{"style":5977},[11284],{"type":35,"value":10836},{"type":29,"tag":901,"props":11286,"children":11287},{"style":908},[11288],{"type":35,"value":11289}," - Le code promo à valider (peut être null)\n",{"type":29,"tag":901,"props":11291,"children":11292},{"class":903,"line":6055},[11293,11297,11301,11306,11310,11315,11319],{"type":29,"tag":901,"props":11294,"children":11295},{"style":908},[11296],{"type":35,"value":11181},{"type":29,"tag":901,"props":11298,"children":11299},{"style":11184},[11300],{"type":35,"value":8917},{"type":29,"tag":901,"props":11302,"children":11303},{"style":917},[11304],{"type":35,"value":11305},"returns",{"type":29,"tag":901,"props":11307,"children":11308},{"style":11194},[11309],{"type":35,"value":10883},{"type":29,"tag":901,"props":11311,"children":11312},{"style":5179},[11313],{"type":35,"value":11314},"{ eligible: boolean, reason?: string }",{"type":29,"tag":901,"props":11316,"children":11317},{"style":11194},[11318],{"type":35,"value":2255},{"type":29,"tag":901,"props":11320,"children":11321},{"style":908},[11322],{"type":35,"value":11323}," Résultat de l'éligibilité\n",{"type":29,"tag":901,"props":11325,"children":11326},{"class":903,"line":6063},[11327],{"type":29,"tag":901,"props":11328,"children":11329},{"style":908},[11330],{"type":35,"value":11331}," */\n",{"type":29,"tag":37,"props":11333,"children":11334},{},[11335,11337,11342],{"type":35,"value":11336},"Limite importante : l'IA génère des docstrings corrects sur la forme, mais peut se tromper sur la sémantique métier. Toujours réviser pour vérifier que la description correspond au comportement réel. la génération IA réduit le temps d'écriture de 80%, elle ne remplace pas la révision humaine. Voir comment intégrer l'",{"type":29,"tag":48,"props":11338,"children":11339},{"href":2117},[11340],{"type":35,"value":11341},"IA dans la code review",{"type":35,"value":11343}," pour un workflow cohérent.",{"type":29,"tag":176,"props":11345,"children":11347},{"cta":178,"href":179,"title":11346,"type":181},"Votre équipe perd du temps sur une base de code non documentée et vous cherchez un plan pragmatique ?",[11348],{"type":29,"tag":37,"props":11349,"children":11350},{},[11351],{"type":35,"value":11352},"Vous savez que la documentation est en retard et que ça coûte cher en onboarding et en interruptions des seniors. Mais vous ne savez pas par où commencer avec l'IA. En 30 minutes, on identifie les 3 actions à impact immédiat sur la productivité de votre équipe.",{"type":29,"tag":76,"props":11354,"children":11355},{},[],{"type":29,"tag":80,"props":11357,"children":11359},{"id":11358},"cas-dusage-3-readme-de-service-et-onboarding-roi-élevé",[11360],{"type":35,"value":11361},"Cas d'usage 3 : README de service et onboarding (ROI élevé)",{"type":29,"tag":37,"props":11363,"children":11364},{},[11365,11369],{"type":29,"tag":65,"props":11366,"children":11367},{},[11368],{"type":35,"value":10666},{"type":35,"value":11370}," chaque service d'un système distribué devrait avoir un README qui explique son rôle, comment le démarrer en local, comment le tester, et les variables d'environnement requises. En pratique, ces READMEs sont absents ou obsolètes.",{"type":29,"tag":37,"props":11372,"children":11373},{},[11374,11378],{"type":29,"tag":65,"props":11375,"children":11376},{},[11377],{"type":35,"value":10676},{"type":35,"value":11379}," à partir du code source (package.json, Dockerfile, docker-compose.yml, code principal), l'IA génère un README structuré.",{"type":29,"tag":37,"props":11381,"children":11382},{},[11383],{"type":35,"value":11384},"Prompt type :",{"type":29,"tag":651,"props":11386,"children":11388},{"code":11387},"Voici le package.json, le Dockerfile, et le fichier main.ts d'un service Node.js.\nGénère un README.md complet incluant :\n- Description du service et son rôle dans l'architecture\n- Prérequis\n- Installation et démarrage en local\n- Variables d'environnement (liste depuis le code)\n- Endpoints principaux\n- Comment lancer les tests\n",[11389],{"type":29,"tag":565,"props":11390,"children":11391},{"__ignoreMap":8},[11392],{"type":35,"value":11387},{"type":29,"tag":37,"props":11394,"children":11395},{},[11396,11401],{"type":29,"tag":65,"props":11397,"children":11398},{},[11399],{"type":35,"value":11400},"Ce que l'humain ajoute :",{"type":35,"value":11402}," le contexte business (quel problème ce service résout), les dépendances avec les autres services, les décisions d'architecture importantes.",{"type":29,"tag":37,"props":11404,"children":11405},{},[11406,11411],{"type":29,"tag":65,"props":11407,"children":11408},{},[11409],{"type":35,"value":11410},"Gain pour l'onboarding :",{"type":35,"value":11412}," un nouveau développeur avec des READMEs à jour démarre en autonomie 3 à 5 jours plus tôt qu'avec des READMEs absents. Sur une équipe qui recrute 4 personnes par an, c'est 12 à 20 jours de productivité récupérés chaque année.",{"type":29,"tag":76,"props":11414,"children":11415},{},[],{"type":29,"tag":80,"props":11417,"children":11419},{"id":11418},"cas-dusage-4-résumés-de-pr-et-commit-messages-roi-élevé",[11420],{"type":35,"value":11421},"Cas d'usage 4 : Résumés de PR et commit messages (ROI élevé)",{"type":29,"tag":37,"props":11423,"children":11424},{},[11425,11429],{"type":29,"tag":65,"props":11426,"children":11427},{},[11428],{"type":35,"value":10666},{"type":35,"value":11430}," les commit messages et descriptions de PR sont soit vides (\"fix bug\", \"update code\"), soit trop détaillés pour être lus. L'historique git devient inutilisable.",{"type":29,"tag":37,"props":11432,"children":11433},{},[11434,11438],{"type":29,"tag":65,"props":11435,"children":11436},{},[11437],{"type":35,"value":10676},{"type":35,"value":11439}," à partir du diff d'une PR, l'IA génère un résumé structuré (ce qui a changé, pourquoi, les impacts potentiels, le plan de test).",{"type":29,"tag":37,"props":11441,"children":11442},{},[11443],{"type":35,"value":11444},"GitHub Copilot peut générer des descriptions de PR automatiquement. Alternativement, un script pre-commit qui appelle l'API Claude avec le diff :",{"type":29,"tag":651,"props":11446,"children":11450},{"code":11447,"language":11448,"meta":8,"className":11449,"style":8},"# Script pre-commit simplifié\ngit diff --cached | claude -p \"Génère un commit message conventionnel en anglais\npour ce diff. Format: type(scope): description. Types: feat/fix/refactor/test/docs\"\n","bash","language-bash shiki shiki-themes catppuccin-frappe github-dark",[11451],{"type":29,"tag":565,"props":11452,"children":11453},{"__ignoreMap":8},[11454,11462,11500],{"type":29,"tag":901,"props":11455,"children":11456},{"class":903,"line":904},[11457],{"type":29,"tag":901,"props":11458,"children":11459},{"style":908},[11460],{"type":35,"value":11461},"# Script pre-commit simplifié\n",{"type":29,"tag":901,"props":11463,"children":11464},{"class":903,"line":463},[11465,11470,11475,11481,11485,11490,11495],{"type":29,"tag":901,"props":11466,"children":11467},{"style":5362},[11468],{"type":35,"value":11469},"git",{"type":29,"tag":901,"props":11471,"children":11472},{"style":2236},[11473],{"type":35,"value":11474}," diff",{"type":29,"tag":901,"props":11476,"children":11478},{"style":11477},"--shiki-default:#A6D189;--shiki-dark:#79B8FF",[11479],{"type":35,"value":11480}," --cached",{"type":29,"tag":901,"props":11482,"children":11483},{"style":947},[11484],{"type":35,"value":7384},{"type":29,"tag":901,"props":11486,"children":11487},{"style":5362},[11488],{"type":35,"value":11489}," claude",{"type":29,"tag":901,"props":11491,"children":11492},{"style":11477},[11493],{"type":35,"value":11494}," -p",{"type":29,"tag":901,"props":11496,"children":11497},{"style":2236},[11498],{"type":35,"value":11499}," \"Génère un commit message conventionnel en anglais\n",{"type":29,"tag":901,"props":11501,"children":11502},{"class":903,"line":469},[11503],{"type":29,"tag":901,"props":11504,"children":11505},{"style":2236},[11506],{"type":35,"value":11507},"pour ce diff. Format: type(scope): description. Types: feat/fix/refactor/test/docs\"\n",{"type":29,"tag":37,"props":11509,"children":11510},{},[11511,11513,11518],{"type":35,"value":11512},"Bénéfice secondaire : des descriptions de PR de qualité améliorent le processus de code review, le reviewer comprend rapidement l'intention du changement avant de lire le code. Une étude de ",{"type":29,"tag":65,"props":11514,"children":11515},{},[11516],{"type":35,"value":11517},"l'équipe DevEx de Google (2023)",{"type":35,"value":11519}," sur la qualité des PRs indique que des descriptions claires réduisent le temps de review de 15 à 25%.",{"type":29,"tag":76,"props":11521,"children":11522},{},[],{"type":29,"tag":80,"props":11524,"children":11526},{"id":11525},"cas-dusage-5-mise-à-jour-de-documentation-existante-roi-moyen",[11527],{"type":35,"value":11528},"Cas d'usage 5 : Mise à jour de documentation existante (ROI moyen)",{"type":29,"tag":37,"props":11530,"children":11531},{},[11532,11536],{"type":29,"tag":65,"props":11533,"children":11534},{},[11535],{"type":35,"value":10666},{"type":35,"value":11537}," la documentation existante se désynchronise du code. Une API change, la documentation ne change pas. Un développeur suit la doc et se retrouve avec des erreurs incompréhensibles.",{"type":29,"tag":37,"props":11539,"children":11540},{},[11541,11545],{"type":29,"tag":65,"props":11542,"children":11543},{},[11544],{"type":35,"value":10676},{"type":35,"value":11546}," comparer la documentation existante avec le code actuel et identifier les divergences.",{"type":29,"tag":37,"props":11548,"children":11549},{},[11550],{"type":35,"value":11384},{"type":29,"tag":651,"props":11552,"children":11554},{"code":11553},"Voici la documentation actuelle de l'API /users/{id}/subscriptions :\n[documentation]\n\nVoici le code actuel de cet endpoint :\n[code]\n\nIdentifie les divergences entre la documentation et le code, et propose\nune documentation mise à jour.\n",[11555],{"type":29,"tag":565,"props":11556,"children":11557},{"__ignoreMap":8},[11558],{"type":35,"value":11553},{"type":29,"tag":37,"props":11560,"children":11561},{},[11562],{"type":35,"value":11563},"Limite : l'IA identifie les divergences techniques (paramètres manquants, types incorrects) mais pas les divergences de logique métier. La révision humaine reste nécessaire.",{"type":29,"tag":76,"props":11565,"children":11566},{},[],{"type":29,"tag":80,"props":11568,"children":11570},{"id":11569},"ce-que-lia-ne-peut-pas-documenter",[11571],{"type":35,"value":11572},"Ce que l'IA ne peut pas documenter",{"type":29,"tag":37,"props":11574,"children":11575},{},[11576,11586],{"type":29,"tag":65,"props":11577,"children":11578},{},[11579,11584],{"type":29,"tag":48,"props":11580,"children":11581},{"href":610},[11582],{"type":35,"value":11583},"Décisions d'architecture",{"type":35,"value":11585}," :",{"type":35,"value":11587}," pourquoi Event Sourcing plutôt que CRUD, pourquoi PostgreSQL plutôt que MongoDB, pourquoi ce découpage en microservices. Ces décisions ont un contexte (contraintes techniques, état de l'équipe, urgence du moment) que l'IA ne peut pas reconstruire. Les ADR (Architecture Decision Records) restent un exercice humain.",{"type":29,"tag":37,"props":11589,"children":11590},{},[11591,11596],{"type":29,"tag":65,"props":11592,"children":11593},{},[11594],{"type":35,"value":11595},"Contraintes non-exprimées dans le code :",{"type":35,"value":11597}," un timeout à 3 secondes dans une config qui existe parce qu'un service tiers SLA garantit 99% de réponses en moins de 2,5 secondes. Sans commentaire humain, l'IA ne peut pas savoir que cette valeur ne doit pas changer.",{"type":29,"tag":37,"props":11599,"children":11600},{},[11601,11606],{"type":29,"tag":65,"props":11602,"children":11603},{},[11604],{"type":35,"value":11605},"Le \"pourquoi ça ne marche pas\" :",{"type":35,"value":11607}," les runbooks de debugging, les solutions aux problèmes connus, les workarounds pour les bugs connus des dépendances. Ces informations viennent de l'expérience terrain, pas du code.",{"type":29,"tag":76,"props":11609,"children":11610},{},[],{"type":29,"tag":80,"props":11612,"children":11614},{"id":11613},"comment-intégrer-lia-dans-le-workflow-de-documentation",[11615],{"type":35,"value":11616},"Comment intégrer l'IA dans le workflow de documentation",{"type":29,"tag":37,"props":11618,"children":11619},{},[11620,11625,11627,11632],{"type":29,"tag":65,"props":11621,"children":11622},{},[11623],{"type":35,"value":11624},"Option A : Documentation as part of PR :",{"type":35,"value":11626}," ajouter à la ",{"type":29,"tag":48,"props":11628,"children":11629},{"href":4950},[11630],{"type":35,"value":11631},"Definition of Done",{"type":35,"value":11633}," que toute nouvelle API ou service doit avoir sa documentation générée par IA et révisée par l'auteur. Le reviewer vérifie la documentation comme il vérifie le code.",{"type":29,"tag":37,"props":11635,"children":11636},{},[11637,11642],{"type":29,"tag":65,"props":11638,"children":11639},{},[11640],{"type":35,"value":11641},"Option B : Sprint de documentation :",{"type":35,"value":11643}," une fois par trimestre, un sprint de 2 jours dédié à la mise à jour de la documentation avec assistance IA. Chaque développeur génère la doc de ses services et la révise.",{"type":29,"tag":37,"props":11645,"children":11646},{},[11647,11652],{"type":29,"tag":65,"props":11648,"children":11649},{},[11650],{"type":35,"value":11651},"Option C : Automatisation continue :",{"type":35,"value":11653}," un pipeline CI qui génère automatiquement la documentation OpenAPI à partir des annotations de code et la déploie dans un portail de documentation (Stoplight, Backstage). La doc est toujours à jour avec le code.",{"type":29,"tag":37,"props":11655,"children":11656},{},[11657],{"type":35,"value":11658},"La séquence que je recommande : commencer par les READMEs des services critiques (impact onboarding immédiat), puis la documentation des APIs internes (impact developer experience), puis les résumés de PR (impact code review quality).",{"type":29,"tag":76,"props":11660,"children":11661},{},[],{"type":29,"tag":80,"props":11663,"children":11665},{"id":11664},"faq-sur-lia-et-la-documentation-technique",[11666],{"type":35,"value":11667},"FAQ sur l'IA et la documentation technique",{"type":29,"tag":381,"props":11669,"children":11670},{},[11671,11676],{"type":29,"tag":385,"props":11672,"children":11673},{},[11674],{"type":35,"value":11675},"1. La documentation générée par IA est-elle fiable ?",{"type":29,"tag":37,"props":11677,"children":11678},{},[11679],{"type":35,"value":11680},"Pour le \"quoi\" technique (paramètres, types, structure), oui, avec révision. L'IA peut se tromper sur la sémantique d'une valeur de retour ou sur le comportement dans les cas d'erreur. La règle : toute documentation générée est relue par le développeur qui connaît le code avant d'être mergée. La génération IA réduit le temps d'écriture de 80%, elle ne remplace pas la révision humaine.",{"type":29,"tag":381,"props":11682,"children":11683},{},[11684,11689],{"type":29,"tag":385,"props":11685,"children":11686},{},[11687],{"type":35,"value":11688},"2. Quels outils IA utiliser pour la documentation ?",{"type":29,"tag":37,"props":11690,"children":11691},{},[11692],{"type":35,"value":11693},"GitHub Copilot intégré dans l'IDE génère des docstrings en temps réel. Claude ou GPT-4 pour la génération de READMEs et docs d'API depuis le code. Mintlify Doc Writer (extension VSCode) pour les docstrings. Pour la documentation OpenAPI automatique, les annotations natives de FastAPI ou Spring Boot font mieux que l'IA, le framework le gère nativement.",{"type":29,"tag":381,"props":11695,"children":11696},{},[11697,11702],{"type":29,"tag":385,"props":11698,"children":11699},{},[11700],{"type":35,"value":11701},"3. Comment éviter que la documentation générée soit obsolète dès le lendemain ?",{"type":29,"tag":37,"props":11703,"children":11704},{},[11705],{"type":35,"value":11706},"Deux stratégies : (1) Documentation automatique synchronisée avec le code (OpenAPI généré par le framework, Storybook pour les composants frontend), toujours à jour par construction. (2) Documentation révisée par humain + tests de documentation qui vérifient que les exemples de code dans la doc compilent et retournent les bons résultats. L'approche hybride : génération automatique pour les APIs, révision humaine pour les guides.",{"type":29,"tag":381,"props":11708,"children":11709},{},[11710,11715],{"type":29,"tag":385,"props":11711,"children":11712},{},[11713],{"type":35,"value":11714},"4. Les développeurs seniors résistent à documenter même avec l'IA : comment les convaincre ?",{"type":29,"tag":37,"props":11716,"children":11717},{},[11718],{"type":35,"value":11719},"En changeant le cadre. La documentation n'est pas un effort pour les autres, c'est une réduction du coût de maintenance pour soi. Le développeur senior qui documente son service aujourd'hui est celui qui ne répondra plus à 3 questions par semaine sur ce service dans 6 mois. Calculez le coût réel des interruptions : 3 questions × 30 min × 52 semaines = 78 heures/an, contre 2 heures de documentation avec IA. L'argument est économique, pas moral.",{"type":29,"tag":381,"props":11721,"children":11722},{},[11723,11728],{"type":29,"tag":385,"props":11724,"children":11725},{},[11726],{"type":35,"value":11727},"5. Faut-il documenter en français ou en anglais ?",{"type":29,"tag":37,"props":11729,"children":11730},{},[11731],{"type":35,"value":11732},"Le code et les commentaires techniques dans la même langue que le reste du codebase (souvent anglais dans les équipes internationales). Les READMEs et guides internes dans la langue de l'équipe. La règle pratique : si un document sera lu par des personnes externes à l'équipe → anglais. Si interne à l'équipe → langue de l'équipe.",{"type":29,"tag":76,"props":11734,"children":11735},{},[],{"type":29,"tag":176,"props":11737,"children":11739},{"cta":11738,"href":453,"title":4082,"type":455},"Télécharger la checklist gratuite →",[11740],{"type":29,"tag":37,"props":11741,"children":11742},{},[11743],{"type":35,"value":11744},"La checklist AI-Ready inclut les cas d'usage IA validés par pilier (documentation, code review, tests, architecture) et le framework d'évaluation d'adoption pour votre équipe. Avec les métriques de ROI pour chaque cas d'usage.",{"type":29,"tag":1252,"props":11746,"children":11747},{},[11748],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":11750},[11751,11752,11753,11754,11755,11756,11757,11758,11759],{"id":10616,"depth":463,"text":10619},{"id":10655,"depth":463,"text":10658},{"id":10758,"depth":463,"text":10761},{"id":11358,"depth":463,"text":11361},{"id":11418,"depth":463,"text":11421},{"id":11525,"depth":463,"text":11528},{"id":11569,"depth":463,"text":11572},{"id":11613,"depth":463,"text":11616},{"id":11664,"depth":463,"text":11667},"content:fr:intelligence-artificielle:ia-documentation-technique-cas-usage.md","fr/intelligence-artificielle/ia-documentation-technique-cas-usage.md","fr/intelligence-artificielle/ia-documentation-technique-cas-usage",{"_path":11764,"_dir":4106,"_draft":7,"_partial":7,"_locale":8,"title":11765,"description":11766,"id":6327,"date":11767,"listed":13,"nocomments":7,"hidden":7,"categories":11768,"tags":11769,"--cover":11773,"readingTime":11774,"body":11778,"_type":476,"_id":12558,"_source":478,"_file":12559,"_stem":12560,"_extension":481},"/fr/pratiques-agiles/continuous-integration-fondamentaux","Continuous Integration : les 5 fondamentaux non-négociables","Avoir Jenkins ou GitHub Actions n'est pas faire de la CI. La vraie CI implique des pratiques humaines que l'outil seul ne peut pas imposer.","2026-03-06",[4106],[11770,11771,11772,2128],"Continuous Integration","CI/CD","Pipeline","covers/articles/continuous-integration-fondamentaux.jpg",{"text":21,"minutes":11775,"time":11776,"words":11777},8.17,490200,1634,{"type":26,"children":11779,"toc":12548},[11780,11785,11790,11795,11800,11805,11810,11813,11819,11824,11834,11844,11854,11859,11862,11868,11873,11878,11883,12002,12007,12010,12016,12021,12026,12031,12299,12308,12311,12317,12322,12327,12332,12337,12340,12346,12351,12356,12361,12364,12370,12381,12386,12422,12427,12430,12436,12441,12446,12459,12462,12468,12481,12494,12507,12520,12533,12536,12544],{"type":29,"tag":30,"props":11781,"children":11783},{"id":11782},"continuous-integration-les-5-fondamentaux-non-négociables",[11784],{"type":35,"value":11765},{"type":29,"tag":37,"props":11786,"children":11787},{},[11788],{"type":35,"value":11789},"Dans un client dans l'édition logicielle que j'accompagnais (15 développeurs, produit financier B2B), le pipeline CI durait 28 minutes. Les branches vivaient en moyenne 4 jours avant d'être mergées. L'équipe avait GitHub Actions configuré depuis 18 mois. Elle pensait pratiquer la Continuous Integration.",{"type":29,"tag":37,"props":11791,"children":11792},{},[11793],{"type":35,"value":11794},"Elle pratiquait le contraire.",{"type":29,"tag":37,"props":11796,"children":11797},{},[11798],{"type":35,"value":11799},"Les merges de longues branches généraient des conflits quotidiens. Les builds rouges duraient parfois 6 heures avant d'être corrigés. Et les développeurs avaient arrêté de regarder les alertes du pipeline depuis longtemps : trop de faux positifs, trop de délai entre le commit et le feedback.",{"type":29,"tag":37,"props":11801,"children":11802},{},[11803],{"type":35,"value":11804},"La Continuous Integration est une discipline humaine autant qu'une infrastructure technique. La plupart des équipes ont l'outil, et pratiquent le contraire de la CI sans le savoir.",{"type":29,"tag":37,"props":11806,"children":11807},{},[11808],{"type":35,"value":11809},"La définition originale vient de Kent Beck (Extreme Programming, 1999) et Martin Fowler : intégrer ses changements dans la branche principale plusieurs fois par jour. Pas une fois par semaine lors de la \"merge PR\". Plusieurs fois par jour. Selon les recherches DORA, les équipes qui pratiquent la vraie CI ont un lead time 4 fois inférieur et un taux d'échec de déploiement 3 fois plus bas. Ce n'est pas l'outil qui fait la différence : c'est la discipline.",{"type":29,"tag":76,"props":11811,"children":11812},{},[],{"type":29,"tag":80,"props":11814,"children":11816},{"id":11815},"ce-que-la-ci-nest-pas",[11817],{"type":35,"value":11818},"Ce que la CI n'est pas",{"type":29,"tag":37,"props":11820,"children":11821},{},[11822],{"type":35,"value":11823},"Trois confusions fréquentes méritent d'être clarifiées avant d'aller plus loin.",{"type":29,"tag":37,"props":11825,"children":11826},{},[11827,11832],{"type":29,"tag":65,"props":11828,"children":11829},{},[11830],{"type":35,"value":11831},"La CI n'est pas un pipeline de build automatisé.",{"type":35,"value":11833}," Lancer des tests automatiquement à chaque push n'est pas de la CI si les branches durent 2 semaines avant d'être mergées. L'automatisation sans intégration fréquente, c'est du quality assurance sur des changements isolés.",{"type":29,"tag":37,"props":11835,"children":11836},{},[11837,11842],{"type":29,"tag":65,"props":11838,"children":11839},{},[11840],{"type":35,"value":11841},"La CI n'est pas un gating de qualité.",{"type":35,"value":11843}," Utiliser le pipeline pour bloquer les PRs avec des tests qui échouent est utile, mais c'est de l'assurance qualité, pas de la CI au sens strict.",{"type":29,"tag":37,"props":11845,"children":11846},{},[11847,11852],{"type":29,"tag":65,"props":11848,"children":11849},{},[11850],{"type":35,"value":11851},"La CI n'est pas une histoire de fréquence de déploiement.",{"type":35,"value":11853}," Déployer souvent (CD) est différent d'intégrer souvent (CI). On peut déployer une fois par jour depuis une branche de longue durée : ce n'est pas de la CI.",{"type":29,"tag":37,"props":11855,"children":11856},{},[11857],{"type":35,"value":11858},"La définition précise de Martin Fowler : \"Continuous Integration is a practice where members of a team merge their work frequently, usually each person merges at least daily.\" L'accent est sur la fréquence d'intégration, pas sur l'automatisation.",{"type":29,"tag":76,"props":11860,"children":11861},{},[],{"type":29,"tag":80,"props":11863,"children":11865},{"id":11864},"fondamental-1-intégrer-dans-le-trunk-au-moins-une-fois-par-jour",[11866],{"type":35,"value":11867},"Fondamental 1 : Intégrer dans le trunk au moins une fois par jour",{"type":29,"tag":37,"props":11869,"children":11870},{},[11871],{"type":35,"value":11872},"Chaque développeur intègre son code dans la branche principale (main, master, trunk) au moins une fois toutes les 24 heures.",{"type":29,"tag":37,"props":11874,"children":11875},{},[11876],{"type":35,"value":11877},"Ce qui rend cela difficile : ça suppose que chaque commit soit dans un état qui ne casse pas la branche principale. Ce qui implique des feature flags pour les fonctionnalités incomplètes, et une culture de \"never break the trunk\".",{"type":29,"tag":37,"props":11879,"children":11880},{},[11881],{"type":35,"value":11882},"Les feature flags permettent d'intégrer du code incomplet sans l'exposer aux utilisateurs. C'est le mécanisme qui rend la CI viable pour des fonctionnalités qui prennent plus d'une journée :",{"type":29,"tag":651,"props":11884,"children":11886},{"className":2200,"code":11885,"language":2202,"meta":8,"style":8},"# La fonctionnalité n'est pas terminée mais le code est intégré\nif feature_flags.is_enabled('new_checkout_flow', user):\n    return new_checkout_flow(request)\nelse:\n    return legacy_checkout_flow(request)\n",[11887],{"type":29,"tag":565,"props":11888,"children":11889},{"__ignoreMap":8},[11890,11898,11941,11966,11978],{"type":29,"tag":901,"props":11891,"children":11892},{"class":903,"line":904},[11893],{"type":29,"tag":901,"props":11894,"children":11895},{"style":908},[11896],{"type":35,"value":11897},"# La fonctionnalité n'est pas terminée mais le code est intégré\n",{"type":29,"tag":901,"props":11899,"children":11900},{"class":903,"line":463},[11901,11906,11911,11915,11920,11924,11929,11933,11937],{"type":29,"tag":901,"props":11902,"children":11903},{"style":917},[11904],{"type":35,"value":11905},"if",{"type":29,"tag":901,"props":11907,"children":11908},{"style":923},[11909],{"type":35,"value":11910}," feature_flags",{"type":29,"tag":901,"props":11912,"children":11913},{"style":5185},[11914],{"type":35,"value":342},{"type":29,"tag":901,"props":11916,"children":11917},{"style":5242},[11918],{"type":35,"value":11919},"is_enabled",{"type":29,"tag":901,"props":11921,"children":11922},{"style":5185},[11923],{"type":35,"value":3080},{"type":29,"tag":901,"props":11925,"children":11926},{"style":2236},[11927],{"type":35,"value":11928},"'new_checkout_flow'",{"type":29,"tag":901,"props":11930,"children":11931},{"style":5185},[11932],{"type":35,"value":3663},{"type":29,"tag":901,"props":11934,"children":11935},{"style":923},[11936],{"type":35,"value":11210},{"type":29,"tag":901,"props":11938,"children":11939},{"style":5185},[11940],{"type":35,"value":5217},{"type":29,"tag":901,"props":11942,"children":11943},{"class":903,"line":469},[11944,11948,11953,11957,11962],{"type":29,"tag":901,"props":11945,"children":11946},{"style":917},[11947],{"type":35,"value":6695},{"type":29,"tag":901,"props":11949,"children":11950},{"style":5242},[11951],{"type":35,"value":11952}," new_checkout_flow",{"type":29,"tag":901,"props":11954,"children":11955},{"style":5185},[11956],{"type":35,"value":3080},{"type":29,"tag":901,"props":11958,"children":11959},{"style":923},[11960],{"type":35,"value":11961},"request",{"type":29,"tag":901,"props":11963,"children":11964},{"style":5185},[11965],{"type":35,"value":5437},{"type":29,"tag":901,"props":11967,"children":11968},{"class":903,"line":968},[11969,11974],{"type":29,"tag":901,"props":11970,"children":11971},{"style":917},[11972],{"type":35,"value":11973},"else",{"type":29,"tag":901,"props":11975,"children":11976},{"style":5185},[11977],{"type":35,"value":5188},{"type":29,"tag":901,"props":11979,"children":11980},{"class":903,"line":977},[11981,11985,11990,11994,11998],{"type":29,"tag":901,"props":11982,"children":11983},{"style":917},[11984],{"type":35,"value":6695},{"type":29,"tag":901,"props":11986,"children":11987},{"style":5242},[11988],{"type":35,"value":11989}," legacy_checkout_flow",{"type":29,"tag":901,"props":11991,"children":11992},{"style":5185},[11993],{"type":35,"value":3080},{"type":29,"tag":901,"props":11995,"children":11996},{"style":923},[11997],{"type":35,"value":11961},{"type":29,"tag":901,"props":11999,"children":12000},{"style":5185},[12001],{"type":35,"value":5437},{"type":29,"tag":37,"props":12003,"children":12004},{},[12005],{"type":35,"value":12006},"Le signal d'alerte est simple : si vos branches vivent plus de 2 jours, vous ne pratiquez pas la CI : vous faites du \"integrate when done.\"",{"type":29,"tag":76,"props":12008,"children":12009},{},[],{"type":29,"tag":80,"props":12011,"children":12013},{"id":12012},"fondamental-2-le-pipeline-de-build-doit-passer-en-moins-de-10-minutes",[12014],{"type":35,"value":12015},"Fondamental 2 : Le pipeline de build doit passer en moins de 10 minutes",{"type":29,"tag":37,"props":12017,"children":12018},{},[12019],{"type":35,"value":12020},"Si le feedback du pipeline prend plus de 10 minutes, les développeurs arrêtent d'attendre le résultat avant de passer à la tâche suivante. Le feedback loop se rompt.",{"type":29,"tag":37,"props":12022,"children":12023},{},[12024],{"type":35,"value":12025},"Cette règle vient des recherches sur la productivité des développeurs : au-delà de 10 minutes, le développeur a changé de contexte mental. Quand le pipeline échoue 15 minutes plus tard, le coût de retour au contexte est élevé.",{"type":29,"tag":37,"props":12027,"children":12028},{},[12029],{"type":35,"value":12030},"Pour maintenir un pipeline sous 10 minutes : tests unitaires en parallèle, tests d'intégration sélectifs basés sur les changements, cache agressif des dépendances, et séparation en stages, avec un fast feedback en moins de 5 minutes et un slow feedback déclenché séparément.",{"type":29,"tag":651,"props":12032,"children":12036},{"className":12033,"code":12034,"language":12035,"meta":8,"style":8},"language-yaml shiki shiki-themes catppuccin-frappe github-dark","# GitHub Actions — jobs parallèles\njobs:\n  unit-tests:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm run test:unit    # \u003C 3 min\n\n  lint-typecheck:\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm run lint && npm run typecheck    # \u003C 2 min\n\n  integration-tests:\n    needs: [unit-tests]    # Seulement si les unit tests passent\n    runs-on: ubuntu-latest\n    steps:\n      - run: npm run test:integration    # \u003C 10 min\n","yaml",[12037],{"type":29,"tag":565,"props":12038,"children":12039},{"__ignoreMap":8},[12040,12048,12061,12073,12090,12102,12129,12136,12148,12163,12174,12199,12206,12218,12248,12263,12274],{"type":29,"tag":901,"props":12041,"children":12042},{"class":903,"line":904},[12043],{"type":29,"tag":901,"props":12044,"children":12045},{"style":908},[12046],{"type":35,"value":12047},"# GitHub Actions — jobs parallèles\n",{"type":29,"tag":901,"props":12049,"children":12050},{"class":903,"line":463},[12051,12057],{"type":29,"tag":901,"props":12052,"children":12054},{"style":12053},"--shiki-default:#8CAAEE;--shiki-dark:#85E89D",[12055],{"type":35,"value":12056},"jobs",{"type":29,"tag":901,"props":12058,"children":12059},{"style":7730},[12060],{"type":35,"value":5188},{"type":29,"tag":901,"props":12062,"children":12063},{"class":903,"line":469},[12064,12069],{"type":29,"tag":901,"props":12065,"children":12066},{"style":12053},[12067],{"type":35,"value":12068},"  unit-tests",{"type":29,"tag":901,"props":12070,"children":12071},{"style":7730},[12072],{"type":35,"value":5188},{"type":29,"tag":901,"props":12074,"children":12075},{"class":903,"line":968},[12076,12081,12085],{"type":29,"tag":901,"props":12077,"children":12078},{"style":12053},[12079],{"type":35,"value":12080},"    runs-on",{"type":29,"tag":901,"props":12082,"children":12083},{"style":7730},[12084],{"type":35,"value":5760},{"type":29,"tag":901,"props":12086,"children":12087},{"style":2236},[12088],{"type":35,"value":12089}," ubuntu-latest\n",{"type":29,"tag":901,"props":12091,"children":12092},{"class":903,"line":977},[12093,12098],{"type":29,"tag":901,"props":12094,"children":12095},{"style":12053},[12096],{"type":35,"value":12097},"    steps",{"type":29,"tag":901,"props":12099,"children":12100},{"style":7730},[12101],{"type":35,"value":5188},{"type":29,"tag":901,"props":12103,"children":12104},{"class":903,"line":986},[12105,12110,12115,12119,12124],{"type":29,"tag":901,"props":12106,"children":12107},{"style":5185},[12108],{"type":35,"value":12109},"      -",{"type":29,"tag":901,"props":12111,"children":12112},{"style":12053},[12113],{"type":35,"value":12114}," run",{"type":29,"tag":901,"props":12116,"children":12117},{"style":7730},[12118],{"type":35,"value":5760},{"type":29,"tag":901,"props":12120,"children":12121},{"style":2236},[12122],{"type":35,"value":12123}," npm run test:unit",{"type":29,"tag":901,"props":12125,"children":12126},{"style":908},[12127],{"type":35,"value":12128},"    # \u003C 3 min\n",{"type":29,"tag":901,"props":12130,"children":12131},{"class":903,"line":1007},[12132],{"type":29,"tag":901,"props":12133,"children":12134},{"emptyLinePlaceholder":13},[12135],{"type":35,"value":974},{"type":29,"tag":901,"props":12137,"children":12138},{"class":903,"line":5354},[12139,12144],{"type":29,"tag":901,"props":12140,"children":12141},{"style":12053},[12142],{"type":35,"value":12143},"  lint-typecheck",{"type":29,"tag":901,"props":12145,"children":12146},{"style":7730},[12147],{"type":35,"value":5188},{"type":29,"tag":901,"props":12149,"children":12150},{"class":903,"line":5390},[12151,12155,12159],{"type":29,"tag":901,"props":12152,"children":12153},{"style":12053},[12154],{"type":35,"value":12080},{"type":29,"tag":901,"props":12156,"children":12157},{"style":7730},[12158],{"type":35,"value":5760},{"type":29,"tag":901,"props":12160,"children":12161},{"style":2236},[12162],{"type":35,"value":12089},{"type":29,"tag":901,"props":12164,"children":12165},{"class":903,"line":5440},[12166,12170],{"type":29,"tag":901,"props":12167,"children":12168},{"style":12053},[12169],{"type":35,"value":12097},{"type":29,"tag":901,"props":12171,"children":12172},{"style":7730},[12173],{"type":35,"value":5188},{"type":29,"tag":901,"props":12175,"children":12176},{"class":903,"line":5506},[12177,12181,12185,12189,12194],{"type":29,"tag":901,"props":12178,"children":12179},{"style":5185},[12180],{"type":35,"value":12109},{"type":29,"tag":901,"props":12182,"children":12183},{"style":12053},[12184],{"type":35,"value":12114},{"type":29,"tag":901,"props":12186,"children":12187},{"style":7730},[12188],{"type":35,"value":5760},{"type":29,"tag":901,"props":12190,"children":12191},{"style":2236},[12192],{"type":35,"value":12193}," npm run lint && npm run typecheck",{"type":29,"tag":901,"props":12195,"children":12196},{"style":908},[12197],{"type":35,"value":12198},"    # \u003C 2 min\n",{"type":29,"tag":901,"props":12200,"children":12201},{"class":903,"line":5911},[12202],{"type":29,"tag":901,"props":12203,"children":12204},{"emptyLinePlaceholder":13},[12205],{"type":35,"value":974},{"type":29,"tag":901,"props":12207,"children":12208},{"class":903,"line":5919},[12209,12214],{"type":29,"tag":901,"props":12210,"children":12211},{"style":12053},[12212],{"type":35,"value":12213},"  integration-tests",{"type":29,"tag":901,"props":12215,"children":12216},{"style":7730},[12217],{"type":35,"value":5188},{"type":29,"tag":901,"props":12219,"children":12220},{"class":903,"line":5928},[12221,12226,12230,12234,12239,12243],{"type":29,"tag":901,"props":12222,"children":12223},{"style":12053},[12224],{"type":35,"value":12225},"    needs",{"type":29,"tag":901,"props":12227,"children":12228},{"style":7730},[12229],{"type":35,"value":5760},{"type":29,"tag":901,"props":12231,"children":12232},{"style":5185},[12233],{"type":35,"value":7129},{"type":29,"tag":901,"props":12235,"children":12236},{"style":2236},[12237],{"type":35,"value":12238},"unit-tests",{"type":29,"tag":901,"props":12240,"children":12241},{"style":5185},[12242],{"type":35,"value":6939},{"type":29,"tag":901,"props":12244,"children":12245},{"style":908},[12246],{"type":35,"value":12247},"    # Seulement si les unit tests passent\n",{"type":29,"tag":901,"props":12249,"children":12250},{"class":903,"line":5944},[12251,12255,12259],{"type":29,"tag":901,"props":12252,"children":12253},{"style":12053},[12254],{"type":35,"value":12080},{"type":29,"tag":901,"props":12256,"children":12257},{"style":7730},[12258],{"type":35,"value":5760},{"type":29,"tag":901,"props":12260,"children":12261},{"style":2236},[12262],{"type":35,"value":12089},{"type":29,"tag":901,"props":12264,"children":12265},{"class":903,"line":6003},[12266,12270],{"type":29,"tag":901,"props":12267,"children":12268},{"style":12053},[12269],{"type":35,"value":12097},{"type":29,"tag":901,"props":12271,"children":12272},{"style":7730},[12273],{"type":35,"value":5188},{"type":29,"tag":901,"props":12275,"children":12276},{"class":903,"line":6029},[12277,12281,12285,12289,12294],{"type":29,"tag":901,"props":12278,"children":12279},{"style":5185},[12280],{"type":35,"value":12109},{"type":29,"tag":901,"props":12282,"children":12283},{"style":12053},[12284],{"type":35,"value":12114},{"type":29,"tag":901,"props":12286,"children":12287},{"style":7730},[12288],{"type":35,"value":5760},{"type":29,"tag":901,"props":12290,"children":12291},{"style":2236},[12292],{"type":35,"value":12293}," npm run test:integration",{"type":29,"tag":901,"props":12295,"children":12296},{"style":908},[12297],{"type":35,"value":12298},"    # \u003C 10 min\n",{"type":29,"tag":176,"props":12300,"children":12302},{"cta":178,"href":179,"title":12301,"type":181},"Votre pipeline CI dépasse les 15 minutes et les développeurs ont arrêté de le surveiller ?",[12303],{"type":29,"tag":37,"props":12304,"children":12305},{},[12306],{"type":35,"value":12307},"Un pipeline qui dérive vers 20-30 minutes nécessite un audit de la structure des tests et des stages. En 30 minutes, j'identifie les goulots d'étranglement et je vous donne une stratégie de réduction à moins de 10 minutes, applicable dès le sprint suivant.",{"type":29,"tag":76,"props":12309,"children":12310},{},[],{"type":29,"tag":80,"props":12312,"children":12314},{"id":12313},"fondamental-3-les-tests-cassés-sont-la-priorité-absolue",[12315],{"type":35,"value":12316},"Fondamental 3 : Les tests cassés sont la priorité absolue",{"type":29,"tag":37,"props":12318,"children":12319},{},[12320],{"type":35,"value":12321},"Quand le pipeline est rouge, réparer le trunk est la priorité numéro un de toute l'équipe, avant les nouvelles features, avant les code reviews en attente, avant les réunions.",{"type":29,"tag":37,"props":12323,"children":12324},{},[12325],{"type":35,"value":12326},"Cette règle s'appelle le \"stop the line\", empruntée au Toyota Production System (Jidoka). Dans le TPS, quand un problème est détecté sur la ligne de production, la ligne s'arrête jusqu'à ce que le problème soit résolu. En CI, le trunk cassé est la ligne arrêtée.",{"type":29,"tag":37,"props":12328,"children":12329},{},[12330],{"type":35,"value":12331},"En pratique : pipeline rouge → alerte immédiate à toute l'équipe via Slack et dashboard. La personne qui a cassé le trunk a 10 minutes pour proposer un fix ou reverter. Si pas de fix en 10 minutes : revert automatique ou manuel. Pas de nouveaux commits sur trunk tant qu'il est rouge.",{"type":29,"tag":37,"props":12333,"children":12334},{},[12335],{"type":35,"value":12336},"Ce qui arrive sans cette règle : les builds cassés s'accumulent, les développeurs ignorent les alertes, et le pipeline devient du décor plutôt qu'un signal utile. J'ai vu des équipes avec un pipeline rouge depuis 3 semaines : tout le monde avait arrêté de regarder.",{"type":29,"tag":76,"props":12338,"children":12339},{},[],{"type":29,"tag":80,"props":12341,"children":12343},{"id":12342},"fondamental-4-tout-le-monde-voit-létat-du-pipeline",[12344],{"type":35,"value":12345},"Fondamental 4 : Tout le monde voit l'état du pipeline",{"type":29,"tag":37,"props":12347,"children":12348},{},[12349],{"type":35,"value":12350},"L'état du pipeline doit être visible passivement par toute l'équipe, pas seulement quand quelqu'un pense à aller le vérifier.",{"type":29,"tag":37,"props":12352,"children":12353},{},[12354],{"type":35,"value":12355},"Les mécanismes de visibilité : dashboard de build sur un écran visible dans l'espace de travail, notification Slack dans le canal de l'équipe (pas seulement à la personne qui a pushé), badge de statut sur le README du repo, statut visible dans l'IDE.",{"type":29,"tag":37,"props":12357,"children":12358},{},[12359],{"type":35,"value":12360},"La différence entre \"notification opt-in\" et \"visibilité passive\" est fondamentale : si le développeur doit aller chercher l'information, il ne le fera pas systématiquement. La visibilité passive crée une conscience collective de l'état de la CI sans effort individuel.",{"type":29,"tag":76,"props":12362,"children":12363},{},[],{"type":29,"tag":80,"props":12365,"children":12367},{"id":12366},"fondamental-5-les-tests-sont-la-définition-de-trunk-en-bonne-santé",[12368],{"type":35,"value":12369},"Fondamental 5 : Les tests sont la définition de \"trunk en bonne santé\"",{"type":29,"tag":37,"props":12371,"children":12372},{},[12373,12375,12379],{"type":35,"value":12374},"Les tests automatisés définissent ce que \"trunk en bonne santé\" signifie : intégrez ce critère dans votre ",{"type":29,"tag":48,"props":12376,"children":12377},{"href":4950},[12378],{"type":35,"value":11631},{"type":35,"value":12380},". Si un comportement n'est pas testé, la CI ne peut pas le protéger.",{"type":29,"tag":37,"props":12382,"children":12383},{},[12384],{"type":35,"value":12385},"La pyramide de tests en CI définit la structure optimale :",{"type":29,"tag":1080,"props":12387,"children":12388},{},[12389,12399,12412],{"type":29,"tag":1084,"props":12390,"children":12391},{},[12392,12397],{"type":29,"tag":65,"props":12393,"children":12394},{},[12395],{"type":35,"value":12396},"Tests unitaires",{"type":35,"value":12398}," (70-80% des tests) : rapides, sans dépendances externes. Feedback en moins de 2 minutes.",{"type":29,"tag":1084,"props":12400,"children":12401},{},[12402,12410],{"type":29,"tag":65,"props":12403,"children":12404},{},[12405],{"type":29,"tag":48,"props":12406,"children":12407},{"href":9765},[12408],{"type":35,"value":12409},"Tests d'intégration",{"type":35,"value":12411}," (15-20% des tests) : avec base de données ou services externes. Feedback en moins de 8 minutes.",{"type":29,"tag":1084,"props":12413,"children":12414},{},[12415,12420],{"type":29,"tag":65,"props":12416,"children":12417},{},[12418],{"type":35,"value":12419},"Tests end-to-end",{"type":35,"value":12421}," (5-10% des tests) : sur les flux critiques uniquement. Déclenchés moins fréquemment.",{"type":29,"tag":37,"props":12423,"children":12424},{},[12425],{"type":35,"value":12426},"Un pipeline vert ne garantit pas que le logiciel est correct : il garantit qu'il est cohérent avec ses tests. La qualité des tests détermine la qualité du signal.",{"type":29,"tag":76,"props":12428,"children":12429},{},[],{"type":29,"tag":80,"props":12431,"children":12433},{"id":12432},"ce-que-ça-change-concrètement",[12434],{"type":35,"value":12435},"Ce que ça change concrètement",{"type":29,"tag":37,"props":12437,"children":12438},{},[12439],{"type":35,"value":12440},"Dans l'équipe mentionnée en introduction, après 6 semaines de travail sur les 5 fondamentaux (parallélisation des tests, feature flags systématiques, règle du stop the line, dashboard visible, refonte de la pyramide de tests), le résultat était mesurable. Le pipeline est passé de 28 minutes à 8 minutes. La durée des branches est passée de 4 jours à 18 heures. Le lead time de delivery a baissé de 40%.",{"type":29,"tag":37,"props":12442,"children":12443},{},[12444],{"type":35,"value":12445},"Aucun recrutement. Aucun changement de framework. Seulement des pratiques humaines appliquées avec discipline.",{"type":29,"tag":37,"props":12447,"children":12448},{},[12449,12451,12457],{"type":35,"value":12450},"Les métriques de maturité CI à suivre (ces indicateurs font partie des ",{"type":29,"tag":48,"props":12452,"children":12454},{"href":12453},"/fr/management/metriques-management-developpeurs-motivation",[12455],{"type":35,"value":12456},"4 métriques DORA",{"type":35,"value":12458},") : fréquence d'intégration par développeur (cible : plus de 2 fois par jour), MTTR du pipeline en cas de rupture (cible : moins de 30 minutes), durée du pipeline en p95 (cible : moins de 10 minutes), taux de flakiness des tests (cible : moins de 5%).",{"type":29,"tag":76,"props":12460,"children":12461},{},[],{"type":29,"tag":80,"props":12463,"children":12465},{"id":12464},"faq-sur-la-continuous-integration",[12466],{"type":35,"value":12467},"FAQ sur la Continuous Integration",{"type":29,"tag":381,"props":12469,"children":12470},{},[12471,12476],{"type":29,"tag":385,"props":12472,"children":12473},{},[12474],{"type":35,"value":12475},"1. Quelle est la différence entre CI et CD (Continuous Delivery / Deployment) ?",{"type":29,"tag":37,"props":12477,"children":12478},{},[12479],{"type":35,"value":12480},"La CI est l'intégration fréquente du code dans le trunk avec vérification automatique. La CD (Delivery) est la capacité à déployer n'importe quel commit en production de façon fiable à tout moment. La CD (Deployment) est le déploiement automatique de chaque commit qui passe la CI. La CI est un prérequis à la CD. On peut pratiquer la CI sans CD, mais pas l'inverse de façon viable.",{"type":29,"tag":381,"props":12482,"children":12483},{},[12484,12489],{"type":29,"tag":385,"props":12485,"children":12486},{},[12487],{"type":35,"value":12488},"2. Comment convaincre une équipe de passer des feature branches longues aux intégrations quotidiennes ?",{"type":29,"tag":37,"props":12490,"children":12491},{},[12492],{"type":35,"value":12493},"Par la data. Calculer le temps moyen passé à résoudre les conflits de merge sur les 3 derniers mois. Dans la plupart des équipes avec des branches de 1-2 semaines, les merge conflicts représentent 10 à 15% du temps de développement. Proposer un pilote de 4 sprints avec des branches courtes et feature flags, et mesurer. Le résultat parle de lui-même.",{"type":29,"tag":381,"props":12495,"children":12496},{},[12497,12502],{"type":29,"tag":385,"props":12498,"children":12499},{},[12500],{"type":35,"value":12501},"3. Les feature flags créent-ils une dette technique ?",{"type":29,"tag":37,"props":12503,"children":12504},{},[12505],{"type":35,"value":12506},"Oui, si mal gérés. Un feature flag non supprimé après le lancement de la feature est de la dette. La règle : chaque feature flag a une date d'expiration définie au moment de sa création. Un linter ou un test automatique vérifie que les flags expirés sont supprimés. En pratique, un backlog dédié à la suppression des flags (2 à 3 par sprint) suffit pour maintenir le stock sous contrôle.",{"type":29,"tag":381,"props":12508,"children":12509},{},[12510,12515],{"type":29,"tag":385,"props":12511,"children":12512},{},[12513],{"type":35,"value":12514},"4. Comment gérer la CI dans un monorepo avec de nombreux services ?",{"type":29,"tag":37,"props":12516,"children":12517},{},[12518],{"type":35,"value":12519},"Avec des pipelines sélectifs basés sur les changements. Les outils comme Nx pour JavaScript/TypeScript, Bazel pour les environnements multi-langages, ou les \"path filters\" dans GitHub Actions permettent de ne lancer que les tests des services impactés par les changements. Cela maintient un pipeline sous 10 minutes même dans un monorepo de 20 services.",{"type":29,"tag":381,"props":12521,"children":12522},{},[12523,12528],{"type":29,"tag":385,"props":12524,"children":12525},{},[12526],{"type":35,"value":12527},"5. Que faire quand les tests sont trop lents pour permettre une intégration quotidienne ?",{"type":29,"tag":37,"props":12529,"children":12530},{},[12531],{"type":35,"value":12532},"C'est le signal pour revoir la pyramide de tests. Audit en 3 étapes : identifier les 20% de tests les plus lents qui représentent 80% du temps, évaluer si ces tests d'intégration pourraient être remplacés par des tests unitaires avec mocks, puis déplacer les tests lents dans un stage séparé déclenché toutes les 2 heures. Le pipeline fast feedback reste sous 10 minutes, le reste se vérifie en continu.",{"type":29,"tag":76,"props":12534,"children":12535},{},[],{"type":29,"tag":176,"props":12537,"children":12538},{"cta":4551,"href":453,"title":4552,"type":455},[12539],{"type":29,"tag":37,"props":12540,"children":12541},{},[12542],{"type":35,"value":12543},"Le guide complet pour réduire votre lead time en 90 jours inclut un chapitre sur l'optimisation du pipeline CI/CD et les pratiques d'intégration qui font la différence sur la fréquence de delivery, avec les métriques DORA à suivre.",{"type":29,"tag":1252,"props":12545,"children":12546},{},[12547],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":12549},[12550,12551,12552,12553,12554,12555,12556,12557],{"id":11815,"depth":463,"text":11818},{"id":11864,"depth":463,"text":11867},{"id":12012,"depth":463,"text":12015},{"id":12313,"depth":463,"text":12316},{"id":12342,"depth":463,"text":12345},{"id":12366,"depth":463,"text":12369},{"id":12432,"depth":463,"text":12435},{"id":12464,"depth":463,"text":12467},"content:fr:pratiques-agiles:continuous-integration-fondamentaux.md","fr/pratiques-agiles/continuous-integration-fondamentaux.md","fr/pratiques-agiles/continuous-integration-fondamentaux",{"_path":4950,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":12562,"description":12563,"id":6275,"date":12564,"listed":13,"nocomments":7,"hidden":7,"categories":12565,"tags":12566,"--cover":12568,"readingTime":12569,"body":12573,"_type":476,"_id":13180,"_source":478,"_file":13181,"_stem":13182,"_extension":481},"Définir une Definition of Done qui améliore vraiment la qualité","Une DoD vague produit une qualité vague. Comment construire une Definition of Done qui tient ses promesses et s'améliore dans le temps.","2026-03-04",[6],[11631,2128,12567],"Agile","covers/articles/definition-of-done-qualite.jpg",{"text":497,"minutes":12570,"time":12571,"words":12572},7.46,447600,1492,{"type":26,"children":12574,"toc":13170},[12575,12580,12585,12593,12598,12601,12607,12625,12628,12634,12651,12656,12665,12683,12688,12698,12701,12707,12722,12727,12737,12747,12764,12774,12784,12794,12804,12813,12816,12825,12828,12834,12839,12849,12859,12869,12879,12888,12891,12897,12902,12912,12930,12942,12951,12954,12960,12969,12972,12978,13077,13080,13086,13099,13112,13133,13146,13159,13162],{"type":29,"tag":30,"props":12576,"children":12578},{"id":12577},"définir-une-definition-of-done-qui-améliore-vraiment-la-qualité",[12579],{"type":35,"value":12562},{"type":29,"tag":37,"props":12581,"children":12582},{},[12583],{"type":35,"value":12584},"Je me souviens d'une équipe dans une grande organisation de retraite complémentaire. Ils avaient une DoD, une vraie, écrite, affichée dans la salle. Je leur ai demandé comment elle était utilisée. Le Scrum Master a répondu avec un sourire gêné : \"En théorie, elle est vérifiée avant chaque merge. En pratique, en fin de sprint, on coche tout et on merge pour tenir le sprint.\" J'ai vérifié les métriques : 38% des bugs de prod de l'année précédente étaient apparus dans des stories \"Done\" selon la DoD de l'équipe. Ce n'était pas un problème de personnes. C'était un problème de contrat.",{"type":29,"tag":37,"props":12586,"children":12587},{},[12588],{"type":29,"tag":65,"props":12589,"children":12590},{},[12591],{"type":35,"value":12592},"La DoD la plus fréquente que je rencontre dans les équipes : \"Le code est mergé et testé.\" C'est une description, pas une Definition of Done. Et cette ambiguïté est directement responsable de 30 à 40% des bugs qui atteignent la production.",{"type":29,"tag":37,"props":12594,"children":12595},{},[12596],{"type":35,"value":12597},"La Definition of Done est le contrat de qualité de l'équipe. Quand elle est vague, chaque développeur l'interprète différemment. Quand elle est absente, la qualité dépend de la conscience professionnelle individuelle, ce qui est insuffisant pour garantir la cohérence.",{"type":29,"tag":76,"props":12599,"children":12600},{},[],{"type":29,"tag":80,"props":12602,"children":12604},{"id":12603},"avant-de-commencer-les-prérequis",[12605],{"type":35,"value":12606},"Avant de commencer : les prérequis",{"type":29,"tag":1080,"props":12608,"children":12609},{},[12610,12615,12620],{"type":29,"tag":1084,"props":12611,"children":12612},{},[12613],{"type":35,"value":12614},"L'équipe a déjà une DoD existante (même minimale ou informelle) à partir de laquelle progresser",{"type":29,"tag":1084,"props":12616,"children":12617},{},[12618],{"type":35,"value":12619},"Le Product Owner et le Tech Lead sont impliqués dans la redéfinition",{"type":29,"tag":1084,"props":12621,"children":12622},{},[12623],{"type":35,"value":12624},"L'équipe a accès aux métriques de base : taux de bugs de prod, lead time, incidents récents",{"type":29,"tag":76,"props":12626,"children":12627},{},[],{"type":29,"tag":80,"props":12629,"children":12631},{"id":12630},"étape-1-auditer-la-dod-actuelle-ou-son-absence",[12632],{"type":35,"value":12633},"Étape 1 : Auditer la DoD actuelle (ou son absence)",{"type":29,"tag":37,"props":12635,"children":12636},{},[12637,12642,12644,12649],{"type":29,"tag":65,"props":12638,"children":12639},{},[12640],{"type":35,"value":12641},"Durée estimée",{"type":35,"value":12643}," : 2 heures en atelier équipe\n",{"type":29,"tag":65,"props":12645,"children":12646},{},[12647],{"type":35,"value":12648},"Qui",{"type":35,"value":12650}," : Toute l'équipe de développement + PO + Scrum Master",{"type":29,"tag":37,"props":12652,"children":12653},{},[12654],{"type":35,"value":12655},"Avant de construire une nouvelle DoD, comprendre pourquoi l'actuelle ne fonctionne pas.",{"type":29,"tag":37,"props":12657,"children":12658},{},[12659,12664],{"type":29,"tag":65,"props":12660,"children":12661},{},[12662],{"type":35,"value":12663},"Questions à poser en atelier",{"type":35,"value":11585},{"type":29,"tag":1080,"props":12666,"children":12667},{},[12668,12673,12678],{"type":29,"tag":1084,"props":12669,"children":12670},{},[12671],{"type":35,"value":12672},"\"Quand considérez-vous qu'une story est vraiment terminée ?\" Recueillir les réponses individuelles avant la discussion.",{"type":29,"tag":1084,"props":12674,"children":12675},{},[12676],{"type":35,"value":12677},"\"Citez un bug récent de prod : quelle étape de la DoD aurait dû le détecter ?\"",{"type":29,"tag":1084,"props":12679,"children":12680},{},[12681],{"type":35,"value":12682},"\"Y a-t-il des items de notre DoD actuelle que personne ne vérifie vraiment ?\"",{"type":29,"tag":37,"props":12684,"children":12685},{},[12686],{"type":35,"value":12687},"Le dernier exercice est le plus révélateur. Dans 80% des équipes que j'accompagne, il existe des items \"fantômes\" dans la DoD : des critères formellement présents mais systématiquement contournés, généralement par manque de temps en fin de sprint.",{"type":29,"tag":37,"props":12689,"children":12690},{},[12691,12696],{"type":29,"tag":65,"props":12692,"children":12693},{},[12694],{"type":35,"value":12695},"Résultat attendu",{"type":35,"value":12697}," : une liste de ce qui fonctionne, ce qui est contourné, et ce qui manque.",{"type":29,"tag":76,"props":12699,"children":12700},{},[],{"type":29,"tag":80,"props":12702,"children":12704},{"id":12703},"étape-2-les-7-critères-non-négociables-dune-dod-solide",[12705],{"type":35,"value":12706},"Étape 2 : Les 7 critères non-négociables d'une DoD solide",{"type":29,"tag":37,"props":12708,"children":12709},{},[12710,12714,12716,12720],{"type":29,"tag":65,"props":12711,"children":12712},{},[12713],{"type":35,"value":12641},{"type":35,"value":12715}," : 1 heure de discussion\n",{"type":29,"tag":65,"props":12717,"children":12718},{},[12719],{"type":35,"value":12648},{"type":35,"value":12721}," : Tech Lead + PO",{"type":29,"tag":37,"props":12723,"children":12724},{},[12725],{"type":35,"value":12726},"Ces 7 critères sont le minimum pour une DoD qui protège réellement la qualité. Adaptez le wording à votre contexte, mais ne supprimez pas les catégories.",{"type":29,"tag":37,"props":12728,"children":12729},{},[12730,12735],{"type":29,"tag":65,"props":12731,"children":12732},{},[12733],{"type":35,"value":12734},"1. Code reviewé par au moins un pair",{"type":35,"value":12736},"\nPas \"par le Tech Lead si disponible\". Par n'importe quel pair, avec un retour documenté dans la PR. Spécifier le délai maximum : aucune PR ne reste sans review plus de 24 heures ouvrées.",{"type":29,"tag":37,"props":12738,"children":12739},{},[12740,12745],{"type":29,"tag":65,"props":12741,"children":12742},{},[12743],{"type":35,"value":12744},"2. Tests automatisés écrits ou mis à jour",{"type":35,"value":12746},"\nSpécifier le type : tests unitaires pour la logique, tests d'intégration pour les interactions avec les dépendances. Spécifier le seuil : la couverture du module ne descend pas en dessous du seuil de l'équipe.",{"type":29,"tag":37,"props":12748,"children":12749},{},[12750,12762],{"type":29,"tag":65,"props":12751,"children":12752},{},[12753,12755,12760],{"type":35,"value":12754},"3. ",{"type":29,"tag":48,"props":12756,"children":12757},{"href":11764},[12758],{"type":35,"value":12759},"Build CI",{"type":35,"value":12761}," vert sur la branche",{"type":35,"value":12763},"\nÉvident mais souvent contourné \"pour gagner du temps\". Un build rouge = story non terminée, sans exception.",{"type":29,"tag":37,"props":12765,"children":12766},{},[12767,12772],{"type":29,"tag":65,"props":12768,"children":12769},{},[12770],{"type":35,"value":12771},"4. Critères d'acceptation vérifiés et documentés",{"type":35,"value":12773},"\nChaque critère d'acceptation de la story doit avoir été testé manuellement ou automatiquement. Le résultat est documenté dans le ticket.",{"type":29,"tag":37,"props":12775,"children":12776},{},[12777,12782],{"type":29,"tag":65,"props":12778,"children":12779},{},[12780],{"type":35,"value":12781},"5. Pas de régression identifiée sur les scénarios existants",{"type":35,"value":12783},"\nUne suite de tests de régression tourne sur chaque PR. Si elle n'existe pas, c'est un déficit à combler progressivement, mais c'est un objectif de la DoD.",{"type":29,"tag":37,"props":12785,"children":12786},{},[12787,12792],{"type":29,"tag":65,"props":12788,"children":12789},{},[12790],{"type":35,"value":12791},"6. Documentation mise à jour si applicable",{"type":35,"value":12793},"\nPas de documentation pour chaque story. Mais si la story modifie une API publique, un flux d'intégration, ou une règle métier documentée, la documentation est mise à jour dans la même PR.",{"type":29,"tag":37,"props":12795,"children":12796},{},[12797,12802],{"type":29,"tag":65,"props":12798,"children":12799},{},[12800],{"type":35,"value":12801},"7. Déployable en environnement de staging sans intervention manuelle",{"type":35,"value":12803},"\nLa story doit pouvoir être déployée en staging en appuyant sur un bouton. Si un déploiement nécessite des étapes manuelles, c'est une dette technique à documenter et traiter.",{"type":29,"tag":37,"props":12805,"children":12806},{},[12807,12811],{"type":29,"tag":65,"props":12808,"children":12809},{},[12810],{"type":35,"value":12695},{"type":35,"value":12812}," : une DoD de 7 items précis et actionnables.",{"type":29,"tag":76,"props":12814,"children":12815},{},[],{"type":29,"tag":176,"props":12817,"children":12819},{"cta":178,"href":179,"title":12818,"type":181},"Votre équipe merge du code que tout le monde sait incomplet faute d'une DoD claire ?",[12820],{"type":29,"tag":37,"props":12821,"children":12822},{},[12823],{"type":35,"value":12824},"Vous voyez les patterns se répéter : les bugs arrivent en prod sur des stories \"Done\", les revues de code sont expéditives en fin de sprint, et personne n'ose vraiment bloquer un merge. Ce n'est pas de la mauvaise volonté, c'est l'absence d'un contrat clair. En 30 minutes, on identifie la vraie cause et on définit une DoD réaliste et tenue.",{"type":29,"tag":76,"props":12826,"children":12827},{},[],{"type":29,"tag":80,"props":12829,"children":12831},{"id":12830},"étape-3-lintégrer-dans-le-workflow-sans-friction",[12832],{"type":35,"value":12833},"Étape 3 : L'intégrer dans le workflow sans friction",{"type":29,"tag":37,"props":12835,"children":12836},{},[12837],{"type":35,"value":12838},"Une DoD que personne ne consulte n'existe pas. Elle doit être au bon endroit, au bon moment.",{"type":29,"tag":37,"props":12840,"children":12841},{},[12842,12847],{"type":29,"tag":65,"props":12843,"children":12844},{},[12845],{"type":35,"value":12846},"Dans Jira/Linear",{"type":35,"value":12848}," : ajouter la DoD comme checklist dans le template de story. Chaque item est coché (et non supprimé) avant de passer au statut \"Done\". L'outil garde une trace.",{"type":29,"tag":37,"props":12850,"children":12851},{},[12852,12857],{"type":29,"tag":65,"props":12853,"children":12854},{},[12855],{"type":35,"value":12856},"Dans GitHub/GitLab",{"type":35,"value":12858}," : créer un template de PR avec les items de la DoD comme checklist. Le développeur les coche au moment de la PR, pas après coup.",{"type":29,"tag":37,"props":12860,"children":12861},{},[12862,12867],{"type":29,"tag":65,"props":12863,"children":12864},{},[12865],{"type":35,"value":12866},"Dans le sprint review",{"type":35,"value":12868}," : le PO valide que les items de la DoD ont été respectés avant d'accepter la story. C'est le moment de fermeture du cycle qualité.",{"type":29,"tag":37,"props":12870,"children":12871},{},[12872,12877],{"type":29,"tag":65,"props":12873,"children":12874},{},[12875],{"type":35,"value":12876},"L'erreur à éviter",{"type":35,"value":12878}," : transformer la DoD en checklist bureaucratique que tout le monde coche sans vérifier. Pour éviter ça, j'inclus des items vérifiables de façon objective (build vert, coverage seuil) plutôt que subjectifs (\"le code est de qualité\").",{"type":29,"tag":37,"props":12880,"children":12881},{},[12882,12886],{"type":29,"tag":65,"props":12883,"children":12884},{},[12885],{"type":35,"value":12695},{"type":35,"value":12887}," : la DoD est intégrée dans les templates Jira et GitHub. Elle est visible au bon moment dans le workflow.",{"type":29,"tag":76,"props":12889,"children":12890},{},[],{"type":29,"tag":80,"props":12892,"children":12894},{"id":12893},"étape-4-la-faire-évoluer-chaque-trimestre",[12895],{"type":35,"value":12896},"Étape 4 : La faire évoluer chaque trimestre",{"type":29,"tag":37,"props":12898,"children":12899},{},[12900],{"type":35,"value":12901},"Une DoD figée devient rapidement soit trop laxiste (l'équipe a progressé et la DoD ne reflète plus ses standards actuels) soit trop contraignante (les outils ont changé et certains items ne s'appliquent plus).",{"type":29,"tag":37,"props":12903,"children":12904},{},[12905,12910],{"type":29,"tag":65,"props":12906,"children":12907},{},[12908],{"type":35,"value":12909},"Rituel recommandé",{"type":35,"value":12911}," : une session de 1 heure par trimestre, en même temps que le trimestrial planning, pour réviser la DoD :",{"type":29,"tag":1080,"props":12913,"children":12914},{},[12915,12920,12925],{"type":29,"tag":1084,"props":12916,"children":12917},{},[12918],{"type":35,"value":12919},"Quels items sont systématiquement respectés ? (→ potentiellement automatisables dans la CI)",{"type":29,"tag":1084,"props":12921,"children":12922},{},[12923],{"type":35,"value":12924},"Quels items sont régulièrement contournés ? (→ soit les supprimer, soit identifier pourquoi et lever le blocage)",{"type":29,"tag":1084,"props":12926,"children":12927},{},[12928],{"type":35,"value":12929},"Quels items manquent compte tenu des problèmes rencontrés ce trimestre ?",{"type":29,"tag":37,"props":12931,"children":12932},{},[12933,12935,12940],{"type":35,"value":12934},"L'objectif à 12-18 mois : une DoD qui contient des items d'un ",{"type":29,"tag":48,"props":12936,"children":12937},{"href":166},[12938],{"type":35,"value":12939},"niveau 3 de maturité engineering",{"type":35,"value":12941}," : les standards de qualité sont ancrés dans les pratiques de l'équipe, pas seulement dans un document.",{"type":29,"tag":37,"props":12943,"children":12944},{},[12945,12949],{"type":29,"tag":65,"props":12946,"children":12947},{},[12948],{"type":35,"value":12695},{"type":35,"value":12950}," : une DoD vivante, révisée trimestriellement, qui progresse avec le niveau de maturité de l'équipe.",{"type":29,"tag":76,"props":12952,"children":12953},{},[],{"type":29,"tag":80,"props":12955,"children":12957},{"id":12956},"le-piège-à-éviter",[12958],{"type":35,"value":12959},"Le piège à éviter",{"type":29,"tag":12961,"props":12962,"children":12963},"blockquote",{},[12964],{"type":29,"tag":37,"props":12965,"children":12966},{},[12967],{"type":35,"value":12968},"Ne jamais créer deux niveaux de DoD \"selon le temps disponible\". J'ai vu des équipes définir une \"DoD normale\" et une \"DoD express\" pour les sprints surchargés. Résultat : la DoD express devient la norme, et la DoD normale n'est jamais appliquée. Une seule DoD : si elle n'est pas atteignable, réduire le scope du sprint, pas les standards. C'est la discipline fondamentale d'un système agile sain.",{"type":29,"tag":76,"props":12970,"children":12971},{},[],{"type":29,"tag":80,"props":12973,"children":12975},{"id":12974},"en-résumé",[12976],{"type":35,"value":12977},"En résumé",{"type":29,"tag":714,"props":12979,"children":12980},{},[12981,13002],{"type":29,"tag":718,"props":12982,"children":12983},{},[12984],{"type":29,"tag":722,"props":12985,"children":12986},{},[12987,12992,12997],{"type":29,"tag":726,"props":12988,"children":12989},{},[12990],{"type":35,"value":12991},"Étape",{"type":29,"tag":726,"props":12993,"children":12994},{},[12995],{"type":35,"value":12996},"Action",{"type":29,"tag":726,"props":12998,"children":12999},{},[13000],{"type":35,"value":13001},"Résultat",{"type":29,"tag":742,"props":13003,"children":13004},{},[13005,13023,13041,13059],{"type":29,"tag":722,"props":13006,"children":13007},{},[13008,13013,13018],{"type":29,"tag":749,"props":13009,"children":13010},{},[13011],{"type":35,"value":13012},"1",{"type":29,"tag":749,"props":13014,"children":13015},{},[13016],{"type":35,"value":13017},"Auditer la DoD actuelle en atelier",{"type":29,"tag":749,"props":13019,"children":13020},{},[13021],{"type":35,"value":13022},"Identifier les items fantômes et les manques",{"type":29,"tag":722,"props":13024,"children":13025},{},[13026,13031,13036],{"type":29,"tag":749,"props":13027,"children":13028},{},[13029],{"type":35,"value":13030},"2",{"type":29,"tag":749,"props":13032,"children":13033},{},[13034],{"type":35,"value":13035},"Définir les 7 critères non-négociables",{"type":29,"tag":749,"props":13037,"children":13038},{},[13039],{"type":35,"value":13040},"DoD précise et actionnable",{"type":29,"tag":722,"props":13042,"children":13043},{},[13044,13049,13054],{"type":29,"tag":749,"props":13045,"children":13046},{},[13047],{"type":35,"value":13048},"3",{"type":29,"tag":749,"props":13050,"children":13051},{},[13052],{"type":35,"value":13053},"Intégrer dans Jira et GitHub",{"type":29,"tag":749,"props":13055,"children":13056},{},[13057],{"type":35,"value":13058},"DoD consultée au bon moment dans le workflow",{"type":29,"tag":722,"props":13060,"children":13061},{},[13062,13067,13072],{"type":29,"tag":749,"props":13063,"children":13064},{},[13065],{"type":35,"value":13066},"4",{"type":29,"tag":749,"props":13068,"children":13069},{},[13070],{"type":35,"value":13071},"Réviser chaque trimestre",{"type":29,"tag":749,"props":13073,"children":13074},{},[13075],{"type":35,"value":13076},"DoD qui progresse avec la maturité de l'équipe",{"type":29,"tag":76,"props":13078,"children":13079},{},[],{"type":29,"tag":80,"props":13081,"children":13083},{"id":13082},"faq-sur-la-definition-of-done",[13084],{"type":35,"value":13085},"FAQ sur la Definition of Done",{"type":29,"tag":381,"props":13087,"children":13088},{},[13089,13094],{"type":29,"tag":385,"props":13090,"children":13091},{},[13092],{"type":35,"value":13093},"1. Quelle est la différence entre la DoD et les critères d'acceptation ?",{"type":29,"tag":37,"props":13095,"children":13096},{},[13097],{"type":35,"value":13098},"Les critères d'acceptation sont spécifiques à une story : ils décrivent ce que cette story particulière doit faire. La DoD est transversale à toutes les stories : elle décrit les standards de qualité qui s'appliquent à toute livraison, quelles que soient les fonctionnalités. Une story peut respecter tous ses critères d'acceptation et ne pas respecter la DoD (ex : pas de tests écrits, code non reviewé).",{"type":29,"tag":381,"props":13100,"children":13101},{},[13102,13107],{"type":29,"tag":385,"props":13103,"children":13104},{},[13105],{"type":35,"value":13106},"2. La DoD doit-elle être la même pour tous les types de stories ?",{"type":29,"tag":37,"props":13108,"children":13109},{},[13110],{"type":35,"value":13111},"Généralement oui, avec des nuances légères. Certains items peuvent être contextuels (la documentation n'est pas mise à jour pour une story de refactoring interne). Mais les items fondamentaux (code reviewé, build vert, tests écrits) s'appliquent à toutes les stories sans exception. Trop d'exceptions crée de l'ambiguïté et ouvre la porte aux contournements.",{"type":29,"tag":381,"props":13113,"children":13114},{},[13115,13120],{"type":29,"tag":385,"props":13116,"children":13117},{},[13118],{"type":35,"value":13119},"3. Comment gérer la résistance de l'équipe à une DoD plus stricte ?",{"type":29,"tag":37,"props":13121,"children":13122},{},[13123,13125,13131],{"type":35,"value":13124},"La résistance vient généralement de la peur que la DoD crée un blocage en fin de sprint. La réponse est de traiter la cause : si la DoD ne peut pas être respectée dans un sprint, le problème est en amont (stories trop grandes, ",{"type":29,"tag":48,"props":13126,"children":13128},{"href":13127},"/fr/pratiques-agiles/definition-of-ready-bugs-sprint",[13129],{"type":35,"value":13130},"Definition of Ready absente",{"type":35,"value":13132},", capacité surestimée) pas dans la DoD elle-même. Impliquer l'équipe dans la rédaction de la DoD réduit significativement la résistance à son application.",{"type":29,"tag":381,"props":13134,"children":13135},{},[13136,13141],{"type":29,"tag":385,"props":13137,"children":13138},{},[13139],{"type":35,"value":13140},"4. Faut-il une DoD différente par équipe dans une organisation avec plusieurs équipes ?",{"type":29,"tag":37,"props":13142,"children":13143},{},[13144],{"type":35,"value":13145},"Une base commune + des extensions par équipe est la meilleure approche. La base commune garantit un niveau minimum de qualité cohérent à travers l'organisation, particulièrement important pour les composants partagés. Les extensions permettent aux équipes d'adapter aux spécificités de leur contexte (ex : une équipe data peut avoir des items spécifiques sur la validation des schémas).",{"type":29,"tag":381,"props":13147,"children":13148},{},[13149,13154],{"type":29,"tag":385,"props":13150,"children":13151},{},[13152],{"type":35,"value":13153},"5. Comment mesurer si la DoD améliore réellement la qualité ?",{"type":29,"tag":37,"props":13155,"children":13156},{},[13157],{"type":35,"value":13158},"Trois métriques à suivre avant/après l'amélioration de la DoD : le taux de bugs de prod sur les stories \"Done\" (doit baisser), le nombre de réouvertures de tickets (doit baisser), et le temps passé en correction de bugs vs développement de features (doit s'améliorer). Sur les équipes que j'accompagne, une DoD bien appliquée réduit le taux de bugs de prod de 25 à 40% en 3 mois.",{"type":29,"tag":76,"props":13160,"children":13161},{},[],{"type":29,"tag":176,"props":13163,"children":13164},{"cta":452,"href":453,"title":454,"type":455},[13165],{"type":29,"tag":37,"props":13166,"children":13167},{},[13168],{"type":35,"value":13169},"L'assessment évalue vos pratiques de qualité, incluant la Definition of Done, les pratiques de tests et de revue de code. Identifiez votre niveau actuel et les 3 actions prioritaires pour progresser.",{"title":8,"searchDepth":463,"depth":463,"links":13171},[13172,13173,13174,13175,13176,13177,13178,13179],{"id":12603,"depth":463,"text":12606},{"id":12630,"depth":463,"text":12633},{"id":12703,"depth":463,"text":12706},{"id":12830,"depth":463,"text":12833},{"id":12893,"depth":463,"text":12896},{"id":12956,"depth":463,"text":12959},{"id":12974,"depth":463,"text":12977},{"id":13082,"depth":463,"text":13085},"content:fr:dette-technique:definition-of-done-qualite.md","fr/dette-technique/definition-of-done-qualite.md","fr/dette-technique/definition-of-done-qualite",{"_path":666,"_dir":484,"_draft":7,"_partial":7,"_locale":8,"title":13184,"description":13185,"id":6250,"date":13186,"listed":13,"nocomments":7,"hidden":7,"categories":13187,"tags":13188,"--cover":13192,"readingTime":13193,"body":13198,"_type":476,"_id":14769,"_source":478,"_file":14770,"_stem":14771,"_extension":481},"Patterns de résilience : circuit breaker, retry, timeout","Les 3 patterns de résilience fondamentaux que tout système distribué doit implémenter. Sans eux, la défaillance d'un service cascade et fait tomber toute l'architecture.","2026-03-02",[484],[13189,13190,13191,493],"Résilience","Circuit Breaker","Retry","covers/articles/patterns-resilience-circuit-breaker.jpg",{"text":13194,"minutes":13195,"time":13196,"words":13197},"7 min read",6.985,419100,1397,{"type":26,"children":13199,"toc":14760},[13200,13205,13210,13215,13220,13225,13228,13234,13245,13250,13262,13265,13271,13276,13286,13294,13312,13522,13532,13535,13541,13546,13556,13913,13921,13934,13943,13946,13952,13957,13965,13975,13985,13995,14313,14562,14565,14571,14581,14591,14609,14614,14617,14623,14657,14662,14665,14671,14691,14704,14724,14745,14748,14756],{"type":29,"tag":30,"props":13201,"children":13203},{"id":13202},"patterns-de-résilience-circuit-breaker-retry-timeout",[13204],{"type":35,"value":13184},{"type":29,"tag":37,"props":13206,"children":13207},{},[13208],{"type":35,"value":13209},"J'accompagnais un client dans le secteur du retail en ligne (25 développeurs). En six mois, trois incidents P1, à chaque fois pendant des pics de trafic. Le service de recommandations devenait lent, les threads du service produit s'accumulaient en attente, le pool de connexions s'épuisait, et le service produit tombait à son tour. La homepage devenait indisponible.",{"type":29,"tag":37,"props":13211,"children":13212},{},[13213],{"type":35,"value":13214},"Le service de recommandations avait une excuse valable : les pics de charge. Le service produit n'en avait pas. Il n'avait simplement aucun mécanisme pour se protéger d'un voisin défaillant.",{"type":29,"tag":37,"props":13216,"children":13217},{},[13218],{"type":35,"value":13219},"Deux heures de développement pour ajouter un timeout. Deux jours pour le circuit breaker. Zéro incident P1 lié aux recommandations depuis lors. Les recommandations continuent de tomber lors des pics, mais ça reste isolé.",{"type":29,"tag":37,"props":13221,"children":13222},{},[13223],{"type":35,"value":13224},"C'est ce que les patterns de résilience font : ils n'éliminent pas les pannes, ils empêchent qu'une panne locale devienne un effondrement global.",{"type":29,"tag":76,"props":13226,"children":13227},{},[],{"type":29,"tag":80,"props":13229,"children":13231},{"id":13230},"la-cascade-failure-pourquoi-les-systèmes-distribués-seffondrent-en-bloc",[13232],{"type":35,"value":13233},"La cascade failure : pourquoi les systèmes distribués s'effondrent en bloc",{"type":29,"tag":37,"props":13235,"children":13236},{},[13237,13239,13243],{"type":35,"value":13238},"Sans mécanisme de protection, les appels vers des services externes dans un système distribué ont une propriété dangereuse : si le service cible ralentit, les appelants attendent, leurs ressources se consomment, et ils deviennent eux-mêmes défaillants. Ce phénomène est aggravé par le ",{"type":29,"tag":48,"props":13240,"children":13241},{"href":684},[13242],{"type":35,"value":687},{"type":35,"value":13244}," entre services, qui crée des dépendances implicites d'ordre ou de timing difficiles à détecter jusqu'en production.",{"type":29,"tag":37,"props":13246,"children":13247},{},[13248],{"type":35,"value":13249},"Michael Nygard a documenté ce pattern en détail dans \"Release It!\" (2007), l'ouvrage de référence sur la résilience des systèmes en production. Sa conclusion : la stabilité ne se construit pas par l'optimisme (espérer que les services tiers restent disponibles), mais par la conception défensive (prévoir leur défaillance et la gérer).",{"type":29,"tag":37,"props":13251,"children":13252},{},[13253,13255,13260],{"type":35,"value":13254},"Selon Gartner, une heure de downtime coûte en moyenne ",{"type":29,"tag":65,"props":13256,"children":13257},{},[13258],{"type":35,"value":13259},"300 000€",{"type":35,"value":13261}," pour une application business critique. Les 3 patterns décrits ici sont des assurances contre ce coût.",{"type":29,"tag":76,"props":13263,"children":13264},{},[],{"type":29,"tag":80,"props":13266,"children":13268},{"id":13267},"pattern-1-timeout",[13269],{"type":35,"value":13270},"Pattern 1 : Timeout",{"type":29,"tag":37,"props":13272,"children":13273},{},[13274],{"type":35,"value":13275},"Le timeout est le premier niveau de protection, et le plus souvent absent. Un appel vers un service externe sans timeout peut attendre indéfiniment, bloquant les ressources de l'appelant.",{"type":29,"tag":37,"props":13277,"children":13278},{},[13279,13284],{"type":29,"tag":65,"props":13280,"children":13281},{},[13282],{"type":35,"value":13283},"Principe :",{"type":35,"value":13285}," tout appel vers un service externe (HTTP, base de données, cache, message broker) doit avoir un timeout explicite défini dans le code. Si le service ne répond pas dans ce délai, l'appel est considéré comme échoué et les ressources sont libérées.",{"type":29,"tag":37,"props":13287,"children":13288},{},[13289],{"type":29,"tag":65,"props":13290,"children":13291},{},[13292],{"type":35,"value":13293},"Comment définir la valeur du timeout :",{"type":29,"tag":1080,"props":13295,"children":13296},{},[13297,13302,13307],{"type":29,"tag":1084,"props":13298,"children":13299},{},[13300],{"type":35,"value":13301},"Mesurer le p99 (99ème percentile) de la latence du service cible sur les 30 derniers jours",{"type":29,"tag":1084,"props":13303,"children":13304},{},[13305],{"type":35,"value":13306},"Multiplier par 2 à 3 pour le timeout",{"type":29,"tag":1084,"props":13308,"children":13309},{},[13310],{"type":35,"value":13311},"Ne jamais utiliser la valeur par défaut du client HTTP (souvent 30 secondes à 2 minutes, beaucoup trop long)",{"type":29,"tag":651,"props":13313,"children":13315},{"className":8753,"code":13314,"language":8752,"meta":8,"style":8},"// Exemple avec OkHttp (Java)\nOkHttpClient client = new OkHttpClient.Builder()\n    .connectTimeout(2, TimeUnit.SECONDS)  // temps max pour établir la connexion\n    .readTimeout(5, TimeUnit.SECONDS)     // temps max pour recevoir la réponse\n    .writeTimeout(5, TimeUnit.SECONDS)    // temps max pour envoyer la requête\n    .build();\n",[13316],{"type":29,"tag":565,"props":13317,"children":13318},{"__ignoreMap":8},[13319,13327,13366,13414,13460,13505],{"type":29,"tag":901,"props":13320,"children":13321},{"class":903,"line":904},[13322],{"type":29,"tag":901,"props":13323,"children":13324},{"style":908},[13325],{"type":35,"value":13326},"// Exemple avec OkHttp (Java)\n",{"type":29,"tag":901,"props":13328,"children":13329},{"class":903,"line":463},[13330,13335,13340,13344,13348,13353,13357,13362],{"type":29,"tag":901,"props":13331,"children":13332},{"style":8807},[13333],{"type":35,"value":13334},"OkHttpClient",{"type":29,"tag":901,"props":13336,"children":13337},{"style":923},[13338],{"type":35,"value":13339}," client ",{"type":29,"tag":901,"props":13341,"children":13342},{"style":947},[13343],{"type":35,"value":2227},{"type":29,"tag":901,"props":13345,"children":13346},{"style":917},[13347],{"type":35,"value":7877},{"type":29,"tag":901,"props":13349,"children":13350},{"style":923},[13351],{"type":35,"value":13352}," OkHttpClient",{"type":29,"tag":901,"props":13354,"children":13355},{"style":5185},[13356],{"type":35,"value":342},{"type":29,"tag":901,"props":13358,"children":13359},{"style":5362},[13360],{"type":35,"value":13361},"Builder",{"type":29,"tag":901,"props":13363,"children":13364},{"style":5185},[13365],{"type":35,"value":7003},{"type":29,"tag":901,"props":13367,"children":13368},{"class":903,"line":469},[13369,13374,13379,13383,13387,13391,13396,13400,13405,13409],{"type":29,"tag":901,"props":13370,"children":13371},{"style":5185},[13372],{"type":35,"value":13373},"    .",{"type":29,"tag":901,"props":13375,"children":13376},{"style":5362},[13377],{"type":35,"value":13378},"connectTimeout",{"type":29,"tag":901,"props":13380,"children":13381},{"style":5185},[13382],{"type":35,"value":3080},{"type":29,"tag":901,"props":13384,"children":13385},{"style":5280},[13386],{"type":35,"value":13030},{"type":29,"tag":901,"props":13388,"children":13389},{"style":5185},[13390],{"type":35,"value":3663},{"type":29,"tag":901,"props":13392,"children":13393},{"style":923},[13394],{"type":35,"value":13395}," TimeUnit",{"type":29,"tag":901,"props":13397,"children":13398},{"style":5185},[13399],{"type":35,"value":342},{"type":29,"tag":901,"props":13401,"children":13402},{"style":923},[13403],{"type":35,"value":13404},"SECONDS",{"type":29,"tag":901,"props":13406,"children":13407},{"style":5185},[13408],{"type":35,"value":2881},{"type":29,"tag":901,"props":13410,"children":13411},{"style":908},[13412],{"type":35,"value":13413},"  // temps max pour établir la connexion\n",{"type":29,"tag":901,"props":13415,"children":13416},{"class":903,"line":968},[13417,13421,13426,13430,13435,13439,13443,13447,13451,13455],{"type":29,"tag":901,"props":13418,"children":13419},{"style":5185},[13420],{"type":35,"value":13373},{"type":29,"tag":901,"props":13422,"children":13423},{"style":5362},[13424],{"type":35,"value":13425},"readTimeout",{"type":29,"tag":901,"props":13427,"children":13428},{"style":5185},[13429],{"type":35,"value":3080},{"type":29,"tag":901,"props":13431,"children":13432},{"style":5280},[13433],{"type":35,"value":13434},"5",{"type":29,"tag":901,"props":13436,"children":13437},{"style":5185},[13438],{"type":35,"value":3663},{"type":29,"tag":901,"props":13440,"children":13441},{"style":923},[13442],{"type":35,"value":13395},{"type":29,"tag":901,"props":13444,"children":13445},{"style":5185},[13446],{"type":35,"value":342},{"type":29,"tag":901,"props":13448,"children":13449},{"style":923},[13450],{"type":35,"value":13404},{"type":29,"tag":901,"props":13452,"children":13453},{"style":5185},[13454],{"type":35,"value":2881},{"type":29,"tag":901,"props":13456,"children":13457},{"style":908},[13458],{"type":35,"value":13459},"     // temps max pour recevoir la réponse\n",{"type":29,"tag":901,"props":13461,"children":13462},{"class":903,"line":977},[13463,13467,13472,13476,13480,13484,13488,13492,13496,13500],{"type":29,"tag":901,"props":13464,"children":13465},{"style":5185},[13466],{"type":35,"value":13373},{"type":29,"tag":901,"props":13468,"children":13469},{"style":5362},[13470],{"type":35,"value":13471},"writeTimeout",{"type":29,"tag":901,"props":13473,"children":13474},{"style":5185},[13475],{"type":35,"value":3080},{"type":29,"tag":901,"props":13477,"children":13478},{"style":5280},[13479],{"type":35,"value":13434},{"type":29,"tag":901,"props":13481,"children":13482},{"style":5185},[13483],{"type":35,"value":3663},{"type":29,"tag":901,"props":13485,"children":13486},{"style":923},[13487],{"type":35,"value":13395},{"type":29,"tag":901,"props":13489,"children":13490},{"style":5185},[13491],{"type":35,"value":342},{"type":29,"tag":901,"props":13493,"children":13494},{"style":923},[13495],{"type":35,"value":13404},{"type":29,"tag":901,"props":13497,"children":13498},{"style":5185},[13499],{"type":35,"value":2881},{"type":29,"tag":901,"props":13501,"children":13502},{"style":908},[13503],{"type":35,"value":13504},"    // temps max pour envoyer la requête\n",{"type":29,"tag":901,"props":13506,"children":13507},{"class":903,"line":986},[13508,13512,13517],{"type":29,"tag":901,"props":13509,"children":13510},{"style":5185},[13511],{"type":35,"value":13373},{"type":29,"tag":901,"props":13513,"children":13514},{"style":5362},[13515],{"type":35,"value":13516},"build",{"type":29,"tag":901,"props":13518,"children":13519},{"style":5185},[13520],{"type":35,"value":13521},"();\n",{"type":29,"tag":37,"props":13523,"children":13524},{},[13525,13530],{"type":29,"tag":65,"props":13526,"children":13527},{},[13528],{"type":35,"value":13529},"À quelle couche définir le timeout :",{"type":35,"value":13531}," aussi près que possible de l'appel externe. Un timeout au niveau de l'API gateway seul ne protège pas les services internes.",{"type":29,"tag":76,"props":13533,"children":13534},{},[],{"type":29,"tag":80,"props":13536,"children":13538},{"id":13537},"pattern-2-retry-avec-backoff-exponentiel",[13539],{"type":35,"value":13540},"Pattern 2 : Retry avec backoff exponentiel",{"type":29,"tag":37,"props":13542,"children":13543},{},[13544],{"type":35,"value":13545},"Un service peut échouer de façon transitoire : surcharge momentanée, redémarrage d'instance, pic de latence. Un retry permet de retenter l'opération après un délai, sans inonder le service défaillant de requêtes supplémentaires.",{"type":29,"tag":37,"props":13547,"children":13548},{},[13549,13554],{"type":29,"tag":65,"props":13550,"children":13551},{},[13552],{"type":35,"value":13553},"Principe du backoff exponentiel :",{"type":35,"value":13555}," le délai entre les tentatives augmente exponentiellement. Avec un jitter (variation aléatoire) pour éviter que tous les appelants retentent exactement au même moment, ce qui recréerait la surcharge qu'on cherche à éviter.",{"type":29,"tag":651,"props":13557,"children":13559},{"className":2200,"code":13558,"language":2202,"meta":8,"style":8},"import time\nimport random\n\ndef call_with_retry(func, max_retries=3, base_delay=0.1):\n    for attempt in range(max_retries):\n        try:\n            return func()\n        except TransientError as e:\n            if attempt == max_retries - 1:\n                raise  # dernière tentative — propager l'erreur\n            delay = base_delay * (2 ** attempt) + random.uniform(0, 0.1)  # jitter\n            time.sleep(delay)\n",[13560],{"type":29,"tag":565,"props":13561,"children":13562},{"__ignoreMap":8},[13563,13575,13587,13594,13654,13689,13701,13718,13745,13781,13794,13883],{"type":29,"tag":901,"props":13564,"children":13565},{"class":903,"line":904},[13566,13570],{"type":29,"tag":901,"props":13567,"children":13568},{"style":917},[13569],{"type":35,"value":5671},{"type":29,"tag":901,"props":13571,"children":13572},{"style":923},[13573],{"type":35,"value":13574}," time\n",{"type":29,"tag":901,"props":13576,"children":13577},{"class":903,"line":463},[13578,13582],{"type":29,"tag":901,"props":13579,"children":13580},{"style":917},[13581],{"type":35,"value":5671},{"type":29,"tag":901,"props":13583,"children":13584},{"style":923},[13585],{"type":35,"value":13586}," random\n",{"type":29,"tag":901,"props":13588,"children":13589},{"class":903,"line":469},[13590],{"type":29,"tag":901,"props":13591,"children":13592},{"emptyLinePlaceholder":13},[13593],{"type":35,"value":974},{"type":29,"tag":901,"props":13595,"children":13596},{"class":903,"line":968},[13597,13601,13606,13610,13615,13619,13624,13628,13632,13636,13641,13645,13650],{"type":29,"tag":901,"props":13598,"children":13599},{"style":917},[13600],{"type":35,"value":6593},{"type":29,"tag":901,"props":13602,"children":13603},{"style":5362},[13604],{"type":35,"value":13605}," call_with_retry",{"type":29,"tag":901,"props":13607,"children":13608},{"style":5185},[13609],{"type":35,"value":3080},{"type":29,"tag":901,"props":13611,"children":13612},{"style":5380},[13613],{"type":35,"value":13614},"func",{"type":29,"tag":901,"props":13616,"children":13617},{"style":5185},[13618],{"type":35,"value":3663},{"type":29,"tag":901,"props":13620,"children":13621},{"style":5380},[13622],{"type":35,"value":13623}," max_retries",{"type":29,"tag":901,"props":13625,"children":13626},{"style":947},[13627],{"type":35,"value":2227},{"type":29,"tag":901,"props":13629,"children":13630},{"style":5280},[13631],{"type":35,"value":13048},{"type":29,"tag":901,"props":13633,"children":13634},{"style":5185},[13635],{"type":35,"value":3663},{"type":29,"tag":901,"props":13637,"children":13638},{"style":5380},[13639],{"type":35,"value":13640}," base_delay",{"type":29,"tag":901,"props":13642,"children":13643},{"style":947},[13644],{"type":35,"value":2227},{"type":29,"tag":901,"props":13646,"children":13647},{"style":5280},[13648],{"type":35,"value":13649},"0.1",{"type":29,"tag":901,"props":13651,"children":13652},{"style":5185},[13653],{"type":35,"value":5217},{"type":29,"tag":901,"props":13655,"children":13656},{"class":903,"line":977},[13657,13662,13667,13671,13676,13680,13685],{"type":29,"tag":901,"props":13658,"children":13659},{"style":917},[13660],{"type":35,"value":13661},"    for",{"type":29,"tag":901,"props":13663,"children":13664},{"style":923},[13665],{"type":35,"value":13666}," attempt ",{"type":29,"tag":901,"props":13668,"children":13669},{"style":917},[13670],{"type":35,"value":7164},{"type":29,"tag":901,"props":13672,"children":13673},{"style":5763},[13674],{"type":35,"value":13675}," range",{"type":29,"tag":901,"props":13677,"children":13678},{"style":5185},[13679],{"type":35,"value":3080},{"type":29,"tag":901,"props":13681,"children":13682},{"style":923},[13683],{"type":35,"value":13684},"max_retries",{"type":29,"tag":901,"props":13686,"children":13687},{"style":5185},[13688],{"type":35,"value":5217},{"type":29,"tag":901,"props":13690,"children":13691},{"class":903,"line":986},[13692,13697],{"type":29,"tag":901,"props":13693,"children":13694},{"style":917},[13695],{"type":35,"value":13696},"        try",{"type":29,"tag":901,"props":13698,"children":13699},{"style":5185},[13700],{"type":35,"value":5188},{"type":29,"tag":901,"props":13702,"children":13703},{"class":903,"line":1007},[13704,13709,13714],{"type":29,"tag":901,"props":13705,"children":13706},{"style":917},[13707],{"type":35,"value":13708},"            return",{"type":29,"tag":901,"props":13710,"children":13711},{"style":5242},[13712],{"type":35,"value":13713}," func",{"type":29,"tag":901,"props":13715,"children":13716},{"style":5185},[13717],{"type":35,"value":7003},{"type":29,"tag":901,"props":13719,"children":13720},{"class":903,"line":5354},[13721,13726,13731,13736,13741],{"type":29,"tag":901,"props":13722,"children":13723},{"style":917},[13724],{"type":35,"value":13725},"        except",{"type":29,"tag":901,"props":13727,"children":13728},{"style":923},[13729],{"type":35,"value":13730}," TransientError ",{"type":29,"tag":901,"props":13732,"children":13733},{"style":917},[13734],{"type":35,"value":13735},"as",{"type":29,"tag":901,"props":13737,"children":13738},{"style":923},[13739],{"type":35,"value":13740}," e",{"type":29,"tag":901,"props":13742,"children":13743},{"style":5185},[13744],{"type":35,"value":5188},{"type":29,"tag":901,"props":13746,"children":13747},{"class":903,"line":5390},[13748,13753,13757,13762,13767,13772,13777],{"type":29,"tag":901,"props":13749,"children":13750},{"style":917},[13751],{"type":35,"value":13752},"            if",{"type":29,"tag":901,"props":13754,"children":13755},{"style":923},[13756],{"type":35,"value":13666},{"type":29,"tag":901,"props":13758,"children":13759},{"style":947},[13760],{"type":35,"value":13761},"==",{"type":29,"tag":901,"props":13763,"children":13764},{"style":923},[13765],{"type":35,"value":13766}," max_retries ",{"type":29,"tag":901,"props":13768,"children":13769},{"style":947},[13770],{"type":35,"value":13771},"-",{"type":29,"tag":901,"props":13773,"children":13774},{"style":5280},[13775],{"type":35,"value":13776}," 1",{"type":29,"tag":901,"props":13778,"children":13779},{"style":5185},[13780],{"type":35,"value":5188},{"type":29,"tag":901,"props":13782,"children":13783},{"class":903,"line":5440},[13784,13789],{"type":29,"tag":901,"props":13785,"children":13786},{"style":917},[13787],{"type":35,"value":13788},"                raise",{"type":29,"tag":901,"props":13790,"children":13791},{"style":908},[13792],{"type":35,"value":13793},"  # dernière tentative — propager l'erreur\n",{"type":29,"tag":901,"props":13795,"children":13796},{"class":903,"line":5506},[13797,13802,13806,13811,13816,13820,13824,13829,13834,13838,13842,13847,13851,13856,13860,13865,13869,13874,13878],{"type":29,"tag":901,"props":13798,"children":13799},{"style":923},[13800],{"type":35,"value":13801},"            delay ",{"type":29,"tag":901,"props":13803,"children":13804},{"style":947},[13805],{"type":35,"value":2227},{"type":29,"tag":901,"props":13807,"children":13808},{"style":923},[13809],{"type":35,"value":13810}," base_delay ",{"type":29,"tag":901,"props":13812,"children":13813},{"style":947},[13814],{"type":35,"value":13815},"*",{"type":29,"tag":901,"props":13817,"children":13818},{"style":5185},[13819],{"type":35,"value":7839},{"type":29,"tag":901,"props":13821,"children":13822},{"style":5280},[13823],{"type":35,"value":13030},{"type":29,"tag":901,"props":13825,"children":13826},{"style":947},[13827],{"type":35,"value":13828}," **",{"type":29,"tag":901,"props":13830,"children":13831},{"style":923},[13832],{"type":35,"value":13833}," attempt",{"type":29,"tag":901,"props":13835,"children":13836},{"style":5185},[13837],{"type":35,"value":2881},{"type":29,"tag":901,"props":13839,"children":13840},{"style":947},[13841],{"type":35,"value":9632},{"type":29,"tag":901,"props":13843,"children":13844},{"style":923},[13845],{"type":35,"value":13846}," random",{"type":29,"tag":901,"props":13848,"children":13849},{"style":5185},[13850],{"type":35,"value":342},{"type":29,"tag":901,"props":13852,"children":13853},{"style":5242},[13854],{"type":35,"value":13855},"uniform",{"type":29,"tag":901,"props":13857,"children":13858},{"style":5185},[13859],{"type":35,"value":3080},{"type":29,"tag":901,"props":13861,"children":13862},{"style":5280},[13863],{"type":35,"value":13864},"0",{"type":29,"tag":901,"props":13866,"children":13867},{"style":5185},[13868],{"type":35,"value":3663},{"type":29,"tag":901,"props":13870,"children":13871},{"style":5280},[13872],{"type":35,"value":13873}," 0.1",{"type":29,"tag":901,"props":13875,"children":13876},{"style":5185},[13877],{"type":35,"value":2881},{"type":29,"tag":901,"props":13879,"children":13880},{"style":908},[13881],{"type":35,"value":13882},"  # jitter\n",{"type":29,"tag":901,"props":13884,"children":13885},{"class":903,"line":5911},[13886,13891,13895,13900,13904,13909],{"type":29,"tag":901,"props":13887,"children":13888},{"style":923},[13889],{"type":35,"value":13890},"            time",{"type":29,"tag":901,"props":13892,"children":13893},{"style":5185},[13894],{"type":35,"value":342},{"type":29,"tag":901,"props":13896,"children":13897},{"style":5242},[13898],{"type":35,"value":13899},"sleep",{"type":29,"tag":901,"props":13901,"children":13902},{"style":5185},[13903],{"type":35,"value":3080},{"type":29,"tag":901,"props":13905,"children":13906},{"style":923},[13907],{"type":35,"value":13908},"delay",{"type":29,"tag":901,"props":13910,"children":13911},{"style":5185},[13912],{"type":35,"value":5437},{"type":29,"tag":37,"props":13914,"children":13915},{},[13916],{"type":29,"tag":65,"props":13917,"children":13918},{},[13919],{"type":35,"value":13920},"Quand ne pas retenter :",{"type":29,"tag":1080,"props":13922,"children":13923},{},[13924,13929],{"type":29,"tag":1084,"props":13925,"children":13926},{},[13927],{"type":35,"value":13928},"Erreurs non-transientes (404, 401, 403, validation error) : retenter ne changera rien",{"type":29,"tag":1084,"props":13930,"children":13931},{},[13932],{"type":35,"value":13933},"Opérations non-idempotentes : retenter peut dupliquer l'effet (créer deux commandes au lieu d'une)",{"type":29,"tag":176,"props":13935,"children":13937},{"cta":178,"href":179,"title":13936,"type":181},"Votre système distribué tombe en cascade lors des incidents et vous ne savez pas par où commencer pour le renforcer ?",[13938],{"type":29,"tag":37,"props":13939,"children":13940},{},[13941],{"type":35,"value":13942},"L'implémentation des patterns de résilience nécessite un audit des points de défaillance critiques et un plan de priorisation. Je l'ai fait pour des équipes dans la finance, l'assurance et le e-commerce. En 30 minutes, on peut identifier les 3 flux les plus à risque dans votre architecture et définir le plan d'implémentation.",{"type":29,"tag":76,"props":13944,"children":13945},{},[],{"type":29,"tag":80,"props":13947,"children":13949},{"id":13948},"pattern-3-circuit-breaker",[13950],{"type":35,"value":13951},"Pattern 3 : Circuit Breaker",{"type":29,"tag":37,"props":13953,"children":13954},{},[13955],{"type":35,"value":13956},"Le circuit breaker est le pattern le plus important pour prévenir les cascade failures. Son principe est emprunté à l'électricité : quand un circuit est en surcharge, le disjoncteur coupe le courant pour protéger le reste du circuit.",{"type":29,"tag":37,"props":13958,"children":13959},{},[13960],{"type":29,"tag":65,"props":13961,"children":13962},{},[13963],{"type":35,"value":13964},"Les 3 états :",{"type":29,"tag":37,"props":13966,"children":13967},{},[13968,13973],{"type":29,"tag":65,"props":13969,"children":13970},{},[13971],{"type":35,"value":13972},"Closed (normal)",{"type":35,"value":13974}," : les appels passent normalement. Le circuit breaker monitore le taux d'échec.",{"type":29,"tag":37,"props":13976,"children":13977},{},[13978,13983],{"type":29,"tag":65,"props":13979,"children":13980},{},[13981],{"type":35,"value":13982},"Open",{"type":35,"value":13984}," : le taux d'échec a dépassé le seuil (par exemple, plus de 50% d'échecs sur les 10 derniers appels). Les appels échouent immédiatement sans atteindre le service défaillant. Cela protège le service défaillant de la surcharge et protège l'appelant d'une accumulation de threads.",{"type":29,"tag":37,"props":13986,"children":13987},{},[13988,13993],{"type":29,"tag":65,"props":13989,"children":13990},{},[13991],{"type":35,"value":13992},"Half-Open",{"type":35,"value":13994}," : après un délai (30 secondes par exemple), le circuit breaker laisse passer quelques appels de test. Si ils réussissent, retour à Closed. Sinon, retour à Open.",{"type":29,"tag":651,"props":13996,"children":13998},{"className":8753,"code":13997,"language":8752,"meta":8,"style":8},"// Exemple avec Resilience4j (Java)\nCircuitBreakerConfig config = CircuitBreakerConfig.custom()\n    .failureRateThreshold(50)\n    .waitDurationInOpenState(Duration.ofSeconds(30))\n    .slidingWindowSize(10)\n    .build();\n\nCircuitBreaker circuitBreaker = CircuitBreaker.of(\"paymentService\", config);\n\nSupplier\u003CPayment> decoratedCall = CircuitBreaker\n    .decorateSupplier(circuitBreaker, () -> paymentService.processPayment(request));\n",[13999],{"type":29,"tag":565,"props":14000,"children":14001},{"__ignoreMap":8},[14002,14010,14045,14069,14112,14137,14152,14159,14212,14219,14254],{"type":29,"tag":901,"props":14003,"children":14004},{"class":903,"line":904},[14005],{"type":29,"tag":901,"props":14006,"children":14007},{"style":908},[14008],{"type":35,"value":14009},"// Exemple avec Resilience4j (Java)\n",{"type":29,"tag":901,"props":14011,"children":14012},{"class":903,"line":463},[14013,14018,14023,14027,14032,14036,14041],{"type":29,"tag":901,"props":14014,"children":14015},{"style":8807},[14016],{"type":35,"value":14017},"CircuitBreakerConfig",{"type":29,"tag":901,"props":14019,"children":14020},{"style":923},[14021],{"type":35,"value":14022}," config ",{"type":29,"tag":901,"props":14024,"children":14025},{"style":947},[14026],{"type":35,"value":2227},{"type":29,"tag":901,"props":14028,"children":14029},{"style":923},[14030],{"type":35,"value":14031}," CircuitBreakerConfig",{"type":29,"tag":901,"props":14033,"children":14034},{"style":5185},[14035],{"type":35,"value":342},{"type":29,"tag":901,"props":14037,"children":14038},{"style":5362},[14039],{"type":35,"value":14040},"custom",{"type":29,"tag":901,"props":14042,"children":14043},{"style":5185},[14044],{"type":35,"value":7003},{"type":29,"tag":901,"props":14046,"children":14047},{"class":903,"line":469},[14048,14052,14057,14061,14065],{"type":29,"tag":901,"props":14049,"children":14050},{"style":5185},[14051],{"type":35,"value":13373},{"type":29,"tag":901,"props":14053,"children":14054},{"style":5362},[14055],{"type":35,"value":14056},"failureRateThreshold",{"type":29,"tag":901,"props":14058,"children":14059},{"style":5185},[14060],{"type":35,"value":3080},{"type":29,"tag":901,"props":14062,"children":14063},{"style":5280},[14064],{"type":35,"value":3614},{"type":29,"tag":901,"props":14066,"children":14067},{"style":5185},[14068],{"type":35,"value":5437},{"type":29,"tag":901,"props":14070,"children":14071},{"class":903,"line":968},[14072,14076,14081,14085,14090,14094,14099,14103,14108],{"type":29,"tag":901,"props":14073,"children":14074},{"style":5185},[14075],{"type":35,"value":13373},{"type":29,"tag":901,"props":14077,"children":14078},{"style":5362},[14079],{"type":35,"value":14080},"waitDurationInOpenState",{"type":29,"tag":901,"props":14082,"children":14083},{"style":5185},[14084],{"type":35,"value":3080},{"type":29,"tag":901,"props":14086,"children":14087},{"style":923},[14088],{"type":35,"value":14089},"Duration",{"type":29,"tag":901,"props":14091,"children":14092},{"style":5185},[14093],{"type":35,"value":342},{"type":29,"tag":901,"props":14095,"children":14096},{"style":5362},[14097],{"type":35,"value":14098},"ofSeconds",{"type":29,"tag":901,"props":14100,"children":14101},{"style":5185},[14102],{"type":35,"value":3080},{"type":29,"tag":901,"props":14104,"children":14105},{"style":5280},[14106],{"type":35,"value":14107},"30",{"type":29,"tag":901,"props":14109,"children":14110},{"style":5185},[14111],{"type":35,"value":6687},{"type":29,"tag":901,"props":14113,"children":14114},{"class":903,"line":977},[14115,14119,14124,14128,14133],{"type":29,"tag":901,"props":14116,"children":14117},{"style":5185},[14118],{"type":35,"value":13373},{"type":29,"tag":901,"props":14120,"children":14121},{"style":5362},[14122],{"type":35,"value":14123},"slidingWindowSize",{"type":29,"tag":901,"props":14125,"children":14126},{"style":5185},[14127],{"type":35,"value":3080},{"type":29,"tag":901,"props":14129,"children":14130},{"style":5280},[14131],{"type":35,"value":14132},"10",{"type":29,"tag":901,"props":14134,"children":14135},{"style":5185},[14136],{"type":35,"value":5437},{"type":29,"tag":901,"props":14138,"children":14139},{"class":903,"line":986},[14140,14144,14148],{"type":29,"tag":901,"props":14141,"children":14142},{"style":5185},[14143],{"type":35,"value":13373},{"type":29,"tag":901,"props":14145,"children":14146},{"style":5362},[14147],{"type":35,"value":13516},{"type":29,"tag":901,"props":14149,"children":14150},{"style":5185},[14151],{"type":35,"value":13521},{"type":29,"tag":901,"props":14153,"children":14154},{"class":903,"line":1007},[14155],{"type":29,"tag":901,"props":14156,"children":14157},{"emptyLinePlaceholder":13},[14158],{"type":35,"value":974},{"type":29,"tag":901,"props":14160,"children":14161},{"class":903,"line":5354},[14162,14167,14172,14176,14181,14185,14190,14194,14199,14203,14208],{"type":29,"tag":901,"props":14163,"children":14164},{"style":8807},[14165],{"type":35,"value":14166},"CircuitBreaker",{"type":29,"tag":901,"props":14168,"children":14169},{"style":923},[14170],{"type":35,"value":14171}," circuitBreaker ",{"type":29,"tag":901,"props":14173,"children":14174},{"style":947},[14175],{"type":35,"value":2227},{"type":29,"tag":901,"props":14177,"children":14178},{"style":923},[14179],{"type":35,"value":14180}," CircuitBreaker",{"type":29,"tag":901,"props":14182,"children":14183},{"style":5185},[14184],{"type":35,"value":342},{"type":29,"tag":901,"props":14186,"children":14187},{"style":5362},[14188],{"type":35,"value":14189},"of",{"type":29,"tag":901,"props":14191,"children":14192},{"style":5185},[14193],{"type":35,"value":3080},{"type":29,"tag":901,"props":14195,"children":14196},{"style":2236},[14197],{"type":35,"value":14198},"\"paymentService\"",{"type":29,"tag":901,"props":14200,"children":14201},{"style":5185},[14202],{"type":35,"value":3663},{"type":29,"tag":901,"props":14204,"children":14205},{"style":923},[14206],{"type":35,"value":14207}," config",{"type":29,"tag":901,"props":14209,"children":14210},{"style":5185},[14211],{"type":35,"value":8833},{"type":29,"tag":901,"props":14213,"children":14214},{"class":903,"line":5390},[14215],{"type":29,"tag":901,"props":14216,"children":14217},{"emptyLinePlaceholder":13},[14218],{"type":35,"value":974},{"type":29,"tag":901,"props":14220,"children":14221},{"class":903,"line":5440},[14222,14227,14231,14236,14240,14245,14249],{"type":29,"tag":901,"props":14223,"children":14224},{"style":8807},[14225],{"type":35,"value":14226},"Supplier",{"type":29,"tag":901,"props":14228,"children":14229},{"style":5185},[14230],{"type":35,"value":7317},{"type":29,"tag":901,"props":14232,"children":14233},{"style":917},[14234],{"type":35,"value":14235},"Payment",{"type":29,"tag":901,"props":14237,"children":14238},{"style":5185},[14239],{"type":35,"value":7327},{"type":29,"tag":901,"props":14241,"children":14242},{"style":923},[14243],{"type":35,"value":14244}," decoratedCall ",{"type":29,"tag":901,"props":14246,"children":14247},{"style":947},[14248],{"type":35,"value":2227},{"type":29,"tag":901,"props":14250,"children":14251},{"style":8807},[14252],{"type":35,"value":14253}," CircuitBreaker\n",{"type":29,"tag":901,"props":14255,"children":14256},{"class":903,"line":5506},[14257,14261,14266,14270,14275,14279,14283,14287,14292,14296,14301,14305,14309],{"type":29,"tag":901,"props":14258,"children":14259},{"style":5185},[14260],{"type":35,"value":13373},{"type":29,"tag":901,"props":14262,"children":14263},{"style":5362},[14264],{"type":35,"value":14265},"decorateSupplier",{"type":29,"tag":901,"props":14267,"children":14268},{"style":5185},[14269],{"type":35,"value":3080},{"type":29,"tag":901,"props":14271,"children":14272},{"style":923},[14273],{"type":35,"value":14274},"circuitBreaker",{"type":29,"tag":901,"props":14276,"children":14277},{"style":5185},[14278],{"type":35,"value":3663},{"type":29,"tag":901,"props":14280,"children":14281},{"style":5185},[14282],{"type":35,"value":8144},{"type":29,"tag":901,"props":14284,"children":14285},{"style":917},[14286],{"type":35,"value":5775},{"type":29,"tag":901,"props":14288,"children":14289},{"style":923},[14290],{"type":35,"value":14291}," paymentService",{"type":29,"tag":901,"props":14293,"children":14294},{"style":5185},[14295],{"type":35,"value":342},{"type":29,"tag":901,"props":14297,"children":14298},{"style":5362},[14299],{"type":35,"value":14300},"processPayment",{"type":29,"tag":901,"props":14302,"children":14303},{"style":5185},[14304],{"type":35,"value":3080},{"type":29,"tag":901,"props":14306,"children":14307},{"style":923},[14308],{"type":35,"value":11961},{"type":29,"tag":901,"props":14310,"children":14311},{"style":5185},[14312],{"type":35,"value":9253},{"type":29,"tag":651,"props":14314,"children":14316},{"className":10784,"code":14315,"language":10783,"meta":8,"style":8},"// Exemple avec opossum (Node.js)\nconst CircuitBreaker = require('opossum');\n\nconst breaker = new CircuitBreaker(paymentService.processPayment, {\n    timeout: 3000,\n    errorThresholdPercentage: 50,\n    resetTimeout: 30000\n});\n\nbreaker.fallback(() => ({ status: 'payment_service_unavailable' }));\n",[14317],{"type":29,"tag":565,"props":14318,"children":14319},{"__ignoreMap":8},[14320,14328,14366,14373,14418,14439,14460,14477,14492,14499],{"type":29,"tag":901,"props":14321,"children":14322},{"class":903,"line":904},[14323],{"type":29,"tag":901,"props":14324,"children":14325},{"style":908},[14326],{"type":35,"value":14327},"// Exemple avec opossum (Node.js)\n",{"type":29,"tag":901,"props":14329,"children":14330},{"class":903,"line":463},[14331,14336,14340,14344,14349,14353,14358,14362],{"type":29,"tag":901,"props":14332,"children":14333},{"style":917},[14334],{"type":35,"value":14335},"const",{"type":29,"tag":901,"props":14337,"children":14338},{"style":5674},[14339],{"type":35,"value":14180},{"type":29,"tag":901,"props":14341,"children":14342},{"style":947},[14343],{"type":35,"value":6944},{"type":29,"tag":901,"props":14345,"children":14346},{"style":5362},[14347],{"type":35,"value":14348}," require",{"type":29,"tag":901,"props":14350,"children":14351},{"style":923},[14352],{"type":35,"value":3080},{"type":29,"tag":901,"props":14354,"children":14355},{"style":2236},[14356],{"type":35,"value":14357},"'opossum'",{"type":29,"tag":901,"props":14359,"children":14360},{"style":923},[14361],{"type":35,"value":2881},{"type":29,"tag":901,"props":14363,"children":14364},{"style":5185},[14365],{"type":35,"value":7332},{"type":29,"tag":901,"props":14367,"children":14368},{"class":903,"line":469},[14369],{"type":29,"tag":901,"props":14370,"children":14371},{"emptyLinePlaceholder":13},[14372],{"type":35,"value":974},{"type":29,"tag":901,"props":14374,"children":14375},{"class":903,"line":968},[14376,14380,14385,14389,14393,14397,14402,14406,14410,14414],{"type":29,"tag":901,"props":14377,"children":14378},{"style":917},[14379],{"type":35,"value":14335},{"type":29,"tag":901,"props":14381,"children":14382},{"style":5674},[14383],{"type":35,"value":14384}," breaker",{"type":29,"tag":901,"props":14386,"children":14387},{"style":947},[14388],{"type":35,"value":6944},{"type":29,"tag":901,"props":14390,"children":14391},{"style":7874},[14392],{"type":35,"value":7877},{"type":29,"tag":901,"props":14394,"children":14395},{"style":5362},[14396],{"type":35,"value":14180},{"type":29,"tag":901,"props":14398,"children":14399},{"style":923},[14400],{"type":35,"value":14401},"(paymentService",{"type":29,"tag":901,"props":14403,"children":14404},{"style":7730},[14405],{"type":35,"value":342},{"type":29,"tag":901,"props":14407,"children":14408},{"style":923},[14409],{"type":35,"value":14300},{"type":29,"tag":901,"props":14411,"children":14412},{"style":5185},[14413],{"type":35,"value":3663},{"type":29,"tag":901,"props":14415,"children":14416},{"style":5185},[14417],{"type":35,"value":7272},{"type":29,"tag":901,"props":14419,"children":14420},{"class":903,"line":977},[14421,14426,14430,14435],{"type":29,"tag":901,"props":14422,"children":14423},{"style":923},[14424],{"type":35,"value":14425},"    timeout",{"type":29,"tag":901,"props":14427,"children":14428},{"style":7730},[14429],{"type":35,"value":5760},{"type":29,"tag":901,"props":14431,"children":14432},{"style":5280},[14433],{"type":35,"value":14434}," 3000",{"type":29,"tag":901,"props":14436,"children":14437},{"style":5185},[14438],{"type":35,"value":7598},{"type":29,"tag":901,"props":14440,"children":14441},{"class":903,"line":986},[14442,14447,14451,14456],{"type":29,"tag":901,"props":14443,"children":14444},{"style":923},[14445],{"type":35,"value":14446},"    errorThresholdPercentage",{"type":29,"tag":901,"props":14448,"children":14449},{"style":7730},[14450],{"type":35,"value":5760},{"type":29,"tag":901,"props":14452,"children":14453},{"style":5280},[14454],{"type":35,"value":14455}," 50",{"type":29,"tag":901,"props":14457,"children":14458},{"style":5185},[14459],{"type":35,"value":7598},{"type":29,"tag":901,"props":14461,"children":14462},{"class":903,"line":1007},[14463,14468,14472],{"type":29,"tag":901,"props":14464,"children":14465},{"style":923},[14466],{"type":35,"value":14467},"    resetTimeout",{"type":29,"tag":901,"props":14469,"children":14470},{"style":7730},[14471],{"type":35,"value":5760},{"type":29,"tag":901,"props":14473,"children":14474},{"style":5280},[14475],{"type":35,"value":14476}," 30000\n",{"type":29,"tag":901,"props":14478,"children":14479},{"class":903,"line":5354},[14480,14484,14488],{"type":29,"tag":901,"props":14481,"children":14482},{"style":5185},[14483],{"type":35,"value":2255},{"type":29,"tag":901,"props":14485,"children":14486},{"style":923},[14487],{"type":35,"value":2881},{"type":29,"tag":901,"props":14489,"children":14490},{"style":5185},[14491],{"type":35,"value":7332},{"type":29,"tag":901,"props":14493,"children":14494},{"class":903,"line":5390},[14495],{"type":29,"tag":901,"props":14496,"children":14497},{"emptyLinePlaceholder":13},[14498],{"type":35,"value":974},{"type":29,"tag":901,"props":14500,"children":14501},{"class":903,"line":5440},[14502,14507,14511,14516,14520,14524,14528,14532,14536,14540,14544,14549,14553,14558],{"type":29,"tag":901,"props":14503,"children":14504},{"style":923},[14505],{"type":35,"value":14506},"breaker",{"type":29,"tag":901,"props":14508,"children":14509},{"style":7730},[14510],{"type":35,"value":342},{"type":29,"tag":901,"props":14512,"children":14513},{"style":5362},[14514],{"type":35,"value":14515},"fallback",{"type":29,"tag":901,"props":14517,"children":14518},{"style":923},[14519],{"type":35,"value":3080},{"type":29,"tag":901,"props":14521,"children":14522},{"style":5185},[14523],{"type":35,"value":8253},{"type":29,"tag":901,"props":14525,"children":14526},{"style":917},[14527],{"type":35,"value":8149},{"type":29,"tag":901,"props":14529,"children":14530},{"style":923},[14531],{"type":35,"value":7839},{"type":29,"tag":901,"props":14533,"children":14534},{"style":5185},[14535],{"type":35,"value":2245},{"type":29,"tag":901,"props":14537,"children":14538},{"style":923},[14539],{"type":35,"value":8347},{"type":29,"tag":901,"props":14541,"children":14542},{"style":7730},[14543],{"type":35,"value":5760},{"type":29,"tag":901,"props":14545,"children":14546},{"style":2236},[14547],{"type":35,"value":14548}," 'payment_service_unavailable'",{"type":29,"tag":901,"props":14550,"children":14551},{"style":5185},[14552],{"type":35,"value":8361},{"type":29,"tag":901,"props":14554,"children":14555},{"style":923},[14556],{"type":35,"value":14557},"))",{"type":29,"tag":901,"props":14559,"children":14560},{"style":5185},[14561],{"type":35,"value":7332},{"type":29,"tag":76,"props":14563,"children":14564},{},[],{"type":29,"tag":80,"props":14566,"children":14568},{"id":14567},"les-compléments-bulkhead-et-fallback",[14569],{"type":35,"value":14570},"Les compléments : bulkhead et fallback",{"type":29,"tag":37,"props":14572,"children":14573},{},[14574,14579],{"type":29,"tag":65,"props":14575,"children":14576},{},[14577],{"type":35,"value":14578},"Bulkhead :",{"type":35,"value":14580}," isoler les ressources par service externe. Chaque service externe a son propre pool de threads ou de connexions : une dégradation d'un service ne consomme pas toutes les ressources de l'appelant.",{"type":29,"tag":37,"props":14582,"children":14583},{},[14584,14589],{"type":29,"tag":65,"props":14585,"children":14586},{},[14587],{"type":35,"value":14588},"Fallback :",{"type":35,"value":14590}," définir un comportement de repli quand le circuit est ouvert. Pas \"retourner une erreur 500\", mais retourner un résultat dégradé acceptable.",{"type":29,"tag":1080,"props":14592,"children":14593},{},[14594,14599,14604],{"type":29,"tag":1084,"props":14595,"children":14596},{},[14597],{"type":35,"value":14598},"Service de recommandations indisponible → retourner des recommandations statiques ou populaires",{"type":29,"tag":1084,"props":14600,"children":14601},{},[14602],{"type":35,"value":14603},"Service de notation indisponible → afficher la note moyenne sans recalcul temps-réel",{"type":29,"tag":1084,"props":14605,"children":14606},{},[14607],{"type":35,"value":14608},"Service de paiement indisponible → mettre la commande en queue pour traitement différé",{"type":29,"tag":37,"props":14610,"children":14611},{},[14612],{"type":35,"value":14613},"Votre système doit fonctionner de façon dégradée quand un service non-critique est indisponible. Il ne doit pas être entièrement indisponible.",{"type":29,"tag":76,"props":14615,"children":14616},{},[],{"type":29,"tag":80,"props":14618,"children":14620},{"id":14619},"ordre-dimplémentation",[14621],{"type":35,"value":14622},"Ordre d'implémentation",{"type":29,"tag":14624,"props":14625,"children":14626},"ol",{},[14627,14637,14647],{"type":29,"tag":1084,"props":14628,"children":14629},{},[14630,14635],{"type":29,"tag":65,"props":14631,"children":14632},{},[14633],{"type":35,"value":14634},"Timeout d'abord",{"type":35,"value":14636}," (1 journée) : ajouter des timeouts explicites sur tous les appels vers des services externes. C'est la correction la plus rapide et la plus impactante.",{"type":29,"tag":1084,"props":14638,"children":14639},{},[14640,14645],{"type":29,"tag":65,"props":14641,"children":14642},{},[14643],{"type":35,"value":14644},"Retry sur les erreurs transientes",{"type":35,"value":14646}," (2 à 3 jours) : identifier les erreurs transientes dans votre système et ajouter un retry avec backoff exponentiel. S'assurer que les opérations retriées sont idempotentes.",{"type":29,"tag":1084,"props":14648,"children":14649},{},[14650,14655],{"type":29,"tag":65,"props":14651,"children":14652},{},[14653],{"type":35,"value":14654},"Circuit breaker sur les services critiques",{"type":35,"value":14656}," (1 semaine) : identifier les 5 à 10 dépendances externes les plus critiques et implémenter le circuit breaker avec monitoring.",{"type":29,"tag":37,"props":14658,"children":14659},{},[14660],{"type":35,"value":14661},"En moins de 2 semaines, votre système est significativement plus résilient.",{"type":29,"tag":76,"props":14663,"children":14664},{},[],{"type":29,"tag":80,"props":14666,"children":14668},{"id":14667},"faq-sur-les-patterns-de-résilience",[14669],{"type":35,"value":14670},"FAQ sur les patterns de résilience",{"type":29,"tag":381,"props":14672,"children":14673},{},[14674,14679],{"type":29,"tag":385,"props":14675,"children":14676},{},[14677],{"type":35,"value":14678},"1. Les patterns de résilience s'appliquent-ils aux monolithes ou seulement aux microservices ?",{"type":29,"tag":37,"props":14680,"children":14681},{},[14682,14684,14689],{"type":35,"value":14683},"Aux deux. Tout système qui appelle des services externes (base de données, cache, API tierce, service d'email) bénéficie des timeouts, retries, et circuit breakers. Dans un monolithe, les patterns s'appliquent sur les appels vers les dépendances externes. Dans les ",{"type":29,"tag":48,"props":14685,"children":14686},{"href":483},[14687],{"type":35,"value":14688},"microservices avec une base de données par service",{"type":35,"value":14690},", ils s'appliquent aussi aux appels inter-services, et sont même indispensables pour gérer la cohérence éventuelle entre services. J'ai implémenté ces patterns dans des monolithes bancaires aussi bien que dans des architectures microservices de e-commerce.",{"type":29,"tag":381,"props":14692,"children":14693},{},[14694,14699],{"type":29,"tag":385,"props":14695,"children":14696},{},[14697],{"type":35,"value":14698},"2. Quel outil choisir pour implémenter les patterns de résilience ?",{"type":29,"tag":37,"props":14700,"children":14701},{},[14702],{"type":35,"value":14703},"Par écosystème : Java/Kotlin → Resilience4j (successeur de Hystrix, maintenu activement). Node.js → opossum. Python → tenacity pour le retry. Go → gobreaker. Spring Boot → intégration native de Resilience4j via Spring Cloud Circuit Breaker. À l'infrastructure : Istio et Envoy permettent d'implémenter ces patterns au niveau du service mesh, sans modification du code applicatif, utile pour les équipes qui gèrent de nombreux services.",{"type":29,"tag":381,"props":14705,"children":14706},{},[14707,14712],{"type":29,"tag":385,"props":14708,"children":14709},{},[14710],{"type":35,"value":14711},"3. Comment monitorer l'état des circuit breakers en production ?",{"type":29,"tag":37,"props":14713,"children":14714},{},[14715,14717,14722],{"type":35,"value":14716},"Les circuit breakers ouverts sont des alertes : ils signalent qu'un service est en difficulté. Exposer l'état des circuit breakers dans votre système de monitoring (Prometheus + Grafana, Datadog, New Relic). Configurer une alerte quand un circuit breaker passe à l'état Open : c'est un signal d'action, pas seulement d'information. Un circuit breaker qui reste ouvert en permanence indique un service en difficulté structurelle. Ces métriques de disponibilité font partie des ",{"type":29,"tag":48,"props":14718,"children":14719},{"href":12453},[14720],{"type":35,"value":14721},"indicateurs clés à suivre pour les équipes engineering",{"type":35,"value":14723}," : elles objectivent l'état de santé de l'architecture et rendent visibles les progrès réalisés.",{"type":29,"tag":381,"props":14725,"children":14726},{},[14727,14732],{"type":29,"tag":385,"props":14728,"children":14729},{},[14730],{"type":35,"value":14731},"4. Comment tester les patterns de résilience sans attendre un incident en production ?",{"type":29,"tag":37,"props":14733,"children":14734},{},[14735,14737,14743],{"type":35,"value":14736},"Le chaos engineering est la méthode de référence. Outils : Chaos Monkey (Netflix), Gremlin, ou des scripts simples qui introduisent des latences artificielles en staging. Pour commencer sans outil spécifique : injecter un ",{"type":29,"tag":565,"props":14738,"children":14740},{"className":14739},[],[14741],{"type":35,"value":14742},"sleep(5000)",{"type":35,"value":14744}," dans le service cible en environnement de test et vérifier que les timeouts et circuit breakers fonctionnent comme attendu. Ce test prend 30 minutes et devrait être dans votre suite de tests de non-régression.",{"type":29,"tag":76,"props":14746,"children":14747},{},[],{"type":29,"tag":176,"props":14749,"children":14750},{"cta":1243,"href":1244,"title":454,"type":455},[14751],{"type":29,"tag":37,"props":14752,"children":14753},{},[14754],{"type":35,"value":14755},"L'Engineering Maturity Self-Assessment couvre le domaine Résilience & Architecture : évaluez en 10 minutes votre niveau sur les patterns de résilience, la robustesse de vos services, et la gestion des pannes. Obtenez un score et un plan d'action personnalisé.",{"type":29,"tag":1252,"props":14757,"children":14758},{},[14759],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":14761},[14762,14763,14764,14765,14766,14767,14768],{"id":13230,"depth":463,"text":13233},{"id":13267,"depth":463,"text":13270},{"id":13537,"depth":463,"text":13540},{"id":13948,"depth":463,"text":13951},{"id":14567,"depth":463,"text":14570},{"id":14619,"depth":463,"text":14622},{"id":14667,"depth":463,"text":14670},"content:fr:architecture-craft:patterns-resilience-circuit-breaker-retry.md","fr/architecture-craft/patterns-resilience-circuit-breaker-retry.md","fr/architecture-craft/patterns-resilience-circuit-breaker-retry",{"_path":14773,"_dir":1271,"_draft":7,"_partial":7,"_locale":8,"title":14774,"description":14775,"id":6241,"date":14776,"listed":13,"nocomments":7,"hidden":7,"categories":14777,"tags":14778,"--cover":14781,"readingTime":14782,"body":14786,"_type":476,"_id":15331,"_source":478,"_file":15332,"_stem":15333,"_extension":481},"/fr/management/gerer-developpeur-en-difficulte","Comment gérer un développeur en difficulté","Un développeur en difficulté n'est pas forcément un mauvais développeur. C'est souvent un bon développeur dans le mauvais contexte. Le protocole d'intervention avant qu'il parte.","2026-02-27",[1271],[1279,14779,14780],"Performance","Développement Individuel","covers/articles/gerer-developpeur-difficulte.jpg",{"text":497,"minutes":14783,"time":14784,"words":14785},7.305,438300,1461,{"type":26,"children":14787,"toc":15323},[14788,14793,14798,14810,14815,14818,14824,14836,14844,14867,14875,14898,14908,14911,14917,14922,14932,14942,14952,14962,14971,14974,14980,14990,14995,15007,15017,15025,15043,15051,15069,15079,15082,15088,15093,15110,15120,15136,15146,15156,15159,15165,15170,15188,15193,15226,15231,15234,15240,15253,15273,15286,15299,15312,15315],{"type":29,"tag":30,"props":14789,"children":14791},{"id":14790},"comment-gérer-un-développeur-en-difficulté",[14792],{"type":35,"value":14774},{"type":29,"tag":37,"props":14794,"children":14795},{},[14796],{"type":35,"value":14797},"Chez BNP Paribas, j'avais un développeur (5 ans d'expérience, reconnu dans l'équipe) qui s'était progressivement effacé. Moins de participation en réunion. Stories qui s'étiraient. Code review de moins en moins actif. Pendant 6 semaines, j'ai rationalisé : période chargée, contexte difficile, ça va passer. Ça n'a pas passé. Il est parti 3 mois plus tard. En post-mortem, j'ai compris que sa difficulté avait une cause simple : on l'avait repositionné sur une technologie qu'il ne maîtrisait pas, sans formation, sans filet. Six semaines d'inconfort muet, et personne n'avait ouvert la porte.",{"type":29,"tag":37,"props":14799,"children":14800},{},[14801,14803,14808],{"type":35,"value":14802},"C'est l'erreur la plus courante que j'observe chez les managers engineering. Attendre. Espérer que ça se résout seul. Parfois ça se résout : le développeur trouve ses marques, le problème contextuel disparaît. Mais dans la majorité des cas, l'absence d'intervention transforme un problème traitable en départ. Et remplacer un développeur senior coûte entre ",{"type":29,"tag":65,"props":14804,"children":14805},{},[14806],{"type":35,"value":14807},"65 000 et 130 000€",{"type":35,"value":14809}," en recrutement, onboarding, et perte de productivité sur 6 à 12 mois.",{"type":29,"tag":37,"props":14811,"children":14812},{},[14813],{"type":35,"value":14814},"Ce n'était jamais un problème de personnes. C'était un problème de système : un système qui ne détectait pas les signaux et n'avait pas de protocole d'intervention.",{"type":29,"tag":76,"props":14816,"children":14817},{},[],{"type":29,"tag":80,"props":14819,"children":14821},{"id":14820},"les-signaux-précoces-observer-avant-dintervenir",[14822],{"type":35,"value":14823},"Les signaux précoces : observer avant d'intervenir",{"type":29,"tag":37,"props":14825,"children":14826},{},[14827,14829,14834],{"type":35,"value":14828},"Avant toute conversation, j'observe sur ",{"type":29,"tag":65,"props":14830,"children":14831},{},[14832],{"type":35,"value":14833},"2 à 4 semaines minimum",{"type":35,"value":14835},". Une mauvaise semaine n'est pas un pattern. Un pattern, c'est un signal qui persiste.",{"type":29,"tag":37,"props":14837,"children":14838},{},[14839],{"type":29,"tag":65,"props":14840,"children":14841},{},[14842],{"type":35,"value":14843},"Signaux techniques à surveiller :",{"type":29,"tag":1080,"props":14845,"children":14846},{},[14847,14852,14857,14862],{"type":29,"tag":1084,"props":14848,"children":14849},{},[14850],{"type":35,"value":14851},"Baisse de la qualité du code (plus de bugs sur ses stories, code reviews avec plus de commentaires correctifs)",{"type":29,"tag":1084,"props":14853,"children":14854},{},[14855],{"type":35,"value":14856},"Stories qui s'étirent au-delà de leur estimation habituelle",{"type":29,"tag":1084,"props":14858,"children":14859},{},[14860],{"type":35,"value":14861},"PR créées plus tard dans le sprint, ou abandonnées sans merge",{"type":29,"tag":1084,"props":14863,"children":14864},{},[14865],{"type":35,"value":14866},"Diminution de la participation aux revues de code",{"type":29,"tag":37,"props":14868,"children":14869},{},[14870],{"type":29,"tag":65,"props":14871,"children":14872},{},[14873],{"type":35,"value":14874},"Signaux comportementaux à surveiller :",{"type":29,"tag":1080,"props":14876,"children":14877},{},[14878,14883,14888,14893],{"type":29,"tag":1084,"props":14879,"children":14880},{},[14881],{"type":35,"value":14882},"Moins de participation aux réunions (questions posées, idées proposées)",{"type":29,"tag":1084,"props":14884,"children":14885},{},[14886],{"type":35,"value":14887},"Isolement progressif (moins de communication spontanée dans Slack, moins de conversations informelles)",{"type":29,"tag":1084,"props":14889,"children":14890},{},[14891],{"type":35,"value":14892},"Retards ou absences qui n'avaient pas de précédent",{"type":29,"tag":1084,"props":14894,"children":14895},{},[14896],{"type":35,"value":14897},"Changement de ton dans les échanges écrits",{"type":29,"tag":37,"props":14899,"children":14900},{},[14901,14906],{"type":29,"tag":65,"props":14902,"children":14903},{},[14904],{"type":35,"value":14905},"Ma règle des 2 semaines :",{"type":35,"value":14907}," si un signal persiste sur 2 semaines, c'est un pattern. Si 2 signaux ou plus apparaissent simultanément, j'interviens immédiatement. Je n'attends pas.",{"type":29,"tag":76,"props":14909,"children":14910},{},[],{"type":29,"tag":80,"props":14912,"children":14914},{"id":14913},"le-diagnostic-identifier-la-catégorie-avant-de-parler",[14915],{"type":35,"value":14916},"Le diagnostic : identifier la catégorie avant de parler",{"type":29,"tag":37,"props":14918,"children":14919},{},[14920],{"type":35,"value":14921},"Avant la conversation, je me force à avoir une hypothèse sur la cause. Les 4 catégories de difficultés ont des interventions radicalement différentes : parler sans hypothèse, c'est risquer de traiter le mauvais problème.",{"type":29,"tag":37,"props":14923,"children":14924},{},[14925,14930],{"type":29,"tag":65,"props":14926,"children":14927},{},[14928],{"type":35,"value":14929},"Catégorie 1 : Difficulté contextuelle :",{"type":35,"value":14931}," le projet, la technologie, ou l'environnement a changé. Le développeur n'a pas les outils, l'information, ou le support nécessaire pour s'adapter. C'était le cas dans l'histoire que j'ai décrite plus haut.",{"type":29,"tag":37,"props":14933,"children":14934},{},[14935,14940],{"type":29,"tag":65,"props":14936,"children":14937},{},[14938],{"type":35,"value":14939},"Catégorie 2 : Difficulté de compétences :",{"type":35,"value":14941}," la story ou le projet requiert des compétences que le développeur n'a pas encore, et aucune aide n'a été proposée pour combler le gap. Fréquent dans les équipes qui montent en gamme technologiquement sans investir dans la formation.",{"type":29,"tag":37,"props":14943,"children":14944},{},[14945,14950],{"type":29,"tag":65,"props":14946,"children":14947},{},[14948],{"type":35,"value":14949},"Catégorie 3 : Difficulté de motivation :",{"type":35,"value":14951}," le développeur a perdu le sens de son travail. Le projet ne l'engage plus, les perspectives de carrière sont floues, ou les ambitions ne correspondent plus au rôle. Souvent une conséquence non-adressée des catégories 1 ou 2.",{"type":29,"tag":37,"props":14953,"children":14954},{},[14955,14960],{"type":29,"tag":65,"props":14956,"children":14957},{},[14958],{"type":35,"value":14959},"Catégorie 4 : Difficulté personnelle :",{"type":35,"value":14961}," un problème extérieur au travail (santé, famille, finances) impacte la performance. C'est la catégorie la plus délicate : elle nécessite de la sensibilité et une attention à ne pas franchir les frontières de la vie privée.",{"type":29,"tag":176,"props":14963,"children":14965},{"cta":178,"href":179,"title":14964,"type":181},"Un de vos développeurs semble en difficulté et vous ne savez pas comment aborder le sujet sans aggraver la situation ?",[14966],{"type":29,"tag":37,"props":14967,"children":14968},{},[14969],{"type":35,"value":14970},"Vous avez peut-être les signaux mais pas la méthode pour ouvrir la conversation sans créer de la défensivité. En 30 minutes, je peux vous aider à préparer la conversation, anticiper les réactions possibles, et définir le plan d'action adapté à la catégorie de difficulté que vous observez.",{"type":29,"tag":76,"props":14972,"children":14973},{},[],{"type":29,"tag":80,"props":14975,"children":14977},{"id":14976},"la-conversation-honnête-ni-accusation-ni-déni",[14978],{"type":35,"value":14979},"La conversation honnête : ni accusation ni déni",{"type":29,"tag":37,"props":14981,"children":14982},{},[14983,14988],{"type":29,"tag":65,"props":14984,"children":14985},{},[14986],{"type":35,"value":14987},"L'ouverture que j'utilise :",{"type":35,"value":14989}," je commence par l'observation factuelle, jamais par le jugement.",{"type":29,"tag":37,"props":14991,"children":14992},{},[14993],{"type":35,"value":14994},"Ce que je ne dis pas : \"Ta performance a beaucoup baissé ces dernières semaines.\"",{"type":29,"tag":37,"props":14996,"children":14997},{},[14998,15000,15005],{"type":35,"value":14999},"Ce que je dis : \"J'ai observé que tes stories prennent plus de temps que d'habitude ces 3 dernières semaines, par exemple ",{"type":29,"tag":901,"props":15001,"children":15002},{},[15003],{"type":35,"value":15004},"exemples spécifiques",{"type":35,"value":15006},". Et tu sembles moins participer aux réunions d'équipe. Je voulais prendre le temps de discuter avec toi pour comprendre ce qui se passe.\"",{"type":29,"tag":37,"props":15008,"children":15009},{},[15010,15015],{"type":29,"tag":65,"props":15011,"children":15012},{},[15013],{"type":35,"value":15014},"Après l'ouverture, je me tais.",{"type":35,"value":15016}," La plupart des développeurs en difficulté savent que quelque chose ne va pas : ils attendent souvent qu'on leur ouvre la porte.",{"type":29,"tag":37,"props":15018,"children":15019},{},[15020],{"type":29,"tag":65,"props":15021,"children":15022},{},[15023],{"type":35,"value":15024},"Questions qui fonctionnent :",{"type":29,"tag":1080,"props":15026,"children":15027},{},[15028,15033,15038],{"type":29,"tag":1084,"props":15029,"children":15030},{},[15031],{"type":35,"value":15032},"\"Comment tu vis cette période ?\"",{"type":29,"tag":1084,"props":15034,"children":15035},{},[15036],{"type":35,"value":15037},"\"Qu'est-ce qui serait différent si les choses allaient mieux ?\"",{"type":29,"tag":1084,"props":15039,"children":15040},{},[15041],{"type":35,"value":15042},"\"Y a-t-il des obstacles que tu rencontres sur lesquels je pourrais t'aider ?\"",{"type":29,"tag":37,"props":15044,"children":15045},{},[15046],{"type":29,"tag":65,"props":15047,"children":15048},{},[15049],{"type":35,"value":15050},"Ce que je ne fais absolument pas :",{"type":29,"tag":1080,"props":15052,"children":15053},{},[15054,15059,15064],{"type":29,"tag":1084,"props":15055,"children":15056},{},[15057],{"type":35,"value":15058},"Minimiser (\"tout le monde passe par des périodes difficiles\")",{"type":29,"tag":1084,"props":15060,"children":15061},{},[15062],{"type":35,"value":15063},"Proposer des solutions avant d'avoir compris le problème",{"type":29,"tag":1084,"props":15065,"children":15066},{},[15067],{"type":35,"value":15068},"Menacer, même implicitement, de conséquences pendant cette première conversation",{"type":29,"tag":37,"props":15070,"children":15071},{},[15072,15077],{"type":29,"tag":65,"props":15073,"children":15074},{},[15075],{"type":35,"value":15076},"Résultat attendu :",{"type":35,"value":15078}," une compréhension partagée de ce qui se passe, pas nécessairement la solution, mais la cause.",{"type":29,"tag":76,"props":15080,"children":15081},{},[],{"type":29,"tag":80,"props":15083,"children":15085},{"id":15084},"le-plan-de-développement-sur-30-jours",[15086],{"type":35,"value":15087},"Le plan de développement sur 30 jours",{"type":29,"tag":37,"props":15089,"children":15090},{},[15091],{"type":35,"value":15092},"Selon la catégorie diagnostiquée, le plan de 30 jours est différent.",{"type":29,"tag":37,"props":15094,"children":15095},{},[15096,15101,15103,15108],{"type":29,"tag":65,"props":15097,"children":15098},{},[15099],{"type":35,"value":15100},"Pour la difficulté contextuelle :",{"type":35,"value":15102}," identifier et lever l'obstacle. ",{"type":29,"tag":48,"props":15104,"children":15105},{"href":355},[15106],{"type":35,"value":15107},"Pair programming",{"type":35,"value":15109}," avec quelqu'un qui maîtrise la technologie, accès à la documentation manquante, clarification des attentes.",{"type":29,"tag":37,"props":15111,"children":15112},{},[15113,15118],{"type":29,"tag":65,"props":15114,"children":15115},{},[15116],{"type":35,"value":15117},"Pour la difficulté de compétences :",{"type":35,"value":15119}," définir un plan de formation ciblé. 1 à 2 semaines de formation dédiée, stories de montée en compétence progressive, mentorat d'un senior.",{"type":29,"tag":37,"props":15121,"children":15122},{},[15123,15128,15130,15134],{"type":29,"tag":65,"props":15124,"children":15125},{},[15126],{"type":35,"value":15127},"Pour la difficulté de motivation :",{"type":35,"value":15129}," ouvrir la discussion sur les aspirations. Y a-t-il une direction différente à explorer ? Un projet plus stimulant dans l'organisation ? Une évolution de rôle possible ? Si ce n'est pas encore fait, c'est le moment d'anticiper l'",{"type":29,"tag":48,"props":15131,"children":15132},{"href":2024},[15133],{"type":35,"value":2027},{"type":35,"value":15135}," plutôt que d'attendre la date prévue.",{"type":29,"tag":37,"props":15137,"children":15138},{},[15139,15144],{"type":29,"tag":65,"props":15140,"children":15141},{},[15142],{"type":35,"value":15143},"Pour la difficulté personnelle :",{"type":35,"value":15145}," proposer un support adapté. Flexibilité des horaires, réduction temporaire de la charge, accès à l'assistance psychologique si disponible. Sans chercher à connaître les détails personnels : je propose le cadre, pas l'intrusion.",{"type":29,"tag":37,"props":15147,"children":15148},{},[15149,15154],{"type":29,"tag":65,"props":15150,"children":15151},{},[15152],{"type":35,"value":15153},"Le plan contient systématiquement :",{"type":35,"value":15155}," 2 à 3 actions concrètes sur 30 jours, une métrique de succès visible, et une date de point d'étape à 15 jours. Je l'écris et je le partage avec le développeur, pas dans un email formel, mais dans le compte-rendu du 1-on-1.",{"type":29,"tag":76,"props":15157,"children":15158},{},[],{"type":29,"tag":80,"props":15160,"children":15162},{"id":15161},"le-suivi-hebdomadaire-et-le-seuil-de-décision",[15163],{"type":35,"value":15164},"Le suivi hebdomadaire et le seuil de décision",{"type":29,"tag":37,"props":15166,"children":15167},{},[15168],{"type":35,"value":15169},"Suivi hebdomadaire en 1-on-1 court de 15 minutes pendant 4 semaines. Mes trois questions :",{"type":29,"tag":1080,"props":15171,"children":15172},{},[15173,15178,15183],{"type":29,"tag":1084,"props":15174,"children":15175},{},[15176],{"type":35,"value":15177},"Qu'est-ce qui a avancé cette semaine ?",{"type":29,"tag":1084,"props":15179,"children":15180},{},[15181],{"type":35,"value":15182},"Qu'est-ce qui reste difficile ?",{"type":29,"tag":1084,"props":15184,"children":15185},{},[15186],{"type":35,"value":15187},"L'équipe ou moi avons-nous tenu nos engagements ?",{"type":29,"tag":37,"props":15189,"children":15190},{},[15191],{"type":35,"value":15192},"À 30 jours, évaluation honnête :",{"type":29,"tag":1080,"props":15194,"children":15195},{},[15196,15206,15216],{"type":29,"tag":1084,"props":15197,"children":15198},{},[15199,15204],{"type":29,"tag":65,"props":15200,"children":15201},{},[15202],{"type":35,"value":15203},"Amélioration visible",{"type":35,"value":15205}," → continuer le support, réduire la fréquence des check-ins",{"type":29,"tag":1084,"props":15207,"children":15208},{},[15209,15214],{"type":29,"tag":65,"props":15210,"children":15211},{},[15212],{"type":35,"value":15213},"Plateau",{"type":35,"value":15215}," → approfondir le diagnostic, ajuster le plan",{"type":29,"tag":1084,"props":15217,"children":15218},{},[15219,15224],{"type":29,"tag":65,"props":15220,"children":15221},{},[15222],{"type":35,"value":15223},"Dégradation",{"type":35,"value":15225}," → conversation plus directe sur les conséquences possibles et les décisions à prendre",{"type":29,"tag":37,"props":15227,"children":15228},{},[15229],{"type":35,"value":15230},"Quatre semaines d'investissement en management intensif coûtent bien moins que les 65 000 à 130 000€ d'un remplacement. Le calcul est simple. L'inaction est rarement neutre : elle est presque toujours la décision la plus coûteuse.",{"type":29,"tag":76,"props":15232,"children":15233},{},[],{"type":29,"tag":80,"props":15235,"children":15237},{"id":15236},"faq-sur-la-gestion-dun-développeur-en-difficulté",[15238],{"type":35,"value":15239},"FAQ sur la gestion d'un développeur en difficulté",{"type":29,"tag":381,"props":15241,"children":15242},{},[15243,15248],{"type":29,"tag":385,"props":15244,"children":15245},{},[15246],{"type":35,"value":15247},"Quand faut-il impliquer les RH dans ce processus ?",{"type":29,"tag":37,"props":15249,"children":15250},{},[15251],{"type":35,"value":15252},"Dès que la situation pourrait mener à une procédure disciplinaire ou un licenciement, les RH doivent être impliquées. En pratique, pour une difficulté de performance (catégories 1 à 3), je gère seul les 4 premières semaines. Si la situation ne s'améliore pas à J+30, ou si la difficulté personnelle (catégorie 4) dépasse mes capacités à l'accompagner, les RH entrent en copie.",{"type":29,"tag":381,"props":15254,"children":15255},{},[15256,15261],{"type":29,"tag":385,"props":15257,"children":15258},{},[15259],{"type":35,"value":15260},"Comment gérer la situation si le développeur nie avoir un problème ?",{"type":29,"tag":37,"props":15262,"children":15263},{},[15264,15266,15271],{"type":35,"value":15265},"Je respecte le déni initial : c'est une réaction normale. Je reformule les faits observés sans accusation et laisse la conversation ouverte. \"Je comprends que tu ne vois pas les choses de la même façon. Les faits que j'ai observés sont ",{"type":29,"tag":901,"props":15267,"children":15268},{},[15269],{"type":35,"value":15270},"liste",{"type":35,"value":15272},". Si tu veux qu'on en discute dans quelques jours, ma porte est ouverte.\" Je planifie un suivi à 1 semaine. Si le déni persiste face à des faits répétés et documentés, c'est un signal que la difficulté est plus profonde.",{"type":29,"tag":381,"props":15274,"children":15275},{},[15276,15281],{"type":29,"tag":385,"props":15277,"children":15278},{},[15279],{"type":35,"value":15280},"Quelle est la différence entre un développeur en difficulté et un développeur qui manque de motivation ?",{"type":29,"tag":37,"props":15282,"children":15283},{},[15284],{"type":35,"value":15285},"La motivation est souvent une conséquence, pas une cause. Un développeur démotivé est généralement un développeur dans une difficulté contextuelle ou de sens non-adressée. La question que je pose : \"Il y a 12 mois, était-il motivé ?\" Si oui, chercher ce qui a changé. Si non depuis le début, c'est peut-être un problème de recrutement (un mauvais match entre la personne et le rôle) plutôt qu'un problème de management.",{"type":29,"tag":381,"props":15287,"children":15288},{},[15289,15294],{"type":29,"tag":385,"props":15290,"children":15291},{},[15292],{"type":35,"value":15293},"Comment gérer la situation vis-à-vis du reste de l'équipe ?",{"type":29,"tag":37,"props":15295,"children":15296},{},[15297],{"type":35,"value":15298},"Confidentialité absolue sur le contenu des discussions. L'équipe peut percevoir une différence de traitement (moins de stories assignées, plus de check-ins). Si elle pose des questions, \"nous gérons un sujet individuel\" est suffisant. J'évite de couvrir les défaillances du développeur en difficulté face à l'équipe (ça génère de la frustration chez les autres) tout en évitant de l'exposer publiquement.",{"type":29,"tag":381,"props":15300,"children":15301},{},[15302,15307],{"type":29,"tag":385,"props":15303,"children":15304},{},[15305],{"type":35,"value":15306},"Que faire si les 30 jours ne suffisent pas et que la situation ne s'améliore pas ?",{"type":29,"tag":37,"props":15308,"children":15309},{},[15310],{"type":35,"value":15311},"Ne pas confondre difficulté temporaire et inadéquation structurelle. Un développeur qui est en difficulté depuis 18 mois malgré plusieurs plans d'action peut avoir atteint son niveau de compétence maximum dans le rôle actuel : c'est ce que le Principe de Peter décrit. Dans ce cas, la solution n'est pas plus de support. C'est une discussion honnête sur un rôle mieux adapté, en interne ou en externe. Cette conversation est difficile mais elle est plus respectueuse que de laisser la situation se dégrader indéfiniment.",{"type":29,"tag":76,"props":15313,"children":15314},{},[],{"type":29,"tag":176,"props":15316,"children":15317},{"cta":1243,"href":1244,"title":454,"type":455},[15318],{"type":29,"tag":37,"props":15319,"children":15320},{},[15321],{"type":35,"value":15322},"L'Engineering Maturity Self-Assessment couvre le domaine People & Culture : évaluez la maturité de vos pratiques de détection et d'accompagnement des personnes en difficulté. Identifiez les leviers d'action avant que les signaux faibles ne deviennent des départs.",{"title":8,"searchDepth":463,"depth":463,"links":15324},[15325,15326,15327,15328,15329,15330],{"id":14820,"depth":463,"text":14823},{"id":14913,"depth":463,"text":14916},{"id":14976,"depth":463,"text":14979},{"id":15084,"depth":463,"text":15087},{"id":15161,"depth":463,"text":15164},{"id":15236,"depth":463,"text":15239},"content:fr:management:gerer-developpeur-en-difficulte.md","fr/management/gerer-developpeur-en-difficulte.md","fr/management/gerer-developpeur-en-difficulte",{"_path":2484,"_dir":2118,"_draft":7,"_partial":7,"_locale":8,"title":15335,"description":15336,"id":6233,"date":15337,"listed":13,"nocomments":7,"hidden":7,"categories":15338,"tags":15339,"--cover":15343,"readingTime":15344,"body":15348,"_type":476,"_id":16201,"_source":478,"_file":16202,"_stem":16203,"_extension":481},"Tester du code généré par l'IA : la checklist en 12 points","Le code généré par l'IA passe les tests syntaxiques et rate les tests de logique métier. Une checklist pour valider du code IA avant de le merger.","2026-02-25",[2118],[15340,15341,2128,15342],"Tests","Code IA","Checklist","covers/articles/tester-code-ia-checklist.jpg",{"text":497,"minutes":15345,"time":15346,"words":15347},7.33,439800,1466,{"type":26,"children":15349,"toc":16193},[15350,15355,15360,15365,15380,15383,15389,15394,15406,15409,15415,15423,15428,15433,15441,15446,15469,15477,15482,15490,15495,15504,15507,15513,15521,15526,15534,15539,15625,15633,15638,15646,15651,15677,15680,15686,15694,15699,15929,15937,15942,15950,15955,15963,15971,15976,15979,15985,16002,16012,16022,16025,16104,16107,16113,16126,16139,16152,16165,16178,16181,16189],{"type":29,"tag":30,"props":15351,"children":15353},{"id":15352},"tester-du-code-généré-par-lia-la-checklist-en-12-points",[15354],{"type":35,"value":15335},{"type":29,"tag":37,"props":15356,"children":15357},{},[15358],{"type":35,"value":15359},"Dans une équipe que j'accompagnais chez un assureur, un développeur avait utilisé Claude pour implémenter une règle de calcul de cotisation. Le code compilait. Les tests unitaires passaient, des tests également générés par l'IA. La PR a été mergée. Deux semaines plus tard, en recette, le client a trouvé que les cotisations de certains profils d'assurés étaient calculées avec un taux incorrect. La règle métier avait une condition que le LLM avait simplifiée sans le dire.",{"type":29,"tag":37,"props":15361,"children":15362},{},[15363],{"type":35,"value":15364},"Ce n'était pas un bug de code. C'était un bug de jugement métier que l'IA ne pouvait pas avoir.",{"type":29,"tag":37,"props":15366,"children":15367},{},[15368],{"type":29,"tag":65,"props":15369,"children":15370},{},[15371,15373,15378],{"type":35,"value":15372},"Le code généré par un LLM compile, passe les tests de type, et peut même faire passer une suite de tests unitaires, tout en étant incorrect sur la logique métier. C'est la caractéristique la plus trompeuse du code IA-assisté : les ",{"type":29,"tag":48,"props":15374,"children":15375},{"href":2185},[15376],{"type":35,"value":15377},"vulnérabilités de sécurité spécifiques aux LLMs",{"type":35,"value":15379}," s'y cachent de la même façon : il a l'air juste avant d'être évalué en profondeur.",{"type":29,"tag":76,"props":15381,"children":15382},{},[],{"type":29,"tag":80,"props":15384,"children":15386},{"id":15385},"pourquoi-lia-se-trompe-sur-le-métier",[15387],{"type":35,"value":15388},"Pourquoi l'IA se trompe sur le métier",{"type":29,"tag":37,"props":15390,"children":15391},{},[15392],{"type":35,"value":15393},"Un LLM génère du code plausible basé sur des patterns statistiques. Il ne comprend pas les règles métier de votre domaine spécifique. Il génère du code qui ressemble à du code qui traite des commandes, des paiements, ou des utilisateurs, mais pas du code qui traite vos commandes, selon vos règles métier, dans votre contexte spécifique.",{"type":29,"tag":37,"props":15395,"children":15396},{},[15397,15399,15404],{"type":35,"value":15398},"La conséquence est directe : le code IA-généré peut être techniquement impeccable (pas d'injection, pas de null pointer, bonne gestion des erreurs) et fonctionnellement incorrect (mauvaise règle de calcul, cas d'utilisation manqué, contrainte business ignorée). La recherche de ",{"type":29,"tag":65,"props":15400,"children":15401},{},[15402],{"type":35,"value":15403},"NYU (2023)",{"type":35,"value":15405}," sur le code IA-assisté confirme que les développeurs sous-estiment systématiquement les erreurs de logique dans le code généré, précisément parce que le code \"a l'air propre\".",{"type":29,"tag":76,"props":15407,"children":15408},{},[],{"type":29,"tag":80,"props":15410,"children":15412},{"id":15411},"checklist-partie-1-correction-logique-et-cas-limites-points-1-4",[15413],{"type":35,"value":15414},"Checklist partie 1 : Correction logique et cas limites (points 1-4)",{"type":29,"tag":37,"props":15416,"children":15417},{},[15418],{"type":29,"tag":65,"props":15419,"children":15420},{},[15421],{"type":35,"value":15422},"Point 1 : La logique métier correspond aux règles de votre domaine",{"type":29,"tag":37,"props":15424,"children":15425},{},[15426],{"type":35,"value":15427},"Ne pas se fier au fait que le code \"a l'air logique\". Vérifier explicitement que chaque règle métier implémentée correspond exactement à la spécification. Les LLMs ont tendance à implémenter des règles \"standard\" qui peuvent différer des règles spécifiques de votre domaine.",{"type":29,"tag":37,"props":15429,"children":15430},{},[15431],{"type":35,"value":15432},"Exemple concret : un LLM peut implémenter un calcul de TVA avec les taux standards sans tenir compte des règles spéciales de votre secteur ou des articles exonérés.",{"type":29,"tag":37,"props":15434,"children":15435},{},[15436],{"type":29,"tag":65,"props":15437,"children":15438},{},[15439],{"type":35,"value":15440},"Point 2 : Les cas limites sont couverts",{"type":29,"tag":37,"props":15442,"children":15443},{},[15444],{"type":35,"value":15445},"Vérifiez explicitement :",{"type":29,"tag":1080,"props":15447,"children":15448},{},[15449,15454,15459,15464],{"type":29,"tag":1084,"props":15450,"children":15451},{},[15452],{"type":35,"value":15453},"Que se passe-t-il si la collection est vide ?",{"type":29,"tag":1084,"props":15455,"children":15456},{},[15457],{"type":35,"value":15458},"Que se passe-t-il avec des valeurs nulles ou undefined ?",{"type":29,"tag":1084,"props":15460,"children":15461},{},[15462],{"type":35,"value":15463},"Que se passe-t-il avec les valeurs extrêmes (0, négatif, très grand nombre) ?",{"type":29,"tag":1084,"props":15465,"children":15466},{},[15467],{"type":35,"value":15468},"Que se passe-t-il si une opération concurrente modifie l'état entre deux étapes ?",{"type":29,"tag":37,"props":15470,"children":15471},{},[15472],{"type":29,"tag":65,"props":15473,"children":15474},{},[15475],{"type":35,"value":15476},"Point 3 : Les conditions métier sont correctement combinées",{"type":29,"tag":37,"props":15478,"children":15479},{},[15480],{"type":35,"value":15481},"Les LLMs ont tendance à simplifier les conditions logiques complexes. Une règle business comme \"eligible si (A ET B) OU (C ET PAS D)\" peut être simplifiée en \"eligible si A ET B OU C\", ce qui produit des résultats incorrects pour les cas qui impliquent D. C'est exactement le type d'erreur que j'ai vu en production.",{"type":29,"tag":37,"props":15483,"children":15484},{},[15485],{"type":29,"tag":65,"props":15486,"children":15487},{},[15488],{"type":35,"value":15489},"Point 4 : Le comportement en cas d'erreur est métier-correct",{"type":29,"tag":37,"props":15491,"children":15492},{},[15493],{"type":35,"value":15494},"Le code généré peut gérer les erreurs techniques correctement (try/catch, retours d'erreur) tout en gérant incorrectement les erreurs métier. Vérifiez : quelle est la réponse attendue quand une règle métier est violée ? Est-ce une exception ? Un résultat partiel ? Un état spécifique ?",{"type":29,"tag":176,"props":15496,"children":15498},{"cta":178,"href":179,"title":15497,"type":181},"Votre équipe merge du code IA-assisté sans processus de validation adapté ?",[15499],{"type":29,"tag":37,"props":15500,"children":15501},{},[15502],{"type":35,"value":15503},"Vous adoptez l'IA mais vous n'avez pas encore adapté vos pratiques de test et de review à ses angles morts spécifiques. Un bug de logique métier en production coûte 10 à 100 fois plus cher à corriger qu'un bug détecté en review. En 30 minutes, on définit les pratiques adaptées à votre contexte.",{"type":29,"tag":76,"props":15505,"children":15506},{},[],{"type":29,"tag":80,"props":15508,"children":15510},{"id":15509},"checklist-partie-2-sécurité-et-gestion-des-erreurs-points-5-8",[15511],{"type":35,"value":15512},"Checklist partie 2 : Sécurité et gestion des erreurs (points 5-8)",{"type":29,"tag":37,"props":15514,"children":15515},{},[15516],{"type":29,"tag":65,"props":15517,"children":15518},{},[15519],{"type":35,"value":15520},"Point 5 : Les inputs utilisateurs sont validés et sanitisés",{"type":29,"tag":37,"props":15522,"children":15523},{},[15524],{"type":35,"value":15525},"Vérifiez systématiquement que tout input provenant de l'extérieur (utilisateur, API, message queue) est validé avant d'être utilisé. Les LLMs oublient fréquemment la validation des types, des ranges, et des formats.",{"type":29,"tag":37,"props":15527,"children":15528},{},[15529],{"type":29,"tag":65,"props":15530,"children":15531},{},[15532],{"type":35,"value":15533},"Point 6 : Aucune injection n'est possible",{"type":29,"tag":37,"props":15535,"children":15536},{},[15537],{"type":35,"value":15538},"Pour tout code qui génère des requêtes SQL, des commandes shell, ou des requêtes LDAP : vérifiez que les valeurs dynamiques sont passées par des paramètres, jamais interpolées directement dans des strings.",{"type":29,"tag":651,"props":15540,"children":15542},{"code":15541,"language":2202,"meta":8,"className":2200,"style":8},"# Vérification rapide : chercher les patterns f-string dans les requêtes\nquery = f\"SELECT * FROM users WHERE id = {user_id}\"  # ❌ injection possible\nquery = \"SELECT * FROM users WHERE id = %s\"           # ✅\n",[15543],{"type":29,"tag":565,"props":15544,"children":15545},{"__ignoreMap":8},[15546,15554,15596],{"type":29,"tag":901,"props":15547,"children":15548},{"class":903,"line":904},[15549],{"type":29,"tag":901,"props":15550,"children":15551},{"style":908},[15552],{"type":35,"value":15553},"# Vérification rapide : chercher les patterns f-string dans les requêtes\n",{"type":29,"tag":901,"props":15555,"children":15556},{"class":903,"line":463},[15557,15561,15565,15569,15574,15578,15583,15587,15591],{"type":29,"tag":901,"props":15558,"children":15559},{"style":923},[15560],{"type":35,"value":2222},{"type":29,"tag":901,"props":15562,"children":15563},{"style":947},[15564],{"type":35,"value":2227},{"type":29,"tag":901,"props":15566,"children":15567},{"style":2230},[15568],{"type":35,"value":2233},{"type":29,"tag":901,"props":15570,"children":15571},{"style":2236},[15572],{"type":35,"value":15573},"\"SELECT * FROM users WHERE id = ",{"type":29,"tag":901,"props":15575,"children":15576},{"style":2242},[15577],{"type":35,"value":2245},{"type":29,"tag":901,"props":15579,"children":15580},{"style":923},[15581],{"type":35,"value":15582},"user_id",{"type":29,"tag":901,"props":15584,"children":15585},{"style":2242},[15586],{"type":35,"value":2255},{"type":29,"tag":901,"props":15588,"children":15589},{"style":2236},[15590],{"type":35,"value":5480},{"type":29,"tag":901,"props":15592,"children":15593},{"style":908},[15594],{"type":35,"value":15595},"  # ❌ injection possible\n",{"type":29,"tag":901,"props":15597,"children":15598},{"class":903,"line":469},[15599,15603,15607,15612,15616,15620],{"type":29,"tag":901,"props":15600,"children":15601},{"style":923},[15602],{"type":35,"value":2222},{"type":29,"tag":901,"props":15604,"children":15605},{"style":947},[15606],{"type":35,"value":2227},{"type":29,"tag":901,"props":15608,"children":15609},{"style":2236},[15610],{"type":35,"value":15611}," \"SELECT * FROM users WHERE id = ",{"type":29,"tag":901,"props":15613,"children":15614},{"style":2242},[15615],{"type":35,"value":2294},{"type":29,"tag":901,"props":15617,"children":15618},{"style":2236},[15619],{"type":35,"value":5480},{"type":29,"tag":901,"props":15621,"children":15622},{"style":908},[15623],{"type":35,"value":15624},"           # ✅\n",{"type":29,"tag":37,"props":15626,"children":15627},{},[15628],{"type":29,"tag":65,"props":15629,"children":15630},{},[15631],{"type":35,"value":15632},"Point 7 : Les secrets ne sont pas hardcodés",{"type":29,"tag":37,"props":15634,"children":15635},{},[15636],{"type":35,"value":15637},"Recherchez dans le code généré : passwords, API keys, tokens, connection strings. Les LLMs les hardcodent fréquemment dans les exemples de code et les configurations, car c'est le pattern dominant dans le code d'exemple sur lequel ils ont été entraînés.",{"type":29,"tag":37,"props":15639,"children":15640},{},[15641],{"type":29,"tag":65,"props":15642,"children":15643},{},[15644],{"type":35,"value":15645},"Point 8 : La gestion des exceptions est appropriée",{"type":29,"tag":37,"props":15647,"children":15648},{},[15649],{"type":35,"value":15650},"Vérifiez que :",{"type":29,"tag":1080,"props":15652,"children":15653},{},[15654,15667,15672],{"type":29,"tag":1084,"props":15655,"children":15656},{},[15657,15659,15665],{"type":35,"value":15658},"Les exceptions sont capturées au bon niveau (pas de ",{"type":29,"tag":565,"props":15660,"children":15662},{"className":15661},[],[15663],{"type":35,"value":15664},"catch(Exception)",{"type":35,"value":15666}," généralisé qui avale les erreurs)",{"type":29,"tag":1084,"props":15668,"children":15669},{},[15670],{"type":35,"value":15671},"Les exceptions techniques ne leakent pas de détails d'implémentation dans les réponses API",{"type":29,"tag":1084,"props":15673,"children":15674},{},[15675],{"type":35,"value":15676},"Les ressources (connexions, fichiers, transactions) sont correctement fermées en cas d'exception",{"type":29,"tag":76,"props":15678,"children":15679},{},[],{"type":29,"tag":80,"props":15681,"children":15683},{"id":15682},"checklist-partie-3-performance-lisibilité-tests-points-9-12",[15684],{"type":35,"value":15685},"Checklist partie 3 : Performance, lisibilité, tests (points 9-12)",{"type":29,"tag":37,"props":15687,"children":15688},{},[15689],{"type":29,"tag":65,"props":15690,"children":15691},{},[15692],{"type":35,"value":15693},"Point 9 : Pas de N+1 query",{"type":29,"tag":37,"props":15695,"children":15696},{},[15697],{"type":35,"value":15698},"Le problème de N+1 est l'un des patterns de performance les plus fréquemment générés par les LLMs : une query dans une boucle.",{"type":29,"tag":651,"props":15700,"children":15702},{"code":15701,"language":2202,"meta":8,"className":2200,"style":8},"# ❌ Pattern N+1 généré fréquemment\nfor order in orders:\n    customer = db.get_customer(order.customer_id)  # 1 query par order\n    process(order, customer)\n\n# ✅ Eager loading\ncustomer_ids = [o.customer_id for o in orders]\ncustomers = db.get_customers_by_ids(customer_ids)  # 1 seule query\n",[15703],{"type":29,"tag":565,"props":15704,"children":15705},{"__ignoreMap":8},[15706,15714,15739,15791,15820,15827,15835,15886],{"type":29,"tag":901,"props":15707,"children":15708},{"class":903,"line":904},[15709],{"type":29,"tag":901,"props":15710,"children":15711},{"style":908},[15712],{"type":35,"value":15713},"# ❌ Pattern N+1 généré fréquemment\n",{"type":29,"tag":901,"props":15715,"children":15716},{"class":903,"line":463},[15717,15722,15726,15730,15735],{"type":29,"tag":901,"props":15718,"children":15719},{"style":917},[15720],{"type":35,"value":15721},"for",{"type":29,"tag":901,"props":15723,"children":15724},{"style":923},[15725],{"type":35,"value":9181},{"type":29,"tag":901,"props":15727,"children":15728},{"style":917},[15729],{"type":35,"value":7164},{"type":29,"tag":901,"props":15731,"children":15732},{"style":923},[15733],{"type":35,"value":15734}," orders",{"type":29,"tag":901,"props":15736,"children":15737},{"style":5185},[15738],{"type":35,"value":5188},{"type":29,"tag":901,"props":15740,"children":15741},{"class":903,"line":469},[15742,15747,15751,15756,15760,15765,15769,15773,15777,15782,15786],{"type":29,"tag":901,"props":15743,"children":15744},{"style":923},[15745],{"type":35,"value":15746},"    customer ",{"type":29,"tag":901,"props":15748,"children":15749},{"style":947},[15750],{"type":35,"value":2227},{"type":29,"tag":901,"props":15752,"children":15753},{"style":923},[15754],{"type":35,"value":15755}," db",{"type":29,"tag":901,"props":15757,"children":15758},{"style":5185},[15759],{"type":35,"value":342},{"type":29,"tag":901,"props":15761,"children":15762},{"style":5242},[15763],{"type":35,"value":15764},"get_customer",{"type":29,"tag":901,"props":15766,"children":15767},{"style":5185},[15768],{"type":35,"value":3080},{"type":29,"tag":901,"props":15770,"children":15771},{"style":923},[15772],{"type":35,"value":9324},{"type":29,"tag":901,"props":15774,"children":15775},{"style":5185},[15776],{"type":35,"value":342},{"type":29,"tag":901,"props":15778,"children":15779},{"style":923},[15780],{"type":35,"value":15781},"customer_id",{"type":29,"tag":901,"props":15783,"children":15784},{"style":5185},[15785],{"type":35,"value":2881},{"type":29,"tag":901,"props":15787,"children":15788},{"style":908},[15789],{"type":35,"value":15790},"  # 1 query par order\n",{"type":29,"tag":901,"props":15792,"children":15793},{"class":903,"line":968},[15794,15799,15803,15807,15811,15816],{"type":29,"tag":901,"props":15795,"children":15796},{"style":5242},[15797],{"type":35,"value":15798},"    process",{"type":29,"tag":901,"props":15800,"children":15801},{"style":5185},[15802],{"type":35,"value":3080},{"type":29,"tag":901,"props":15804,"children":15805},{"style":923},[15806],{"type":35,"value":9324},{"type":29,"tag":901,"props":15808,"children":15809},{"style":5185},[15810],{"type":35,"value":3663},{"type":29,"tag":901,"props":15812,"children":15813},{"style":923},[15814],{"type":35,"value":15815}," customer",{"type":29,"tag":901,"props":15817,"children":15818},{"style":5185},[15819],{"type":35,"value":5437},{"type":29,"tag":901,"props":15821,"children":15822},{"class":903,"line":977},[15823],{"type":29,"tag":901,"props":15824,"children":15825},{"emptyLinePlaceholder":13},[15826],{"type":35,"value":974},{"type":29,"tag":901,"props":15828,"children":15829},{"class":903,"line":986},[15830],{"type":29,"tag":901,"props":15831,"children":15832},{"style":908},[15833],{"type":35,"value":15834},"# ✅ Eager loading\n",{"type":29,"tag":901,"props":15836,"children":15837},{"class":903,"line":1007},[15838,15843,15847,15851,15855,15859,15864,15868,15873,15877,15881],{"type":29,"tag":901,"props":15839,"children":15840},{"style":923},[15841],{"type":35,"value":15842},"customer_ids ",{"type":29,"tag":901,"props":15844,"children":15845},{"style":947},[15846],{"type":35,"value":2227},{"type":29,"tag":901,"props":15848,"children":15849},{"style":5185},[15850],{"type":35,"value":7129},{"type":29,"tag":901,"props":15852,"children":15853},{"style":923},[15854],{"type":35,"value":2800},{"type":29,"tag":901,"props":15856,"children":15857},{"style":5185},[15858],{"type":35,"value":342},{"type":29,"tag":901,"props":15860,"children":15861},{"style":923},[15862],{"type":35,"value":15863},"customer_id ",{"type":29,"tag":901,"props":15865,"children":15866},{"style":917},[15867],{"type":35,"value":15721},{"type":29,"tag":901,"props":15869,"children":15870},{"style":923},[15871],{"type":35,"value":15872}," o ",{"type":29,"tag":901,"props":15874,"children":15875},{"style":917},[15876],{"type":35,"value":7164},{"type":29,"tag":901,"props":15878,"children":15879},{"style":923},[15880],{"type":35,"value":15734},{"type":29,"tag":901,"props":15882,"children":15883},{"style":5185},[15884],{"type":35,"value":15885},"]\n",{"type":29,"tag":901,"props":15887,"children":15888},{"class":903,"line":5354},[15889,15894,15898,15902,15906,15911,15915,15920,15924],{"type":29,"tag":901,"props":15890,"children":15891},{"style":923},[15892],{"type":35,"value":15893},"customers ",{"type":29,"tag":901,"props":15895,"children":15896},{"style":947},[15897],{"type":35,"value":2227},{"type":29,"tag":901,"props":15899,"children":15900},{"style":923},[15901],{"type":35,"value":15755},{"type":29,"tag":901,"props":15903,"children":15904},{"style":5185},[15905],{"type":35,"value":342},{"type":29,"tag":901,"props":15907,"children":15908},{"style":5242},[15909],{"type":35,"value":15910},"get_customers_by_ids",{"type":29,"tag":901,"props":15912,"children":15913},{"style":5185},[15914],{"type":35,"value":3080},{"type":29,"tag":901,"props":15916,"children":15917},{"style":923},[15918],{"type":35,"value":15919},"customer_ids",{"type":29,"tag":901,"props":15921,"children":15922},{"style":5185},[15923],{"type":35,"value":2881},{"type":29,"tag":901,"props":15925,"children":15926},{"style":908},[15927],{"type":35,"value":15928},"  # 1 seule query\n",{"type":29,"tag":37,"props":15930,"children":15931},{},[15932],{"type":29,"tag":65,"props":15933,"children":15934},{},[15935],{"type":35,"value":15936},"Point 10 : La complexité est acceptable",{"type":29,"tag":37,"props":15938,"children":15939},{},[15940],{"type":35,"value":15941},"Calculez mentalement (ou avec un outil) la complexité cyclomatique du code généré. Les LLMs peuvent générer des fonctions avec des imbrications de conditions très profondes difficiles à maintenir. Seuil d'alerte : complexité cyclomatique supérieure à 10.",{"type":29,"tag":37,"props":15943,"children":15944},{},[15945],{"type":29,"tag":65,"props":15946,"children":15947},{},[15948],{"type":35,"value":15949},"Point 11 : Le code est testé avec des tests indépendants",{"type":29,"tag":37,"props":15951,"children":15952},{},[15953],{"type":35,"value":15954},"Ne pas se contenter des tests générés par le LLM pour valider le code du LLM. Écrivez des tests indépendants, particulièrement pour les branches d'erreur et les cas limites identifiés au point 2.",{"type":29,"tag":651,"props":15956,"children":15958},{"code":15957},"Règle : au moins 1 test par branche métier critique\nRègle : au moins 1 test pour chaque cas d'erreur explicitement géré\n",[15959],{"type":29,"tag":565,"props":15960,"children":15961},{"__ignoreMap":8},[15962],{"type":35,"value":15957},{"type":29,"tag":37,"props":15964,"children":15965},{},[15966],{"type":29,"tag":65,"props":15967,"children":15968},{},[15969],{"type":35,"value":15970},"Point 12 : Le code est compréhensible par un humain sans explication",{"type":29,"tag":37,"props":15972,"children":15973},{},[15974],{"type":35,"value":15975},"Si vous devez lire le code 3 fois pour comprendre ce qu'il fait, le code est trop complexe. Les LLMs peuvent générer du code \"intelligent\" avec des patterns avancés ou des one-liners obscurs qui réduisent la lisibilité. La lisibilité prévaut sur le \"clever code\". Toujours.",{"type":29,"tag":76,"props":15977,"children":15978},{},[],{"type":29,"tag":80,"props":15980,"children":15982},{"id":15981},"comment-intégrer-la-checklist-dans-le-workflow",[15983],{"type":35,"value":15984},"Comment intégrer la checklist dans le workflow",{"type":29,"tag":37,"props":15986,"children":15987},{},[15988,15993,15995,16000],{"type":29,"tag":65,"props":15989,"children":15990},{},[15991],{"type":35,"value":15992},"Option A : Dans le template de PR :",{"type":35,"value":15994}," ajouter la checklist comme section \"AI-generated code review\" dans le template de PR. Combinez-la avec un ",{"type":29,"tag":48,"props":15996,"children":15997},{"href":337},[15998],{"type":35,"value":15999},"outil d'analyse statique",{"type":35,"value":16001}," pour automatiser les vérifications de sécurité. Le reviewer coche les 12 points pour tout code généré par IA.",{"type":29,"tag":37,"props":16003,"children":16004},{},[16005,16010],{"type":29,"tag":65,"props":16006,"children":16007},{},[16008],{"type":35,"value":16009},"Option B : Dans le template de Story :",{"type":35,"value":16011}," pour les stories développées majoritairement avec assistance IA, ajouter la checklist comme critère de DoD. Le développeur self-review avant de créer la PR.",{"type":29,"tag":37,"props":16013,"children":16014},{},[16015,16020],{"type":29,"tag":65,"props":16016,"children":16017},{},[16018],{"type":35,"value":16019},"Option C : Dans les 1-on-1 :",{"type":35,"value":16021}," utiliser les 12 points comme framework de discussion avec les développeurs qui adoptent l'IA. Identifier les patterns de lacune récurrents pour cibler la formation.",{"type":29,"tag":76,"props":16023,"children":16024},{},[],{"type":29,"tag":714,"props":16026,"children":16027},{},[16028,16049],{"type":29,"tag":718,"props":16029,"children":16030},{},[16031],{"type":29,"tag":722,"props":16032,"children":16033},{},[16034,16039,16044],{"type":29,"tag":726,"props":16035,"children":16036},{},[16037],{"type":35,"value":16038},"Partie",{"type":29,"tag":726,"props":16040,"children":16041},{},[16042],{"type":35,"value":16043},"Points",{"type":29,"tag":726,"props":16045,"children":16046},{},[16047],{"type":35,"value":16048},"Focus",{"type":29,"tag":742,"props":16050,"children":16051},{},[16052,16069,16087],{"type":29,"tag":722,"props":16053,"children":16054},{},[16055,16059,16064],{"type":29,"tag":749,"props":16056,"children":16057},{},[16058],{"type":35,"value":2524},{"type":29,"tag":749,"props":16060,"children":16061},{},[16062],{"type":35,"value":16063},"1-4",{"type":29,"tag":749,"props":16065,"children":16066},{},[16067],{"type":35,"value":16068},"Règles, cas limites, conditions, erreurs métier",{"type":29,"tag":722,"props":16070,"children":16071},{},[16072,16077,16082],{"type":29,"tag":749,"props":16073,"children":16074},{},[16075],{"type":35,"value":16076},"Sécurité",{"type":29,"tag":749,"props":16078,"children":16079},{},[16080],{"type":35,"value":16081},"5-8",{"type":29,"tag":749,"props":16083,"children":16084},{},[16085],{"type":35,"value":16086},"Validation, injections, secrets, exceptions",{"type":29,"tag":722,"props":16088,"children":16089},{},[16090,16094,16099],{"type":29,"tag":749,"props":16091,"children":16092},{},[16093],{"type":35,"value":2128},{"type":29,"tag":749,"props":16095,"children":16096},{},[16097],{"type":35,"value":16098},"9-12",{"type":29,"tag":749,"props":16100,"children":16101},{},[16102],{"type":35,"value":16103},"Performance, complexité, tests, lisibilité",{"type":29,"tag":76,"props":16105,"children":16106},{},[],{"type":29,"tag":80,"props":16108,"children":16110},{"id":16109},"faq-sur-le-test-du-code-ia-généré",[16111],{"type":35,"value":16112},"FAQ sur le test du code IA-généré",{"type":29,"tag":381,"props":16114,"children":16115},{},[16116,16121],{"type":29,"tag":385,"props":16117,"children":16118},{},[16119],{"type":35,"value":16120},"1. Faut-il appliquer la checklist complète à tout le code IA-assisté ?",{"type":29,"tag":37,"props":16122,"children":16123},{},[16124],{"type":35,"value":16125},"Non. Les points 6 (injection), 7 (secrets), et 11 (tests) s'appliquent à tout le code IA-assisté sans exception. Les autres points s'appliquent en fonction du contexte : les points 1-4 (logique métier) sont critiques pour le code qui implémente des règles business ; les points 9-10 (performance) sont importants pour le code dans les chemins chauds.",{"type":29,"tag":381,"props":16127,"children":16128},{},[16129,16134],{"type":29,"tag":385,"props":16130,"children":16131},{},[16132],{"type":35,"value":16133},"2. Comment former rapidement une équipe à utiliser cette checklist ?",{"type":29,"tag":37,"props":16135,"children":16136},{},[16137],{"type":35,"value":16138},"Session de 2 heures avec des exemples réels de code IA-généré dans votre domaine. Pour chaque exemple, demandez à l'équipe d'identifier les problèmes sans la checklist d'abord, puis avec. La différence entre les deux passages révèle les angles morts de l'équipe, et ce sont précisément ces angles morts qu'il faut adresser en formation.",{"type":29,"tag":381,"props":16140,"children":16141},{},[16142,16147],{"type":29,"tag":385,"props":16143,"children":16144},{},[16145],{"type":35,"value":16146},"3. La checklist remplace-t-elle la [code review](/fr/intelligence-artificielle/ia-code-review-retour-experience) standard ?",{"type":29,"tag":37,"props":16148,"children":16149},{},[16150],{"type":35,"value":16151},"Non, elle la complète. La review standard couvre l'architecture, le style, la cohérence avec les patterns de l'équipe. La checklist IA ajoute les vérifications spécifiques aux patterns de vulnérabilités et d'erreurs typiques du code LLM-généré. Les deux sont nécessaires.",{"type":29,"tag":381,"props":16153,"children":16154},{},[16155,16160],{"type":29,"tag":385,"props":16156,"children":16157},{},[16158],{"type":35,"value":16159},"4. Les LLMs s'améliorent. Cette checklist sera-t-elle obsolète dans 6 mois ?",{"type":29,"tag":37,"props":16161,"children":16162},{},[16163],{"type":35,"value":16164},"Elle évoluera, mais ne deviendra pas obsolète. Les LLMs s'améliorent sur les patterns de vulnérabilités bien documentés (injections basiques, hardcoded secrets). Ils continuent à se tromper sur les règles métier spécifiques à votre domaine, car ces règles ne sont pas dans leurs données d'entraînement. Les points 1-4 resteront pertinents tant que les LLMs n'auront pas accès à vos spécifications métier propriétaires.",{"type":29,"tag":381,"props":16166,"children":16167},{},[16168,16173],{"type":29,"tag":385,"props":16169,"children":16170},{},[16171],{"type":35,"value":16172},"5. Comment décider qu'un morceau de code est \"IA-assisté\" et mérite la checklist ?",{"type":29,"tag":37,"props":16174,"children":16175},{},[16176],{"type":35,"value":16177},"La règle pragmatique : si plus de 30% du code d'une fonction a été généré par un LLM, appliquer la checklist complète. Pour les petits snippets (autocomplétion d'une ligne), les points 6 et 7 suffisent. En cas de doute, appliquer la checklist : le coût d'une review supplémentaire est toujours inférieur au coût d'un bug en production.",{"type":29,"tag":76,"props":16179,"children":16180},{},[],{"type":29,"tag":176,"props":16182,"children":16183},{"cta":11738,"href":453,"title":4082,"type":455},[16184],{"type":29,"tag":37,"props":16185,"children":16186},{},[16187],{"type":35,"value":16188},"La checklist AI-Ready inclut la checklist de validation du code IA-assisté, les critères de gouvernance des outils IA, et le framework d'évaluation d'adoption. Complète et adaptable à votre contexte d'équipe.",{"type":29,"tag":1252,"props":16190,"children":16191},{},[16192],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":16194},[16195,16196,16197,16198,16199,16200],{"id":15385,"depth":463,"text":15388},{"id":15411,"depth":463,"text":15414},{"id":15509,"depth":463,"text":15512},{"id":15682,"depth":463,"text":15685},{"id":15981,"depth":463,"text":15984},{"id":16109,"depth":463,"text":16112},"content:fr:intelligence-artificielle:tester-code-genere-ia-checklist.md","fr/intelligence-artificielle/tester-code-genere-ia-checklist.md","fr/intelligence-artificielle/tester-code-genere-ia-checklist",{"_path":4432,"_dir":4106,"_draft":7,"_partial":7,"_locale":8,"title":16205,"description":16206,"id":6221,"date":16207,"listed":13,"nocomments":7,"hidden":7,"categories":16208,"tags":16209,"--cover":16213,"readingTime":16214,"body":16218,"_type":476,"_id":16652,"_source":478,"_file":16653,"_stem":16654,"_extension":481},"Estimation agile : pourquoi les story points sont une mauvaise idée","Les story points mesurent l'effort perçu et créent des jeux politiques. Les alternatives que les équipes d'élite utilisent — et comment faire la transition.","2026-02-23",[4106],[16210,16211,16212],"Story Points","Estimation","No Estimates","covers/articles/story-points-alternative.jpg",{"text":497,"minutes":16215,"time":16216,"words":16217},7.565,453900,1513,{"type":26,"children":16219,"toc":16643},[16220,16225,16230,16235,16240,16245,16250,16253,16259,16264,16269,16274,16279,16284,16287,16293,16303,16313,16323,16332,16335,16341,16346,16351,16393,16398,16403,16406,16412,16423,16428,16433,16438,16441,16447,16452,16462,16472,16482,16487,16490,16496,16508,16521,16531,16541,16551,16554,16560,16573,16586,16606,16619,16632,16635],{"type":29,"tag":30,"props":16221,"children":16223},{"id":16222},"estimation-agile-pourquoi-les-story-points-sont-une-mauvaise-idée",[16224],{"type":35,"value":16205},{"type":29,"tag":37,"props":16226,"children":16227},{},[16228],{"type":35,"value":16229},"J'étais en coaching d'une équipe dans une grande institution financière. Lors du sprint planning, un développeur senior a dit \"13\" pour une story. Silence. Puis, progressivement, tous les autres ont voté 13 aussi. La story a été estimée à 13 points en 90 secondes.",{"type":29,"tag":37,"props":16231,"children":16232},{},[16233],{"type":35,"value":16234},"Personne n'avait compris la story. Tout le monde avait suivi le senior.",{"type":29,"tag":37,"props":16236,"children":16237},{},[16238],{"type":35,"value":16239},"La semaine suivante, le management a demandé à l'équipe d'augmenter sa vélocité de 20%. L'équipe a obligé, en estimant les stories plus bas. La vélocité a augmenté. La valeur livrée n'a pas changé.",{"type":29,"tag":37,"props":16241,"children":16242},{},[16243],{"type":35,"value":16244},"Ron Jeffries, l'un des inventeurs du planning poker et des story points, a publié en 2019 un article titré \"Story Points Revisited\" dans lequel il regrette leur création. \"I think story points are mostly harmful,\" écrit-il. Pas parce que la complexité ne mérite pas d'être estimée, mais parce que la façon dont la plupart des équipes utilisent les story points crée plus de problèmes qu'elle n'en résout.",{"type":29,"tag":37,"props":16246,"children":16247},{},[16248],{"type":35,"value":16249},"Vingt-cinq ans de terrain m'ont donné le même constat.",{"type":29,"tag":76,"props":16251,"children":16252},{},[],{"type":29,"tag":80,"props":16254,"children":16256},{"id":16255},"ce-que-les-story-points-mesurent-vraiment",[16257],{"type":35,"value":16258},"Ce que les story points mesurent vraiment",{"type":29,"tag":37,"props":16260,"children":16261},{},[16262],{"type":35,"value":16263},"Officiellement : la complexité relative d'une User Story, indépendante du temps.",{"type":29,"tag":37,"props":16265,"children":16266},{},[16267],{"type":35,"value":16268},"En pratique : l'effort perçu, filtré par les dynamiques politiques de l'équipe.",{"type":29,"tag":37,"props":16270,"children":16271},{},[16272],{"type":35,"value":16273},"La dérive se produit en 3 étapes invariables. L'équipe estime une story à 8 points parce qu'elle est complexe. Le management observe que l'équipe fait 30 story points par sprint. Le trimestre suivant, l'objectif est de \"faire 35 story points par sprint.\"",{"type":29,"tag":37,"props":16275,"children":16276},{},[16277],{"type":35,"value":16278},"À l'étape 3, les story points ne mesurent plus la complexité : ils mesurent une pression de production. Les développeurs le savent et ajustent leurs estimations en conséquence. La vélocité monte. La valeur livrée ne change pas.",{"type":29,"tag":37,"props":16280,"children":16281},{},[16282],{"type":35,"value":16283},"Dans toute équipe qui utilise les story points depuis plus de 6 mois avec une pression sur la vélocité, des patterns de gaming émergent. L'inflation des estimations pour \"se couvrir\" : tout devient 5 ou 8, jamais 1 ou 2. La déflation pour \"montrer de la vélocité\" : accepter plus de stories au sprint planning qu'on ne peut en faire. Et la négociation politique lors du planning poker : le senior dit 13, tout le monde s'aligne sur 13.",{"type":29,"tag":76,"props":16285,"children":16286},{},[],{"type":29,"tag":80,"props":16288,"children":16290},{"id":16289},"les-3-pathologies-créées-par-les-story-points",[16291],{"type":35,"value":16292},"Les 3 pathologies créées par les story points",{"type":29,"tag":37,"props":16294,"children":16295},{},[16296,16301],{"type":29,"tag":65,"props":16297,"children":16298},{},[16299],{"type":35,"value":16300},"Pathologie 1 : La durée des sessions de planning.",{"type":35,"value":16302}," Le planning poker crée des discussions de 20 à 45 minutes par story sur des questions d'estimation abstraite. Ces discussions ne créent pas de valeur : elles consomment du temps qui pourrait être utilisé à comprendre le métier ou à lever les ambiguïtés réelles. J'ai mesuré dans une équipe de 8 personnes : 180 minutes par sprint consacrées à l'estimation. Soit 78 heures-personne par trimestre pour produire un chiffre que personne ne croit.",{"type":29,"tag":37,"props":16304,"children":16305},{},[16306,16311],{"type":29,"tag":65,"props":16307,"children":16308},{},[16309],{"type":35,"value":16310},"Pathologie 2 : La comparaison entre équipes.",{"type":35,"value":16312}," \"L'équipe A fait 40 points par sprint et l'équipe B en fait 25.\" Cette comparaison est absurde : les story points de deux équipes différentes ne mesurent pas la même chose. Mais le management qui a accès à ces données les compare inévitablement. J'ai vu cette comparaison détruire la collaboration entre deux équipes qui travaillaient pourtant sur la même base de code.",{"type":29,"tag":37,"props":16314,"children":16315},{},[16316,16321],{"type":29,"tag":65,"props":16317,"children":16318},{},[16319],{"type":35,"value":16320},"Pathologie 3 : La dette d'estimation.",{"type":35,"value":16322}," Quand le contexte change (nouvelle technologie, départ d'un senior, changement de stack), la calibration des story points devient invalide. L'équipe passe plusieurs sprints avec une vélocité erratique, et le management interprète ça comme un problème de productivité. C'est un problème de métrique inadaptée, pas de performance.",{"type":29,"tag":176,"props":16324,"children":16326},{"cta":178,"href":179,"title":16325,"type":181},"Votre planning poker est devenu une source de friction sans apporter de valeur réelle à la planification ?",[16327],{"type":29,"tag":37,"props":16328,"children":16329},{},[16330],{"type":35,"value":16331},"La transition vers des alternatives aux story points nécessite un accompagnement pour ne pas perdre la confiance du business dans la planification. En 30 minutes, je définis avec vous la stratégie de transition adaptée à votre contexte et à votre management.",{"type":29,"tag":76,"props":16333,"children":16334},{},[],{"type":29,"tag":80,"props":16336,"children":16338},{"id":16337},"lalternative-1-le-sizing-t-shirt",[16339],{"type":35,"value":16340},"L'alternative 1 : le sizing T-shirt",{"type":29,"tag":37,"props":16342,"children":16343},{},[16344],{"type":35,"value":16345},"Le sizing T-shirt remplace les valeurs numériques par des tailles (S, M, L, XL). L'avantage fondamental : il est impossible de faire de la fausse précision avec des tailles. \"Ceci est une story M\" ne peut pas être transformé en \"notre vélocité est de 35 tailles-M par sprint.\"",{"type":29,"tag":37,"props":16347,"children":16348},{},[16349],{"type":35,"value":16350},"La définition des tailles en termes de cycle time attendu (pas d'effort, de durée réelle) est ce qui rend la méthode concrète :",{"type":29,"tag":1080,"props":16352,"children":16353},{},[16354,16363,16373,16383],{"type":29,"tag":1084,"props":16355,"children":16356},{},[16357,16361],{"type":29,"tag":65,"props":16358,"children":16359},{},[16360],{"type":35,"value":3601},{"type":35,"value":16362}," : terminable en moins d'un jour de développement",{"type":29,"tag":1084,"props":16364,"children":16365},{},[16366,16371],{"type":29,"tag":65,"props":16367,"children":16368},{},[16369],{"type":35,"value":16370},"M",{"type":35,"value":16372}," : terminable en 1 à 3 jours",{"type":29,"tag":1084,"props":16374,"children":16375},{},[16376,16381],{"type":29,"tag":65,"props":16377,"children":16378},{},[16379],{"type":35,"value":16380},"L",{"type":35,"value":16382}," : terminable en 1 semaine",{"type":29,"tag":1084,"props":16384,"children":16385},{},[16386,16391],{"type":29,"tag":65,"props":16387,"children":16388},{},[16389],{"type":35,"value":16390},"XL",{"type":35,"value":16392}," : trop grande pour un sprint, doit être découpée avant d'entrer en sprint planning",{"type":29,"tag":37,"props":16394,"children":16395},{},[16396],{"type":35,"value":16397},"La règle est non-négociable : toute story XL ne peut pas entrer en sprint. Elle doit être découpée en stories S, M, ou L.",{"type":29,"tag":37,"props":16399,"children":16400},{},[16401],{"type":35,"value":16402},"Ce que le business voit : le nombre de stories terminées par sprint et leur distribution par taille. Pas une vélocité abstraite, mais un throughput concret.",{"type":29,"tag":76,"props":16404,"children":16405},{},[],{"type":29,"tag":80,"props":16407,"children":16409},{"id":16408},"lalternative-2-le-throughput-et-le-mouvement-noestimates",[16410],{"type":35,"value":16411},"L'alternative 2 : le throughput et le mouvement #NoEstimates",{"type":29,"tag":37,"props":16413,"children":16414},{},[16415,16417,16421],{"type":35,"value":16416},"Le mouvement #NoEstimates (Vasco Duarte, Woody Zuill) propose une approche encore plus radicale : arrêter d'estimer et mesurer la capacité à travers le ",{"type":29,"tag":65,"props":16418,"children":16419},{},[16420],{"type":35,"value":4435},{"type":35,"value":16422},", c'est-à-dire le nombre de stories terminées par sprint, quelle que soit leur taille.",{"type":29,"tag":37,"props":16424,"children":16425},{},[16426],{"type":35,"value":16427},"L'hypothèse fondamentale : si les stories sont suffisamment petites et uniformes (toutes inférieures ou égales à 3 jours), la loi des grands nombres s'applique. La variance se lisse sur 3 à 6 sprints et le throughput devient un prédicteur fiable de la capacité future.",{"type":29,"tag":37,"props":16429,"children":16430},{},[16431],{"type":35,"value":16432},"Ce que le business entend : \"Avec 15 stories par sprint en moyenne sur les 6 derniers sprints, il nous faudra environ 3 sprints pour terminer les 40 stories restantes de la fonctionnalité X.\" C'est plus précis qu'une prédiction basée sur des story points qui dérivent.",{"type":29,"tag":37,"props":16434,"children":16435},{},[16436],{"type":35,"value":16437},"Le prérequis est strict : que les stories soient uniformément petites. C'est la condition que beaucoup d'équipes ne respectent pas, et c'est pourquoi elles ne peuvent pas adopter #NoEstimates directement. Le sizing T-shirt est souvent une étape intermédiaire nécessaire.",{"type":29,"tag":76,"props":16439,"children":16440},{},[],{"type":29,"tag":80,"props":16442,"children":16444},{"id":16443},"comment-faire-la-transition-sans-casser-la-confiance-du-business",[16445],{"type":35,"value":16446},"Comment faire la transition sans casser la confiance du business",{"type":29,"tag":37,"props":16448,"children":16449},{},[16450],{"type":35,"value":16451},"Le business a souvent été \"vendu\" les story points comme un outil de prédictibilité. La transition doit être gérée avec transparence, pas imposée.",{"type":29,"tag":37,"props":16453,"children":16454},{},[16455,16460],{"type":29,"tag":65,"props":16456,"children":16457},{},[16458],{"type":35,"value":16459},"Sprints 1-2",{"type":35,"value":16461}," : présenter les deux méthodes en parallèle. Continuer à estimer en story points tout en calculant le throughput. Montrer que les deux donnent les mêmes prédictions sur 3 sprints. Rassurer sur la continuité de la prédictibilité.",{"type":29,"tag":37,"props":16463,"children":16464},{},[16465,16470],{"type":29,"tag":65,"props":16466,"children":16467},{},[16468],{"type":35,"value":16469},"Sprints 3-4",{"type":35,"value":16471}," : passer en sizing T-shirt uniquement. Montrer que la planification capacitaire reste fiable. Partager les données avec le management.",{"type":29,"tag":37,"props":16473,"children":16474},{},[16475,16480],{"type":29,"tag":65,"props":16476,"children":16477},{},[16478],{"type":35,"value":16479},"Sprints 5 et suivants",{"type":35,"value":16481}," : si l'équipe est prête et les stories sont uniformément petites, explorer le throughput comme seule métrique.",{"type":29,"tag":37,"props":16483,"children":16484},{},[16485],{"type":35,"value":16486},"L'argument décisif : les données. Sur les 6 derniers mois, quelle est la corrélation entre la vélocité en points et la valeur livrée ? Dans la plupart des équipes, cette corrélation est faible. Ce fait, présenté objectivement, démontre que les story points ne mesurent pas ce qu'on prétend qu'ils mesurent.",{"type":29,"tag":76,"props":16488,"children":16489},{},[],{"type":29,"tag":80,"props":16491,"children":16493},{"id":16492},"les-métriques-qui-remplacent-avantageusement-la-vélocité",[16494],{"type":35,"value":16495},"Les métriques qui remplacent avantageusement la vélocité",{"type":29,"tag":37,"props":16497,"children":16498},{},[16499,16501,16506],{"type":35,"value":16500},"Les ",{"type":29,"tag":48,"props":16502,"children":16503},{"href":12453},[16504],{"type":35,"value":16505},"recherches DORA",{"type":35,"value":16507}," (DevOps Research and Assessment) sont claires : les équipes avec les meilleures performances de delivery n'utilisent généralement pas les story points. Elles mesurent le flux.",{"type":29,"tag":37,"props":16509,"children":16510},{},[16511,16519],{"type":29,"tag":65,"props":16512,"children":16513},{},[16514],{"type":29,"tag":48,"props":16515,"children":16516},{"href":50},[16517],{"type":35,"value":16518},"Cycle Time",{"type":35,"value":16520}," : temps entre le début du développement et le merge. Mesure la fluidité du workflow.",{"type":29,"tag":37,"props":16522,"children":16523},{},[16524,16529],{"type":29,"tag":65,"props":16525,"children":16526},{},[16527],{"type":35,"value":16528},"Throughput",{"type":35,"value":16530}," : nombre de stories terminées par sprint. Mesure la capacité réelle de livraison.",{"type":29,"tag":37,"props":16532,"children":16533},{},[16534,16539],{"type":29,"tag":65,"props":16535,"children":16536},{},[16537],{"type":35,"value":16538},"Flow Efficiency",{"type":35,"value":16540}," : pourcentage du cycle time où la story est activement travaillée versus en attente. Révèle les goulots d'étranglement invisibles.",{"type":29,"tag":37,"props":16542,"children":16543},{},[16544,16549],{"type":29,"tag":65,"props":16545,"children":16546},{},[16547],{"type":35,"value":16548},"Work Item Age",{"type":35,"value":16550}," : âge des stories en cours. Un item vieux de 3 sprints est un signal d'alerte qui mérite investigation.",{"type":29,"tag":76,"props":16552,"children":16553},{},[],{"type":29,"tag":80,"props":16555,"children":16557},{"id":16556},"faq-sur-lestimation-agile",[16558],{"type":35,"value":16559},"FAQ sur l'estimation agile",{"type":29,"tag":381,"props":16561,"children":16562},{},[16563,16568],{"type":29,"tag":385,"props":16564,"children":16565},{},[16566],{"type":35,"value":16567},"1. Peut-on abandonner les story points si le management les utilise pour les planifications budgétaires ?",{"type":29,"tag":37,"props":16569,"children":16570},{},[16571],{"type":35,"value":16572},"Oui, avec une transition transparente. Le management a besoin de prédictibilité, pas de story points spécifiquement. Montrer que le throughput avec des intervalles de confiance basés sur 6 sprints de données est plus fiable pour les prédictions à 3-6 mois que la vélocité en points, qui dérive systématiquement. Proposer une période de validation en parallèle avant le switch complet.",{"type":29,"tag":381,"props":16574,"children":16575},{},[16576,16581],{"type":29,"tag":385,"props":16577,"children":16578},{},[16579],{"type":35,"value":16580},"2. Le sizing T-shirt n'est-il pas trop imprécis pour planifier ?",{"type":29,"tag":37,"props":16582,"children":16583},{},[16584],{"type":35,"value":16585},"C'est exactement la bonne précision. L'estimation en story points donne une fausse précision : 8 points n'est pas plus précis que L, c'est juste plus abstraitement précis. Le sizing T-shirt force à accepter l'incertitude naturelle de l'estimation et à planifier avec des intervalles de confiance plutôt que des prédictions ponctuelles illusoires.",{"type":29,"tag":381,"props":16587,"children":16588},{},[16589,16594],{"type":29,"tag":385,"props":16590,"children":16591},{},[16592],{"type":35,"value":16593},"3. Comment gérer les stories très différentes en taille avec le sizing T-shirt ?",{"type":29,"tag":37,"props":16595,"children":16596},{},[16597,16599,16604],{"type":35,"value":16598},"En appliquant la règle de découpage : toute story XL est découpée avant d'entrer en sprint. C'est le prérequis de la méthode. Un ",{"type":29,"tag":48,"props":16600,"children":16601},{"href":4295},[16602],{"type":35,"value":16603},"backlog sain",{"type":35,"value":16605}," contient essentiellement des stories S et M prêtes à développer. Si une story ne peut pas être découpée en stories M ou L, c'est un signal que la story est mal définie, pas que la méthode ne fonctionne pas.",{"type":29,"tag":381,"props":16607,"children":16608},{},[16609,16614],{"type":29,"tag":385,"props":16610,"children":16611},{},[16612],{"type":35,"value":16613},"4. Les story points sont-ils utiles pour l'estimation initiale d'un projet ?",{"type":29,"tag":37,"props":16615,"children":16616},{},[16617],{"type":35,"value":16618},"Pour une estimation de haut niveau d'un nouveau projet (scope discovery, appel d'offres), les story points peuvent avoir leur utilité, pas pour le sprint planning quotidien, mais pour donner un ordre de grandeur du périmètre. Dans ce cas, utiliser des T-shirt sizes sur les epics ou features plutôt que sur les stories individuelles donne un résultat équivalent avec moins de friction.",{"type":29,"tag":381,"props":16620,"children":16621},{},[16622,16627],{"type":29,"tag":385,"props":16623,"children":16624},{},[16625],{"type":35,"value":16626},"5. Que faire quand les développeurs seniors refusent d'abandonner les story points ?",{"type":29,"tag":37,"props":16628,"children":16629},{},[16630],{"type":35,"value":16631},"Ne pas forcer. Commencer par un pilote volontaire sur un sprint, en mesurant le temps passé en estimation et en comparant la qualité des prédictions. Le résultat de l'expérience parle mieux que l'argument de principe. Les développeurs qui résistent le plus au changement deviennent souvent les défenseurs les plus convaincus une fois qu'ils ont mesuré le gain de temps.",{"type":29,"tag":76,"props":16633,"children":16634},{},[],{"type":29,"tag":176,"props":16636,"children":16637},{"cta":4551,"href":453,"title":4552,"type":455},[16638],{"type":29,"tag":37,"props":16639,"children":16640},{},[16641],{"type":35,"value":16642},"Le guide complet pour réduire votre lead time en 90 jours inclut une section sur les métriques de flow (cycle time, throughput, WIP) qui remplacent avantageusement la vélocité en story points avec plus de précision prédictive.",{"title":8,"searchDepth":463,"depth":463,"links":16644},[16645,16646,16647,16648,16649,16650,16651],{"id":16255,"depth":463,"text":16258},{"id":16289,"depth":463,"text":16292},{"id":16337,"depth":463,"text":16340},{"id":16408,"depth":463,"text":16411},{"id":16443,"depth":463,"text":16446},{"id":16492,"depth":463,"text":16495},{"id":16556,"depth":463,"text":16559},"content:fr:pratiques-agiles:story-points-estimation-agile-alternative.md","fr/pratiques-agiles/story-points-estimation-agile-alternative.md","fr/pratiques-agiles/story-points-estimation-agile-alternative",{"_path":9765,"_dir":6,"_draft":7,"_partial":7,"_locale":8,"title":16656,"description":16657,"id":6160,"date":16658,"listed":13,"nocomments":7,"hidden":7,"categories":16659,"tags":16660,"--cover":16663,"readingTime":16664,"body":16668,"_type":476,"_id":17140,"_source":478,"_file":17141,"_stem":17142,"_extension":481},"Tests d'intégration : les pièges à éviter dans un legacy","Ajouter des tests d'intégration à un legacy est souvent plus difficile qu'écrire from scratch. Les 4 pièges classiques et la séquence qui fonctionne.","2026-02-20",[6],[16661,16662,2128],"Tests Intégration","Legacy","covers/articles/tests-integration-legacy.jpg",{"text":497,"minutes":16665,"time":16666,"words":16667},7.63,457800,1526,{"type":26,"children":16669,"toc":17131},[16670,16675,16680,16688,16699,16702,16708,16713,16739,16744,16747,16753,16758,16768,16785,16788,16794,16799,16808,16824,16837,16840,16849,16852,16858,16863,16871,16894,16910,16915,16918,16924,16929,16938,16957,16962,16965,16971,17041,17046,17049,17055,17068,17081,17094,17107,17120,17123],{"type":29,"tag":30,"props":16671,"children":16673},{"id":16672},"tests-dintégration-les-pièges-à-éviter-dans-un-legacy",[16674],{"type":35,"value":16656},{"type":29,"tag":37,"props":16676,"children":16677},{},[16678],{"type":35,"value":16679},"J'accompagnais une équipe dans un opérateur télécoms : des ingénieurs sérieux, déterminés à \"enfin écrire des tests sur le legacy\". Ils avaient décidé d'attaquer directement le moteur de facturation : 18 000 lignes de code, 30 dépendances, et une logique métier partiellement documentée. Quatre semaines plus tard, ils avaient produit 3 tests unitaires instables et une équipe découragée. Les tests ne compilaient pas parce que les dépendances ne pouvaient pas être initialisées dans un contexte de test. La motivation avait plongé. On a repris à zéro, mais différemment.",{"type":29,"tag":37,"props":16681,"children":16682},{},[16683],{"type":29,"tag":65,"props":16684,"children":16685},{},[16686],{"type":35,"value":16687},"Décider d'ajouter des tests d'intégration à un legacy est une bonne décision. Mal exécutée, c'est une décision qui peut paralyser l'équipe pendant 3 mois pour un résultat décevant. Les pièges sont prévisibles et évitables.",{"type":29,"tag":37,"props":16689,"children":16690},{},[16691,16693,16697],{"type":35,"value":16692},"Les tests unitaires sur le legacy ont une limite bien connue : ils testent des unités isolées mais ne testent pas le comportement d'ensemble. Pour un filet de sécurité au niveau de l'équipe, assurez-vous que votre ",{"type":29,"tag":48,"props":16694,"children":16695},{"href":4950},[16696],{"type":35,"value":11631},{"type":35,"value":16698}," exige des tests d'intégration sur les chemins critiques.. Un système peut avoir 70% de couverture unitaire et tomber en production parce que l'intégration entre composants n'est pas testée. Mais ajouter des tests d'intégration à un legacy n'est pas une opération simple. Le legacy n'a généralement pas été conçu pour être testé.",{"type":29,"tag":76,"props":16700,"children":16701},{},[],{"type":29,"tag":80,"props":16703,"children":16705},{"id":16704},"pourquoi-les-tests-unitaires-seuls-ne-suffisent-pas",[16706],{"type":35,"value":16707},"Pourquoi les tests unitaires seuls ne suffisent pas",{"type":29,"tag":37,"props":16709,"children":16710},{},[16711],{"type":35,"value":16712},"Un test unitaire isole une fonction et vérifie son comportement en isolation. C'est nécessaire. Mais c'est insuffisant pour détecter les bugs qui apparaissent à la jonction entre composants.",{"type":29,"tag":37,"props":16714,"children":16715},{},[16716,16721,16723,16729,16731,16737],{"type":29,"tag":65,"props":16717,"children":16718},{},[16719],{"type":35,"value":16720},"Exemple concret",{"type":35,"value":16722}," : deux classes parfaitement testées en isolation, l'une qui sérialise une date en ",{"type":29,"tag":565,"props":16724,"children":16726},{"className":16725},[],[16727],{"type":35,"value":16728},"MM/DD/YYYY",{"type":35,"value":16730}," et l'autre qui la désérialise en attendant ",{"type":29,"tag":565,"props":16732,"children":16734},{"className":16733},[],[16735],{"type":35,"value":16736},"YYYY-MM-DD",{"type":35,"value":16738},". Les tests unitaires passent. Le système plante en prod.",{"type":29,"tag":37,"props":16740,"children":16741},{},[16742],{"type":35,"value":16743},"Les tests d'intégration testent les interactions : entre services, entre couches, entre la couche application et la base de données. Ils ont un coût d'exécution plus élevé mais une valeur de détection différente et complémentaire. Sur un legacy, les bugs les plus coûteux sont presque toujours des bugs d'intégration, pas des bugs unitaires. J'ai rarement vu un incident de prod majeur causé par un bug unitaire. J'en ai vu des dizaines causés par des bugs d'intégration silencieux.",{"type":29,"tag":76,"props":16745,"children":16746},{},[],{"type":29,"tag":80,"props":16748,"children":16750},{"id":16749},"piège-1-tester-sans-comprendre-le-comportement-attendu",[16751],{"type":35,"value":16752},"Piège 1 : Tester sans comprendre le comportement attendu",{"type":29,"tag":37,"props":16754,"children":16755},{},[16756],{"type":35,"value":16757},"La première erreur est de commencer à écrire des tests sans savoir ce que le système est censé faire. Sur un legacy réel, le comportement attendu est souvent partiellement documenté ou connu uniquement par des personnes qui ont quitté l'entreprise.",{"type":29,"tag":37,"props":16759,"children":16760},{},[16761,16766],{"type":29,"tag":65,"props":16762,"children":16763},{},[16764],{"type":35,"value":16765},"Ce qui arrive",{"type":35,"value":16767}," : l'équipe écrit des tests qui vérifient le comportement actuel, y compris les bugs existants. Quand un vrai bug est corrigé, les tests cassent. L'équipe corrige les tests pour \"faire passer le build\" au lieu de corriger le comportement. Les tests deviennent un obstacle plutôt qu'un filet de sécurité.",{"type":29,"tag":37,"props":16769,"children":16770},{},[16771,16776,16778,16783],{"type":29,"tag":65,"props":16772,"children":16773},{},[16774],{"type":35,"value":16775},"La sortie",{"type":35,"value":16777}," : avant d'écrire le premier test d'intégration, j'organise une session de 2 à 3 heures avec un expert métier pour définir les ",{"type":29,"tag":65,"props":16779,"children":16780},{},[16781],{"type":35,"value":16782},"comportements de référence",{"type":35,"value":16784}," : quels sont les scénarios nominaux et les scénarios d'erreur qui doivent être garantis ? Cette session produit les spécifications des tests, pas l'inverse.",{"type":29,"tag":76,"props":16786,"children":16787},{},[],{"type":29,"tag":80,"props":16789,"children":16791},{"id":16790},"piège-2-commencer-par-le-code-le-plus-complexe",[16792],{"type":35,"value":16793},"Piège 2 : Commencer par le code le plus complexe",{"type":29,"tag":37,"props":16795,"children":16796},{},[16797],{"type":35,"value":16798},"L'instinct technique pousse à attaquer les modules les plus risqués en premier. C'est une mauvaise stratégie, je l'ai apprise à mes dépens dans mes premiers accompagnements.",{"type":29,"tag":37,"props":16800,"children":16801},{},[16802,16806],{"type":29,"tag":65,"props":16803,"children":16804},{},[16805],{"type":35,"value":16765},{"type":35,"value":16807}," : l'équipe passe 3 semaines à essayer de tester le module central du legacy, celui avec 10 000 lignes de code, 30 dépendances implicites, et une logique métier que personne ne comprend entièrement. Les tests ne compilent pas. L'équipe est bloquée et découragée.",{"type":29,"tag":37,"props":16809,"children":16810},{},[16811,16815,16817,16822],{"type":29,"tag":65,"props":16812,"children":16813},{},[16814],{"type":35,"value":16775},{"type":35,"value":16816}," : commencer par les modules ",{"type":29,"tag":65,"props":16818,"children":16819},{},[16820],{"type":35,"value":16821},"en bordure",{"type":35,"value":16823}," du système, c'est-à-dire les points d'entrée et de sortie. Un test d'intégration qui vérifie qu'une API renvoie le bon status code pour une requête valide est simple à écrire et immédiatement utile. Une fois les tests de bordure en place, progresser vers le centre.",{"type":29,"tag":12961,"props":16825,"children":16826},{},[16827],{"type":29,"tag":37,"props":16828,"children":16829},{},[16830,16835],{"type":29,"tag":65,"props":16831,"children":16832},{},[16833],{"type":35,"value":16834},"Retour sur l'équipe télécoms",{"type":35,"value":16836}," : après l'échec initial sur le moteur de facturation, j'ai proposé de pivoter vers les tests de bordure, à savoir les API REST qui alimentent le moteur. En 2 semaines, 15 tests d'intégration fonctionnels. Ce succès rapide a relancé la motivation et donné une base solide pour progresser vers le centre progressivement.",{"type":29,"tag":76,"props":16838,"children":16839},{},[],{"type":29,"tag":176,"props":16841,"children":16843},{"cta":178,"href":179,"title":16842,"type":181},"Vous essayez d'ajouter des tests à un legacy mais vous ne savez pas par où commencer ?",[16844],{"type":29,"tag":37,"props":16845,"children":16846},{},[16847],{"type":35,"value":16848},"Vous avez déjà essayé, et soit l'équipe s'est découragée, soit les tests écrits ne donnent pas confiance. La séquence d'ajout de tests sur un legacy dépend de l'architecture, de la criticité des modules, et des ressources disponibles. En 30 minutes, on définit la stratégie adaptée à votre contexte.",{"type":29,"tag":76,"props":16850,"children":16851},{},[],{"type":29,"tag":80,"props":16853,"children":16855},{"id":16854},"piège-3-créer-une-dépendance-à-la-base-de-données-de-production",[16856],{"type":35,"value":16857},"Piège 3 : Créer une dépendance à la base de données de production",{"type":29,"tag":37,"props":16859,"children":16860},{},[16861],{"type":35,"value":16862},"Pour tester l'intégration, il faut des données. L'approche la plus simple est de pointer sur la base de données de production (ou une copie) dans les tests. C'est une très mauvaise idée.",{"type":29,"tag":37,"props":16864,"children":16865},{},[16866,16870],{"type":29,"tag":65,"props":16867,"children":16868},{},[16869],{"type":35,"value":16765},{"type":35,"value":11585},{"type":29,"tag":1080,"props":16872,"children":16873},{},[16874,16879,16884,16889],{"type":29,"tag":1084,"props":16875,"children":16876},{},[16877],{"type":35,"value":16878},"Les tests sont non-déterministes : ils dépendent de l'état des données, qui change",{"type":29,"tag":1084,"props":16880,"children":16881},{},[16882],{"type":35,"value":16883},"Les tests ralentissent avec le volume de données",{"type":29,"tag":1084,"props":16885,"children":16886},{},[16887],{"type":35,"value":16888},"Des tests mal écrits peuvent modifier des données réelles",{"type":29,"tag":1084,"props":16890,"children":16891},{},[16892],{"type":35,"value":16893},"La base de prod ne peut pas être réinitialisée entre les tests",{"type":29,"tag":37,"props":16895,"children":16896},{},[16897,16901,16903,16908],{"type":29,"tag":65,"props":16898,"children":16899},{},[16900],{"type":35,"value":16775},{"type":35,"value":16902}," : utiliser une base de test dédiée, initialisée à chaque exécution de test avec un jeu de données connu et contrôlé. Pour les bases relationnelles, les ",{"type":29,"tag":65,"props":16904,"children":16905},{},[16906],{"type":35,"value":16907},"test containers",{"type":35,"value":16909}," (Testcontainers Java, Python, Node.js) permettent de démarrer une vraie base de données dans Docker pour chaque suite de tests : propre, isolée, et détruite après.",{"type":29,"tag":37,"props":16911,"children":16912},{},[16913],{"type":35,"value":16914},"Pour les systèmes avec des données volumineuses, créer un dataset de test représentatif mais minimal (100 à 1 000 enregistrements couvrant tous les scénarios) plutôt que de copier des millions de lignes de prod.",{"type":29,"tag":76,"props":16916,"children":16917},{},[],{"type":29,"tag":80,"props":16919,"children":16921},{"id":16920},"piège-4-ignorer-les-tests-de-régression-comportementale",[16922],{"type":35,"value":16923},"Piège 4 : Ignorer les tests de régression comportementale",{"type":29,"tag":37,"props":16925,"children":16926},{},[16927],{"type":35,"value":16928},"Le legacy a un comportement actuel. Ce comportement, même imparfait, est probablement attendu par les utilisateurs. Des tests d'intégration qui ne couvrent pas ce comportement actuel permettent des régressions silencieuses.",{"type":29,"tag":37,"props":16930,"children":16931},{},[16932,16936],{"type":29,"tag":65,"props":16933,"children":16934},{},[16935],{"type":35,"value":16765},{"type":35,"value":16937}," : l'équipe écrit de nouveaux tests d'intégration basés sur la documentation (incomplète). Des comportements non-documentés mais attendus par les utilisateurs sont cassés lors d'un refactoring. L'équipe l'apprend en production.",{"type":29,"tag":37,"props":16939,"children":16940},{},[16941,16945,16947,16955],{"type":29,"tag":65,"props":16942,"children":16943},{},[16944],{"type":35,"value":16775},{"type":35,"value":16946}," : les ",{"type":29,"tag":65,"props":16948,"children":16949},{},[16950],{"type":29,"tag":48,"props":16951,"children":16952},{"href":9834},[16953],{"type":35,"value":16954},"characterization tests",{"type":35,"value":16956}," d'abord. Avant d'écrire des tests qui vérifient le comportement attendu, écrire des tests qui documentent le comportement actuel. C'est le concept de Michael Feathers dans \"Working Effectively with Legacy Code\" : un characterization test capture ce que le système fait réellement, pas ce qu'il devrait faire.",{"type":29,"tag":37,"props":16958,"children":16959},{},[16960],{"type":35,"value":16961},"Ces tests ont une propriété précieuse : si un refactoring casse un characterization test, il faut une décision explicite pour valider que le changement de comportement est intentionnel. C'est le filet de sécurité que je rends obligatoire avant toute modification significative d'un legacy.",{"type":29,"tag":76,"props":16963,"children":16964},{},[],{"type":29,"tag":80,"props":16966,"children":16968},{"id":16967},"la-séquence-qui-fonctionne",[16969],{"type":35,"value":16970},"La séquence qui fonctionne",{"type":29,"tag":14624,"props":16972,"children":16973},{},[16974,16984,16994,17011,17021,17031],{"type":29,"tag":1084,"props":16975,"children":16976},{},[16977,16982],{"type":29,"tag":65,"props":16978,"children":16979},{},[16980],{"type":35,"value":16981},"Session de définition des comportements de référence",{"type":35,"value":16983}," (2-3h avec expert métier) → liste des scénarios à garantir",{"type":29,"tag":1084,"props":16985,"children":16986},{},[16987,16992],{"type":29,"tag":65,"props":16988,"children":16989},{},[16990],{"type":35,"value":16991},"Audit des dépendances",{"type":35,"value":16993}," (1 jour) → cartographie des intégrations externes, DB, services tiers",{"type":29,"tag":1084,"props":16995,"children":16996},{},[16997,17002,17004,17009],{"type":29,"tag":65,"props":16998,"children":16999},{},[17000],{"type":35,"value":17001},"Infrastructure de test",{"type":35,"value":17003}," (2-3 jours) → test containers, fixtures de données, ",{"type":29,"tag":48,"props":17005,"children":17006},{"href":11764},[17007],{"type":35,"value":17008},"CI",{"type":35,"value":17010}," configurée",{"type":29,"tag":1084,"props":17012,"children":17013},{},[17014,17019],{"type":29,"tag":65,"props":17015,"children":17016},{},[17017],{"type":35,"value":17018},"Characterization tests sur les chemins critiques",{"type":35,"value":17020}," (1-2 semaines) → documentation du comportement actuel",{"type":29,"tag":1084,"props":17022,"children":17023},{},[17024,17029],{"type":29,"tag":65,"props":17025,"children":17026},{},[17027],{"type":35,"value":17028},"Tests d'intégration de bordure",{"type":35,"value":17030}," (2-3 semaines) → points d'entrée et de sortie du système",{"type":29,"tag":1084,"props":17032,"children":17033},{},[17034,17039],{"type":29,"tag":65,"props":17035,"children":17036},{},[17037],{"type":35,"value":17038},"Progression vers le centre",{"type":35,"value":17040}," (continu) → module par module, en priorisant par criticité",{"type":29,"tag":37,"props":17042,"children":17043},{},[17044],{"type":35,"value":17045},"Cette séquence n'est pas rapide : comptez 6 à 10 semaines pour une base solide. Mais elle produit des tests qui tiennent dans le temps et qui augmentent réellement la confiance de l'équipe.",{"type":29,"tag":76,"props":17047,"children":17048},{},[],{"type":29,"tag":80,"props":17050,"children":17052},{"id":17051},"faq-sur-les-tests-dintégration-en-legacy",[17053],{"type":35,"value":17054},"FAQ sur les tests d'intégration en legacy",{"type":29,"tag":381,"props":17056,"children":17057},{},[17058,17063],{"type":29,"tag":385,"props":17059,"children":17060},{},[17061],{"type":35,"value":17062},"1. Quelle est la différence entre un test d'intégration et un test end-to-end ?",{"type":29,"tag":37,"props":17064,"children":17065},{},[17066],{"type":35,"value":17067},"Un test d'intégration vérifie l'interaction entre deux ou plusieurs composants internes du système (ex : service + base de données). Un test end-to-end vérifie un scénario utilisateur complet, de l'interface jusqu'à la persistance. Sur un legacy, je commence par les tests d'intégration : ils sont plus rapides, plus stables, et plus faciles à diagnostiquer que les tests E2E.",{"type":29,"tag":381,"props":17069,"children":17070},{},[17071,17076],{"type":29,"tag":385,"props":17072,"children":17073},{},[17074],{"type":35,"value":17075},"2. Combien de temps faut-il pour avoir une suite de tests d'intégration utile sur un legacy ?",{"type":29,"tag":37,"props":17077,"children":17078},{},[17079],{"type":35,"value":17080},"Pour un legacy de taille moyenne (50 000 à 200 000 lignes de code), comptez 6 à 10 semaines pour avoir une suite couvrant les 10 à 15 scénarios critiques. C'est un investissement qui se rentabilise dès le premier refactoring majeur : une régression évitée sur un module critique vaut facilement 10 fois le coût de la suite de tests.",{"type":29,"tag":381,"props":17082,"children":17083},{},[17084,17089],{"type":29,"tag":385,"props":17085,"children":17086},{},[17087],{"type":35,"value":17088},"3. Faut-il des développeurs dédiés aux tests ou tous les développeurs participent ?",{"type":29,"tag":37,"props":17090,"children":17091},{},[17092],{"type":35,"value":17093},"Tous les développeurs participent. Les tests d'intégration ne sont pas une spécialité, ils sont une responsabilité de l'équipe. En pratique, je désigne un \"test champion\" par équipe pour maintenir l'infrastructure et les standards, mais chaque développeur qui modifie un module doit ajouter ou mettre à jour les tests correspondants.",{"type":29,"tag":381,"props":17095,"children":17096},{},[17097,17102],{"type":29,"tag":385,"props":17098,"children":17099},{},[17100],{"type":35,"value":17101},"4. Comment gérer les tests qui tombent de façon intermittente (flaky tests) ?",{"type":29,"tag":37,"props":17103,"children":17104},{},[17105],{"type":35,"value":17106},"Les flaky tests sont le cancer des suites de tests : ils réduisent la confiance dans tous les tests et poussent les équipes à ignorer les échecs. Ma règle est simple : un flaky test est soit corrigé dans les 48h, soit désactivé avec un ticket de suivi. Un test désactivé qui n'a pas de ticket actif dans le backlog est supprimé. La discipline sur les flaky tests conditionne la confiance dans toute la suite.",{"type":29,"tag":381,"props":17108,"children":17109},{},[17110,17115],{"type":29,"tag":385,"props":17111,"children":17112},{},[17113],{"type":35,"value":17114},"5. Les test containers ralentissent-ils la CI de manière inacceptable ?",{"type":29,"tag":37,"props":17116,"children":17117},{},[17118],{"type":35,"value":17119},"Sur un pipeline bien configuré, non. Les test containers démarrent en 5 à 15 secondes pour une base PostgreSQL ou MySQL. En parallélisant les suites de tests et en utilisant un cache Docker sur la CI, l'impact sur le temps total est marginal. Le vrai coût est le premier setup : 1 à 2 jours pour configurer l'infrastructure. Après ça, chaque nouvelle suite de tests bénéficie de l'infrastructure existante.",{"type":29,"tag":76,"props":17121,"children":17122},{},[],{"type":29,"tag":176,"props":17124,"children":17125},{"cta":452,"href":453,"title":454,"type":455},[17126],{"type":29,"tag":37,"props":17127,"children":17128},{},[17129],{"type":35,"value":17130},"L'assessment inclut une évaluation complète de vos pratiques de tests : couverture, types de tests, intégration dans la CI. Identifiez vos angles morts et priorisez les améliorations à fort impact.",{"title":8,"searchDepth":463,"depth":463,"links":17132},[17133,17134,17135,17136,17137,17138,17139],{"id":16704,"depth":463,"text":16707},{"id":16749,"depth":463,"text":16752},{"id":16790,"depth":463,"text":16793},{"id":16854,"depth":463,"text":16857},{"id":16920,"depth":463,"text":16923},{"id":16967,"depth":463,"text":16970},{"id":17051,"depth":463,"text":17054},"content:fr:dette-technique:tests-integration-legacy-pieges.md","fr/dette-technique/tests-integration-legacy-pieges.md","fr/dette-technique/tests-integration-legacy-pieges",{"_path":17144,"_dir":484,"_draft":7,"_partial":7,"_locale":8,"title":17145,"description":17146,"id":6115,"date":17147,"listed":13,"nocomments":7,"hidden":7,"categories":17148,"tags":17149,"--cover":17154,"readingTime":17155,"body":17159,"_type":476,"_id":17828,"_source":478,"_file":17829,"_stem":17830,"_extension":481},"/fr/architecture-craft/event-storming-atelier-modelisation","Modélisation du domaine : l'atelier Event Storming en 3h","L'Event Storming est l'atelier le plus efficace pour aligner développeurs et experts métier en quelques heures. Le guide de facilitation sans formation préalable.","2026-02-18",[484],[17150,17151,17152,17153],"Event Storming","DDD","Modélisation","Atelier","covers/articles/event-storming-atelier.jpg",{"text":497,"minutes":17156,"time":17157,"words":17158},7.4,444000,1480,{"type":26,"children":17160,"toc":17818},[17161,17166,17171,17176,17181,17186,17189,17195,17200,17205,17210,17218,17246,17249,17255,17260,17268,17286,17294,17312,17322,17325,17331,17336,17343,17361,17369,17387,17396,17399,17405,17410,17417,17435,17445,17448,17454,17459,17466,17484,17492,17510,17527,17530,17536,17541,17564,17569,17597,17608,17611,17617,17733,17736,17742,17755,17768,17781,17794,17807,17810],{"type":29,"tag":30,"props":17162,"children":17164},{"id":17163},"modélisation-du-domaine-latelier-event-storming-en-3h",[17165],{"type":35,"value":17145},{"type":29,"tag":37,"props":17167,"children":17168},{},[17169],{"type":35,"value":17170},"Chez un client dans la logistique (40 développeurs, 8 équipes, 4 ans de code accumulé), j'ai posé une question simple en réunion de lancement : \"Qu'est-ce qu'une commande dans votre système ?\"",{"type":29,"tag":37,"props":17172,"children":17173},{},[17174],{"type":35,"value":17175},"Quinze minutes de débat. Cinq définitions différentes. Deux équipes qui découvraient ce soir-là qu'elles ne parlaient pas du même objet depuis des mois.",{"type":29,"tag":37,"props":17177,"children":17178},{},[17179],{"type":35,"value":17180},"Pour l'équipe transport, une \"commande\" était un bon de préparation entrepôt. Pour l'équipe facturation, c'était une transaction client. Pour l'équipe livraison, c'était un shipment carrier. Ces trois concepts vivaient dans la même table de base de données. C'était la source de couplage et de bugs depuis 18 mois.",{"type":29,"tag":37,"props":17182,"children":17183},{},[17184],{"type":35,"value":17185},"Un atelier Event Storming de 3 heures a produit la clarté que 18 mois de réunions n'avaient pas donnée. Voici comment le reproduire.",{"type":29,"tag":76,"props":17187,"children":17188},{},[],{"type":29,"tag":80,"props":17190,"children":17192},{"id":17191},"pourquoi-levent-storming-fonctionne-là-où-les-réunions-échouent",[17193],{"type":35,"value":17194},"Pourquoi l'Event Storming fonctionne là où les réunions échouent",{"type":29,"tag":37,"props":17196,"children":17197},{},[17198],{"type":35,"value":17199},"Le problème numéro un dans le développement de systèmes complexes n'est pas technique. C'est que les développeurs et les experts métier parlent des langages différents pendant des mois, et que cette incompréhension se retrouve encodée dans l'architecture.",{"type":29,"tag":37,"props":17201,"children":17202},{},[17203],{"type":35,"value":17204},"Alberto Brandolini a créé l'Event Storming en 2013 comme une alternative aux longues sessions de recueil de besoins qui produisent des spécifications incompréhensibles. L'idée est radicale dans sa simplicité : rassembler toutes les parties prenantes dans une pièce avec des post-its de couleur, et modéliser le domaine par les événements qui s'y produisent, pas par les entités, pas par les processus, pas par les données.",{"type":29,"tag":37,"props":17206,"children":17207},{},[17208],{"type":35,"value":17209},"En 3 heures, une équipe peut atteindre une compréhension partagée qu'elle n'aurait pas obtenue en 3 mois de réunions classiques. J'ai facilité plus de 30 sessions de ce type dans des secteurs aussi différents que la finance (Crédit Agricole), les médias (Canal+) et la logistique.",{"type":29,"tag":37,"props":17211,"children":17212},{},[17213],{"type":29,"tag":65,"props":17214,"children":17215},{},[17216],{"type":35,"value":17217},"Ce dont vous avez besoin :",{"type":29,"tag":1080,"props":17219,"children":17220},{},[17221,17226,17231,17236,17241],{"type":29,"tag":1084,"props":17222,"children":17223},{},[17224],{"type":35,"value":17225},"Une grande surface murale (minimum 3 mètres linéaires) ou Miro/Mural pour le remote",{"type":29,"tag":1084,"props":17227,"children":17228},{},[17229],{"type":35,"value":17230},"Post-its de 5 couleurs : orange (domain events), bleu (commands), jaune (aggregates), rose (external systems), rouge (hotspots/questions)",{"type":29,"tag":1084,"props":17232,"children":17233},{},[17234],{"type":35,"value":17235},"5 à 12 participants : développeurs, domain experts, PO, et éventuellement le CTO",{"type":29,"tag":1084,"props":17237,"children":17238},{},[17239],{"type":35,"value":17240},"Un facilitateur (qui peut être vous) qui connaît les étapes",{"type":29,"tag":1084,"props":17242,"children":17243},{},[17244],{"type":35,"value":17245},"3 heures sans interruption",{"type":29,"tag":76,"props":17247,"children":17248},{},[],{"type":29,"tag":80,"props":17250,"children":17252},{"id":17251},"étape-1-les-domain-events-en-orange-30-min",[17253],{"type":35,"value":17254},"Étape 1 : Les Domain Events en orange (30 min)",{"type":29,"tag":37,"props":17256,"children":17257},{},[17258],{"type":35,"value":17259},"Un Domain Event est quelque chose qui s'est passé dans le domaine et qui a de l'importance business. Il se formule toujours au passé : \"Commande passée\", \"Paiement reçu\", \"Stock mis à jour\", \"Email de confirmation envoyé\".",{"type":29,"tag":37,"props":17261,"children":17262},{},[17263],{"type":29,"tag":65,"props":17264,"children":17265},{},[17266],{"type":35,"value":17267},"Déroulé :",{"type":29,"tag":14624,"props":17269,"children":17270},{},[17271,17276,17281],{"type":29,"tag":1084,"props":17272,"children":17273},{},[17274],{"type":35,"value":17275},"Chaque participant écrit des événements sur des post-its orange (5 à 10 minutes en silence)",{"type":29,"tag":1084,"props":17277,"children":17278},{},[17279],{"type":35,"value":17280},"Tout le monde colle ses post-its sur le mur",{"type":29,"tag":1084,"props":17282,"children":17283},{},[17284],{"type":35,"value":17285},"Le facilitateur regroupe les événements chronologiquement, de gauche à droite",{"type":29,"tag":37,"props":17287,"children":17288},{},[17289],{"type":29,"tag":65,"props":17290,"children":17291},{},[17292],{"type":35,"value":17293},"Ce que je cherche en tant que facilitateur :",{"type":29,"tag":1080,"props":17295,"children":17296},{},[17297,17302,17307],{"type":29,"tag":1084,"props":17298,"children":17299},{},[17300],{"type":35,"value":17301},"Les doublons (deux termes pour le même événement → discussion sur le terme canonique)",{"type":29,"tag":1084,"props":17303,"children":17304},{},[17305],{"type":35,"value":17306},"Les contradictions (même nom pour des événements différents → signal de problème de domaine)",{"type":29,"tag":1084,"props":17308,"children":17309},{},[17310],{"type":35,"value":17311},"Les trous dans la timeline (il manque des événements entre deux étapes)",{"type":29,"tag":37,"props":17313,"children":17314},{},[17315,17320],{"type":29,"tag":65,"props":17316,"children":17317},{},[17318],{"type":35,"value":17319},"Règle absolue :",{"type":35,"value":17321}," à cette étape, pas de jugement. Tout ce qui peut se passer est bienvenu, même les événements d'erreur et les cas limites. Les \"ce n'est pas un vrai événement\" de la première heure sont souvent les plus révélateurs.",{"type":29,"tag":76,"props":17323,"children":17324},{},[],{"type":29,"tag":80,"props":17326,"children":17328},{"id":17327},"étape-2-les-commands-en-bleu-30-min",[17329],{"type":35,"value":17330},"Étape 2 : Les Commands en bleu (30 min)",{"type":29,"tag":37,"props":17332,"children":17333},{},[17334],{"type":35,"value":17335},"Une Command est ce qui déclenche un Domain Event. C'est une intention, une décision : \"Passer une commande\", \"Valider le paiement\", \"Envoyer la notification\".",{"type":29,"tag":37,"props":17337,"children":17338},{},[17339],{"type":29,"tag":65,"props":17340,"children":17341},{},[17342],{"type":35,"value":17267},{"type":29,"tag":14624,"props":17344,"children":17345},{},[17346,17351,17356],{"type":29,"tag":1084,"props":17347,"children":17348},{},[17349],{"type":35,"value":17350},"Pour chaque Domain Event sur le mur, je demande : \"Qu'est-ce qui déclenche cet événement ?\"",{"type":29,"tag":1084,"props":17352,"children":17353},{},[17354],{"type":35,"value":17355},"Ajouter le post-it bleu (Command) à gauche du post-it orange correspondant",{"type":29,"tag":1084,"props":17357,"children":17358},{},[17359],{"type":35,"value":17360},"Identifier qui émet la Command : un utilisateur, un système automatique, un timer",{"type":29,"tag":37,"props":17362,"children":17363},{},[17364],{"type":29,"tag":65,"props":17365,"children":17366},{},[17367],{"type":35,"value":17368},"Ce que cette étape révèle :",{"type":29,"tag":1080,"props":17370,"children":17371},{},[17372,17377,17382],{"type":29,"tag":1084,"props":17373,"children":17374},{},[17375],{"type":35,"value":17376},"Les décisions implicites du domaine (certains événements se produisent sans command explicite → probable automatisme ou logique métier cachée)",{"type":29,"tag":1084,"props":17378,"children":17379},{},[17380],{"type":35,"value":17381},"Les acteurs du système (qui décide quoi)",{"type":29,"tag":1084,"props":17383,"children":17384},{},[17385],{"type":35,"value":17386},"Les règles métier qui gouvernent les commands",{"type":29,"tag":176,"props":17388,"children":17390},{"cta":178,"href":179,"title":17389,"type":181},"Votre équipe développe sans modèle de domaine partagé et les malentendus métier se retrouvent dans le code ?",[17391],{"type":29,"tag":37,"props":17392,"children":17393},{},[17394],{"type":35,"value":17395},"Faciliter un Event Storming pour la première fois sans expérience, c'est prendre le risque d'un atelier qui part dans tous les sens. En 30 minutes, on peut définir la stratégie d'atelier adaptée à votre contexte et votre domaine, et préparer le facilitateur pour une session qui produit de vrais résultats.",{"type":29,"tag":76,"props":17397,"children":17398},{},[],{"type":29,"tag":80,"props":17400,"children":17402},{"id":17401},"étape-3-les-aggregates-en-jaune-45-min",[17403],{"type":35,"value":17404},"Étape 3 : Les Aggregates en jaune (45 min)",{"type":29,"tag":37,"props":17406,"children":17407},{},[17408],{"type":35,"value":17409},"Un Aggregate est l'entité ou le concept qui traite une Command et produit un Domain Event. C'est l'unité de cohérence du domaine, le concept central du Domain-Driven Design tel que formalisé par Eric Evans.",{"type":29,"tag":37,"props":17411,"children":17412},{},[17413],{"type":29,"tag":65,"props":17414,"children":17415},{},[17416],{"type":35,"value":17267},{"type":29,"tag":14624,"props":17418,"children":17419},{},[17420,17425,17430],{"type":29,"tag":1084,"props":17421,"children":17422},{},[17423],{"type":35,"value":17424},"Pour chaque paire Command → Domain Event, demander : \"Quelle entité traite cette commande et garantit que l'événement est produit correctement ?\"",{"type":29,"tag":1084,"props":17426,"children":17427},{},[17428],{"type":35,"value":17429},"Placer un post-it jaune entre la Command et le Domain Event avec le nom de l'Aggregate",{"type":29,"tag":1084,"props":17431,"children":17432},{},[17433],{"type":35,"value":17434},"Regrouper les paires Command/Event qui partagent le même Aggregate",{"type":29,"tag":37,"props":17436,"children":17437},{},[17438,17443],{"type":29,"tag":65,"props":17439,"children":17440},{},[17441],{"type":35,"value":17442},"L'exercice révélateur :",{"type":35,"value":17444},"\nQuand deux participants donnent des noms différents pour le même Aggregate, c'est un signal fort : soit c'est un problème de vocabulaire à résoudre, soit ce sont deux Aggregates distincts qui ont été confondus et qu'il faut séparer. Ce moment-là est souvent le plus productif de l'atelier.",{"type":29,"tag":76,"props":17446,"children":17447},{},[],{"type":29,"tag":80,"props":17449,"children":17451},{"id":17450},"étape-4-les-bounded-contexts-45-min",[17452],{"type":35,"value":17453},"Étape 4 : Les Bounded Contexts (45 min)",{"type":29,"tag":37,"props":17455,"children":17456},{},[17457],{"type":35,"value":17458},"Un Bounded Context est une frontière dans le modèle de domaine où le même terme peut avoir un sens différent, ou où des équipes différentes travaillent de façon indépendante.",{"type":29,"tag":37,"props":17460,"children":17461},{},[17462],{"type":29,"tag":65,"props":17463,"children":17464},{},[17465],{"type":35,"value":17267},{"type":29,"tag":14624,"props":17467,"children":17468},{},[17469,17474,17479],{"type":29,"tag":1084,"props":17470,"children":17471},{},[17472],{"type":35,"value":17473},"Observer le mur et identifier les clusters naturels d'Aggregates qui travaillent ensemble",{"type":29,"tag":1084,"props":17475,"children":17476},{},[17477],{"type":35,"value":17478},"Tracer des frontières visuelles entre les clusters",{"type":29,"tag":1084,"props":17480,"children":17481},{},[17482],{"type":35,"value":17483},"Nommer chaque zone : \"Catalog\", \"Ordering\", \"Payment\", \"Fulfillment\"...",{"type":29,"tag":37,"props":17485,"children":17486},{},[17487],{"type":29,"tag":65,"props":17488,"children":17489},{},[17490],{"type":35,"value":17491},"Les questions qui révèlent les frontières :",{"type":29,"tag":1080,"props":17493,"children":17494},{},[17495,17500,17505],{"type":29,"tag":1084,"props":17496,"children":17497},{},[17498],{"type":35,"value":17499},"\"Est-ce que cette équipe parlerait à cette équipe directement, ou via un événement ?\"",{"type":29,"tag":1084,"props":17501,"children":17502},{},[17503],{"type":35,"value":17504},"\"Est-ce que le mot 'Customer' a le même sens dans ces deux zones ?\"",{"type":29,"tag":1084,"props":17506,"children":17507},{},[17508],{"type":35,"value":17509},"\"Ces deux zones peuvent-elles évoluer indépendamment ?\"",{"type":29,"tag":37,"props":17511,"children":17512},{},[17513,17518,17520,17525],{"type":29,"tag":65,"props":17514,"children":17515},{},[17516],{"type":35,"value":17517},"Les post-its rouges (Hotspots) :",{"type":35,"value":17519}," pendant tout l'atelier, quand une question reste sans réponse, je colle un post-it rouge. Ces hotspots sont les sujets à approfondir après l'atelier : ils révèlent les zones d'incertitude du domaine et deviennent la backlog des décisions architecturales à prendre. Ces décisions méritent d'être formalisées dans des ",{"type":29,"tag":48,"props":17521,"children":17522},{"href":610},[17523],{"type":35,"value":17524},"Architecture Decision Records",{"type":35,"value":17526}," pour garder la trace du contexte et des choix effectués.",{"type":29,"tag":76,"props":17528,"children":17529},{},[],{"type":29,"tag":80,"props":17531,"children":17533},{"id":17532},"ce-que-latelier-produit",[17534],{"type":35,"value":17535},"Ce que l'atelier produit",{"type":29,"tag":37,"props":17537,"children":17538},{},[17539],{"type":35,"value":17540},"À l'issue des 3 heures, vous disposez de :",{"type":29,"tag":1080,"props":17542,"children":17543},{},[17544,17549,17554,17559],{"type":29,"tag":1084,"props":17545,"children":17546},{},[17547],{"type":35,"value":17548},"Une timeline des Domain Events qui représente le flux complet du domaine",{"type":29,"tag":1084,"props":17550,"children":17551},{},[17552],{"type":35,"value":17553},"Une carte des Commands et des acteurs",{"type":29,"tag":1084,"props":17555,"children":17556},{},[17557],{"type":35,"value":17558},"Une carte des Aggregates et de leurs responsabilités",{"type":29,"tag":1084,"props":17560,"children":17561},{},[17562],{"type":35,"value":17563},"Des Bounded Contexts qui suggèrent les frontières de services",{"type":29,"tag":37,"props":17565,"children":17566},{},[17567],{"type":35,"value":17568},"Ce modèle n'est pas une spec technique. C'est une langue commune entre développeurs et experts métier. Il guide directement :",{"type":29,"tag":1080,"props":17570,"children":17571},{},[17572,17582,17587,17592],{"type":29,"tag":1084,"props":17573,"children":17574},{},[17575,17577],{"type":35,"value":17576},"La définition des microservices (1 service par Bounded Context dans la plupart des cas), et par conséquent les décisions sur le ",{"type":29,"tag":48,"props":17578,"children":17579},{"href":483},[17580],{"type":35,"value":17581},"découpage des bases de données par service",{"type":29,"tag":1084,"props":17583,"children":17584},{},[17585],{"type":35,"value":17586},"Le design des APIs (les Commands deviennent les endpoints)",{"type":29,"tag":1084,"props":17588,"children":17589},{},[17590],{"type":35,"value":17591},"La modélisation de la base de données (les Aggregates deviennent les tables ou collections)",{"type":29,"tag":1084,"props":17593,"children":17594},{},[17595],{"type":35,"value":17596},"L'écriture des tests (les Domain Events deviennent les scénarios de test)",{"type":29,"tag":37,"props":17598,"children":17599},{},[17600,17602,17606],{"type":35,"value":17601},"Chez le client logistique que j'évoquais en ouverture, l'atelier a révélé que l'\"Order\" était conceptuellement 3 choses différentes. Ces 3 concepts ont été extraits en 3 services distincts, chacun avec son architecture bien délimitée, en s'appuyant notamment sur les principes de la ",{"type":29,"tag":48,"props":17603,"children":17604},{"href":5136},[17605],{"type":35,"value":5139},{"type":35,"value":17607}," pour garantir l'indépendance des couches. Les bugs liés au couplage ont disparu dans les 6 semaines suivantes.",{"type":29,"tag":76,"props":17609,"children":17610},{},[],{"type":29,"tag":80,"props":17612,"children":17614},{"id":17613},"récapitulatif",[17615],{"type":35,"value":17616},"Récapitulatif",{"type":29,"tag":714,"props":17618,"children":17619},{},[17620,17644],{"type":29,"tag":718,"props":17621,"children":17622},{},[17623],{"type":29,"tag":722,"props":17624,"children":17625},{},[17626,17630,17635,17640],{"type":29,"tag":726,"props":17627,"children":17628},{},[17629],{"type":35,"value":12991},{"type":29,"tag":726,"props":17631,"children":17632},{},[17633],{"type":35,"value":17634},"Durée",{"type":29,"tag":726,"props":17636,"children":17637},{},[17638],{"type":35,"value":17639},"Post-it",{"type":29,"tag":726,"props":17641,"children":17642},{},[17643],{"type":35,"value":13001},{"type":29,"tag":742,"props":17645,"children":17646},{},[17647,17669,17690,17712],{"type":29,"tag":722,"props":17648,"children":17649},{},[17650,17654,17659,17664],{"type":29,"tag":749,"props":17651,"children":17652},{},[17653],{"type":35,"value":13012},{"type":29,"tag":749,"props":17655,"children":17656},{},[17657],{"type":35,"value":17658},"30 min",{"type":29,"tag":749,"props":17660,"children":17661},{},[17662],{"type":35,"value":17663},"Orange : Domain Events",{"type":29,"tag":749,"props":17665,"children":17666},{},[17667],{"type":35,"value":17668},"Timeline du domaine",{"type":29,"tag":722,"props":17670,"children":17671},{},[17672,17676,17680,17685],{"type":29,"tag":749,"props":17673,"children":17674},{},[17675],{"type":35,"value":13030},{"type":29,"tag":749,"props":17677,"children":17678},{},[17679],{"type":35,"value":17658},{"type":29,"tag":749,"props":17681,"children":17682},{},[17683],{"type":35,"value":17684},"Bleu : Commands",{"type":29,"tag":749,"props":17686,"children":17687},{},[17688],{"type":35,"value":17689},"Déclencheurs et acteurs",{"type":29,"tag":722,"props":17691,"children":17692},{},[17693,17697,17702,17707],{"type":29,"tag":749,"props":17694,"children":17695},{},[17696],{"type":35,"value":13048},{"type":29,"tag":749,"props":17698,"children":17699},{},[17700],{"type":35,"value":17701},"45 min",{"type":29,"tag":749,"props":17703,"children":17704},{},[17705],{"type":35,"value":17706},"Jaune : Aggregates",{"type":29,"tag":749,"props":17708,"children":17709},{},[17710],{"type":35,"value":17711},"Entités et responsabilités",{"type":29,"tag":722,"props":17713,"children":17714},{},[17715,17719,17723,17728],{"type":29,"tag":749,"props":17716,"children":17717},{},[17718],{"type":35,"value":13066},{"type":29,"tag":749,"props":17720,"children":17721},{},[17722],{"type":35,"value":17701},{"type":29,"tag":749,"props":17724,"children":17725},{},[17726],{"type":35,"value":17727},"Frontières visuelles",{"type":29,"tag":749,"props":17729,"children":17730},{},[17731],{"type":35,"value":17732},"Bounded Contexts",{"type":29,"tag":76,"props":17734,"children":17735},{},[],{"type":29,"tag":80,"props":17737,"children":17739},{"id":17738},"faq-sur-levent-storming",[17740],{"type":35,"value":17741},"FAQ sur l'Event Storming",{"type":29,"tag":381,"props":17743,"children":17744},{},[17745,17750],{"type":29,"tag":385,"props":17746,"children":17747},{},[17748],{"type":35,"value":17749},"1. Faut-il connaître DDD pour faciliter un Event Storming ?",{"type":29,"tag":37,"props":17751,"children":17752},{},[17753],{"type":35,"value":17754},"Non. Les concepts fondamentaux (Domain Events, Commands, Aggregates, Bounded Contexts) peuvent s'expliquer en 5 minutes en début de session. L'Event Storming est conçu pour être accessible aux non-DDD. C'est d'ailleurs sa force : il permet aux domain experts, qui ne connaissent pas DDD, de contribuer activement. Un facilitateur qui comprend l'objectif de chaque étape est suffisant pour un premier atelier.",{"type":29,"tag":381,"props":17756,"children":17757},{},[17758,17763],{"type":29,"tag":385,"props":17759,"children":17760},{},[17761],{"type":35,"value":17762},"2. L'Event Storming fonctionne-t-il en remote ?",{"type":29,"tag":37,"props":17764,"children":17765},{},[17766],{"type":35,"value":17767},"Oui, avec des outils comme Miro ou Mural. Les ateliers en remote sont légèrement moins dynamiques (les conversations parallèles sont plus difficiles à gérer), mais produisent des résultats comparables. Mes conseils pour le remote : prévoir des breakout rooms pour les sous-groupes, utiliser le timer visible de l'outil, et allouer 30 minutes supplémentaires pour les latences de communication. J'ai facilité des sessions jusqu'à 10 participants en remote avec de bons résultats.",{"type":29,"tag":381,"props":17769,"children":17770},{},[17771,17776],{"type":29,"tag":385,"props":17772,"children":17773},{},[17774],{"type":35,"value":17775},"3. Quelle est la taille idéale du groupe ?",{"type":29,"tag":37,"props":17777,"children":17778},{},[17779],{"type":35,"value":17780},"5 à 12 personnes. En dessous de 5, on manque de perspectives et les angles morts sont nombreux. Au-dessus de 12, la coordination devient difficile et certains participants restent passifs. Pour les grands domaines, plusieurs sessions Event Storming sur des sous-domaines sont préférables à une seule session avec 20 personnes.",{"type":29,"tag":381,"props":17782,"children":17783},{},[17784,17789],{"type":29,"tag":385,"props":17785,"children":17786},{},[17787],{"type":35,"value":17788},"4. Que faire avec le résultat de l'atelier ? Comment le maintenir à jour ?",{"type":29,"tag":37,"props":17790,"children":17791},{},[17792],{"type":35,"value":17793},"Je recommande de photographier et numériser le mur immédiatement après l'atelier. Créer une page de documentation dans Confluence ou Notion avec les photos annotées et les décisions clés. Le modèle de domaine doit évoluer avec le domaine : prévoir un Event Storming de mise à jour tous les 6 à 12 mois, ou quand une refonte significative du domaine est envisagée.",{"type":29,"tag":381,"props":17795,"children":17796},{},[17797,17802],{"type":29,"tag":385,"props":17798,"children":17799},{},[17800],{"type":35,"value":17801},"5. L'Event Storming peut-il s'appliquer à un domaine technique (infrastructure, CI/CD) plutôt que métier ?",{"type":29,"tag":37,"props":17803,"children":17804},{},[17805],{"type":35,"value":17806},"Oui, avec adaptation. On parle alors de \"Process Modelling Event Storm\", la même technique appliquée aux processus techniques. Les Domain Events deviennent des événements de pipeline (\"Build triggered\", \"Tests failed\", \"Deployment rolled back\"). C'est utile pour modéliser et améliorer les processus de delivery, et j'ai utilisé ce format pour restructurer des pipelines CI/CD chez plusieurs clients.",{"type":29,"tag":76,"props":17808,"children":17809},{},[],{"type":29,"tag":176,"props":17811,"children":17812},{"cta":1243,"href":1244,"title":454,"type":455},[17813],{"type":29,"tag":37,"props":17814,"children":17815},{},[17816],{"type":35,"value":17817},"L'Engineering Maturity Self-Assessment couvre le domaine Architecture & Modélisation : évaluez votre niveau de maturité sur la conception du domaine, le découplage, et les pratiques de modélisation. Résultat en 10 minutes, plan d'action inclus.",{"title":8,"searchDepth":463,"depth":463,"links":17819},[17820,17821,17822,17823,17824,17825,17826,17827],{"id":17191,"depth":463,"text":17194},{"id":17251,"depth":463,"text":17254},{"id":17327,"depth":463,"text":17330},{"id":17401,"depth":463,"text":17404},{"id":17450,"depth":463,"text":17453},{"id":17532,"depth":463,"text":17535},{"id":17613,"depth":463,"text":17616},{"id":17738,"depth":463,"text":17741},"content:fr:architecture-craft:event-storming-atelier-modelisation.md","fr/architecture-craft/event-storming-atelier-modelisation.md","fr/architecture-craft/event-storming-atelier-modelisation",{"_path":2024,"_dir":1271,"_draft":7,"_partial":7,"_locale":8,"title":17832,"description":17833,"id":6063,"date":17834,"listed":13,"nocomments":7,"hidden":7,"categories":17835,"tags":17836,"--cover":17839,"readingTime":17840,"body":17844,"_type":476,"_id":18499,"_source":478,"_file":18500,"_stem":18501,"_extension":481},"L'entretien annuel d'un développeur : le format qui fonctionne vraiment","L'entretien annuel redouté est souvent une formalité RH sans impact. Transformé correctement, c'est le moment de carrière le plus important de l'année pour un développeur.","2026-02-16",[1271],[17837,17838,1279],"Entretien Annuel","Développement Carrière","covers/articles/entretien-annuel-developpeur.jpg",{"text":497,"minutes":17841,"time":17842,"words":17843},7.325,439500,1465,{"type":26,"children":17845,"toc":18486},[17846,17851,17856,17861,17880,17883,17889,17894,17899,17911,17914,17920,17930,17938,17966,17971,17974,17980,17986,17991,17996,18002,18007,18012,18021,18024,18030,18035,18043,18085,18090,18108,18124,18130,18135,18145,18155,18165,18168,18174,18179,18202,18207,18210,18214,18381,18384,18390,18409,18422,18442,18462,18475,18478],{"type":29,"tag":30,"props":17847,"children":17849},{"id":17848},"lentretien-annuel-dun-développeur-le-format-qui-fonctionne-vraiment",[17850],{"type":35,"value":17832},{"type":29,"tag":37,"props":17852,"children":17853},{},[17854],{"type":35,"value":17855},"J'ai conduit des entretiens annuels pendant des années avec un formulaire RH standard. Cinq questions génériques, une note sur une échelle de 1 à 5, une case \"commentaires\" que tout le monde remplissait avec des généralités. À Canal+, j'ai eu le cas d'un développeur senior (7 ans dans l'organisation, excellente technique) qui a remis sa démission deux semaines après son entretien annuel. Sa raison : \"Personne ne m'a jamais demandé où je voulais aller.\" Il avait passé 7 ans dans l'organisation sans qu'un seul entretien annuel aborde réellement ses aspirations de carrière.",{"type":29,"tag":37,"props":17857,"children":17858},{},[17859],{"type":35,"value":17860},"Je n'ai pas refait la même erreur.",{"type":29,"tag":37,"props":17862,"children":17863},{},[17864,17866,17871,17873,17878],{"type":35,"value":17865},"Selon une étude LinkedIn de 2023, ",{"type":29,"tag":65,"props":17867,"children":17868},{},[17869],{"type":35,"value":17870},"62% des développeurs",{"type":35,"value":17872}," citent l'absence de perspectives de carrière comme principale raison de chercher un nouveau poste. Pas la rémunération. Les perspectives. Et les perspectives, c'est précisément ce que l'entretien annuel bien conduit est censé créer. Dans un marché du talent technique où le coût de remplacement d'un développeur senior atteint ",{"type":29,"tag":65,"props":17874,"children":17875},{},[17876],{"type":35,"value":17877},"65 000 à 130 000€",{"type":35,"value":17879},", l'entretien annuel n'est pas une formalité RH. C'est un investissement de rétention.",{"type":29,"tag":76,"props":17881,"children":17882},{},[],{"type":29,"tag":80,"props":17884,"children":17886},{"id":17885},"ce-que-lentretien-annuel-nest-pas",[17887],{"type":35,"value":17888},"Ce que l'entretien annuel n'est pas",{"type":29,"tag":37,"props":17890,"children":17891},{},[17892],{"type":35,"value":17893},"Avant de décrire le format, je veux être clair sur ce que cet entretien ne doit pas être.",{"type":29,"tag":37,"props":17895,"children":17896},{},[17897],{"type":35,"value":17898},"Ce n'est pas un bilan de performance descendant où le manager évalue et le développeur écoute. Ce n'est pas une liste de cases cochées sur les objectifs fixés un an plus tôt. Et surtout, je l'ai appris à mes dépens, ce n'est pas la même réunion que la révision salariale.",{"type":29,"tag":37,"props":17900,"children":17901},{},[17902,17904,17909],{"type":35,"value":17903},"Camille Fournier le décrit précisément dans ",{"type":29,"tag":9942,"props":17905,"children":17906},{},[17907],{"type":35,"value":17908},"The Manager's Path",{"type":35,"value":17910}," : l'entretien annuel doit être un espace de développement, pas d'évaluation. L'évaluation crée de la défensivité. Le développement crée de l'engagement.",{"type":29,"tag":76,"props":17912,"children":17913},{},[],{"type":29,"tag":80,"props":17915,"children":17917},{"id":17916},"la-préparation-ce-qui-se-passe-avant-le-jour-j",[17918],{"type":35,"value":17919},"La préparation : ce qui se passe avant le jour J",{"type":29,"tag":37,"props":17921,"children":17922},{},[17923,17928],{"type":29,"tag":65,"props":17924,"children":17925},{},[17926],{"type":35,"value":17927},"Dix jours avant l'entretien",{"type":35,"value":17929},", j'envoie au développeur un questionnaire de préparation de 5 questions. L'entretien ne commence pas le jour J : il commence quand le développeur a eu le temps de réfléchir.",{"type":29,"tag":37,"props":17931,"children":17932},{},[17933],{"type":29,"tag":65,"props":17934,"children":17935},{},[17936],{"type":35,"value":17937},"Le questionnaire :",{"type":29,"tag":14624,"props":17939,"children":17940},{},[17941,17946,17951,17956,17961],{"type":29,"tag":1084,"props":17942,"children":17943},{},[17944],{"type":35,"value":17945},"\"Quelles ont été tes 2-3 contributions les plus significatives cette année ? Pas les plus visibles, les plus impactantes selon toi.\"",{"type":29,"tag":1084,"props":17947,"children":17948},{},[17949],{"type":35,"value":17950},"\"Qu'as-tu appris cette année qui a changé ta façon de travailler ?\"",{"type":29,"tag":1084,"props":17952,"children":17953},{},[17954],{"type":35,"value":17955},"\"Sur une échelle de 1 à 10, où te sens-tu par rapport à ton potentiel actuel ? Qu'est-ce qui t'empêche d'être à 10 ?\"",{"type":29,"tag":1084,"props":17957,"children":17958},{},[17959],{"type":35,"value":17960},"\"Dans quelles directions voudrais-tu évoluer dans les 12 à 24 prochains mois ?\"",{"type":29,"tag":1084,"props":17962,"children":17963},{},[17964],{"type":35,"value":17965},"\"Y a-t-il des sujets que tu veux aborder et que tu n'as pas pu aborder en 1-on-1 ?\"",{"type":29,"tag":37,"props":17967,"children":17968},{},[17969],{"type":35,"value":17970},"Je lis les réponses avant l'entretien et je prépare mes propres réflexions sur ces mêmes questions, en particulier les questions 3 et 4 du point de vue de l'équipe et de l'organisation.",{"type":29,"tag":76,"props":17972,"children":17973},{},[],{"type":29,"tag":80,"props":17975,"children":17977},{"id":17976},"la-structure-en-4-blocs-90-minutes",[17978],{"type":35,"value":17979},"La structure en 4 blocs (90 minutes)",{"type":29,"tag":116,"props":17981,"children":17983},{"id":17982},"bloc-1-rétrospective-25-min",[17984],{"type":35,"value":17985},"Bloc 1 : Rétrospective (25 min)",{"type":29,"tag":37,"props":17987,"children":17988},{},[17989],{"type":35,"value":17990},"Le développeur présente ses réponses aux questions 1 et 2. J'écoute d'abord, vraiment, sans interrompre. Puis j'ajoute ma perspective sur les contributions de l'année, en commençant par ce que le développeur n'a pas cité mais qui a eu de l'impact.",{"type":29,"tag":37,"props":17992,"children":17993},{},[17994],{"type":35,"value":17995},"Ce que je ne fais pas dans ce bloc : transformer la rétrospective en évaluation notée. L'objectif est de reconnaître la contribution et de construire une perspective partagée sur l'année. La reconnaissance explicite est souvent absente dans les environnements techniques, et son absence est la principale cause du syndrome de l'imposteur chez des développeurs compétents.",{"type":29,"tag":116,"props":17997,"children":17999},{"id":17998},"bloc-2-diagnostic-honnête-20-min",[18000],{"type":35,"value":18001},"Bloc 2 : Diagnostic honnête (20 min)",{"type":29,"tag":37,"props":18003,"children":18004},{},[18005],{"type":35,"value":18006},"La question 3 est la plus difficile et la plus importante. Elle ouvre l'espace pour parler de ce qui bloque, de ce qui frustre, et de ce qui manque.",{"type":29,"tag":37,"props":18008,"children":18009},{},[18010],{"type":35,"value":18011},"J'écoute sans défendre. Si le développeur exprime une frustration sur le management (délégation insuffisante, visibilité insuffisante, manque de reconnaissance), c'est de l'information précieuse, pas une attaque personnelle. Ce qui sort de ce bloc : une liste de 2 à 3 conditions manquantes pour que le développeur soit à 9 ou 10 sur 10. Ces conditions deviennent les engagements de l'organisation pour l'année suivante.",{"type":29,"tag":176,"props":18013,"children":18015},{"cta":178,"href":179,"title":18014,"type":181},"Vos entretiens annuels ne changent rien et vos meilleurs développeurs cherchent ailleurs ?",[18016],{"type":29,"tag":37,"props":18017,"children":18018},{},[18019],{"type":35,"value":18020},"L'entretien annuel inefficace est souvent le symptôme d'un problème plus profond : absence de parcours de carrière structuré, 1-on-1 inexistants, ou culture qui ne valorise pas le développement individuel. En 30 minutes, je peux identifier la vraie cause dans votre organisation et définir le plan d'action concret pour retenir vos profils clés.",{"type":29,"tag":76,"props":18022,"children":18023},{},[],{"type":29,"tag":116,"props":18025,"children":18027},{"id":18026},"bloc-3-plan-de-développement-30-min",[18028],{"type":35,"value":18029},"Bloc 3 : Plan de développement (30 min)",{"type":29,"tag":37,"props":18031,"children":18032},{},[18033],{"type":35,"value":18034},"La question 4 du questionnaire. Discussion ouverte sur les ambitions à 12 à 24 mois.",{"type":29,"tag":37,"props":18036,"children":18037},{},[18038],{"type":29,"tag":65,"props":18039,"children":18040},{},[18041],{"type":35,"value":18042},"Les 4 directions de carrière légitimes pour un développeur :",{"type":29,"tag":1080,"props":18044,"children":18045},{},[18046,18056,18066,18075],{"type":29,"tag":1084,"props":18047,"children":18048},{},[18049,18054],{"type":29,"tag":65,"props":18050,"children":18051},{},[18052],{"type":35,"value":18053},"Expert technique",{"type":35,"value":18055}," : approfondissement d'une compétence (architecture, sécurité, data, IA), jusqu'au niveau staff engineer ou principal engineer",{"type":29,"tag":1084,"props":18057,"children":18058},{},[18059,18064],{"type":29,"tag":65,"props":18060,"children":18061},{},[18062],{"type":35,"value":18063},"Lead technique",{"type":35,"value":18065}," : coordination, mentorat, design technique",{"type":29,"tag":1084,"props":18067,"children":18068},{},[18069,18073],{"type":29,"tag":65,"props":18070,"children":18071},{},[18072],{"type":35,"value":1279},{"type":35,"value":18074}," : équipe puis organisation",{"type":29,"tag":1084,"props":18076,"children":18077},{},[18078,18083],{"type":29,"tag":65,"props":18079,"children":18080},{},[18081],{"type":35,"value":18082},"Autre",{"type":35,"value":18084}," : product, data, autre domaine métier",{"type":29,"tag":37,"props":18086,"children":18087},{},[18088],{"type":35,"value":18089},"Pour chaque direction souhaitée, je définis avec le développeur :",{"type":29,"tag":1080,"props":18091,"children":18092},{},[18093,18098,18103],{"type":29,"tag":1084,"props":18094,"children":18095},{},[18096],{"type":35,"value":18097},"Quelle est la prochaine étape concrète, pas \"devenir architecte\" mais \"contribuer à la conception du prochain système en pair avec le head of architecture\"",{"type":29,"tag":1084,"props":18099,"children":18100},{},[18101],{"type":35,"value":18102},"Quelles compétences sont à développer dans les 6 prochains mois",{"type":29,"tag":1084,"props":18104,"children":18105},{},[18106],{"type":35,"value":18107},"Quelles ressources l'organisation va allouer (formation, budget, temps dédié, mentorat)",{"type":29,"tag":37,"props":18109,"children":18110},{},[18111,18122],{"type":29,"tag":65,"props":18112,"children":18113},{},[18114,18116,18120],{"type":35,"value":18115},"Ce que j'ai appris de ",{"type":29,"tag":9942,"props":18117,"children":18118},{},[18119],{"type":35,"value":17908},{"type":35,"value":18121}," de Camille Fournier :",{"type":35,"value":18123}," si votre organisation n'a que \"développeur → manager\" comme seul chemin de progression, c'est un problème structurel. Les meilleurs experts techniques partent précisément parce qu'ils ne veulent pas gérer des équipes, et qu'on ne leur laisse pas d'autre option pour progresser.",{"type":29,"tag":116,"props":18125,"children":18127},{"id":18126},"bloc-4-le-contrat-15-min",[18128],{"type":35,"value":18129},"Bloc 4 : Le contrat (15 min)",{"type":29,"tag":37,"props":18131,"children":18132},{},[18133],{"type":35,"value":18134},"Les engagements réciproques pour les 12 prochains mois.",{"type":29,"tag":37,"props":18136,"children":18137},{},[18138,18143],{"type":29,"tag":65,"props":18139,"children":18140},{},[18141],{"type":35,"value":18142},"Le développeur s'engage sur :",{"type":35,"value":18144}," les compétences à développer, les comportements à faire évoluer, la visibilité à gagner.",{"type":29,"tag":37,"props":18146,"children":18147},{},[18148,18153],{"type":29,"tag":65,"props":18149,"children":18150},{},[18151],{"type":35,"value":18152},"Je m'engage sur :",{"type":35,"value":18154}," les opportunités à créer (projets, formations, mentorat), les obstacles à lever, les conditions à améliorer identifiées en Bloc 2.",{"type":29,"tag":37,"props":18156,"children":18157},{},[18158,18163],{"type":29,"tag":65,"props":18159,"children":18160},{},[18161],{"type":35,"value":18162},"Ma règle absolue :",{"type":35,"value":18164}," ne promettre que ce qu'on peut tenir. Un engagement non-tenu détruit plus de confiance que de ne rien promettre. Si une promotion n'est pas possible dans les 12 mois, je le dis clairement plutôt que de laisser l'espoir flotter. J'ai vu trop de développeurs partir en mauvais termes après des promesses implicites qui ne se sont pas concrétisées.",{"type":29,"tag":76,"props":18166,"children":18167},{},[],{"type":29,"tag":80,"props":18169,"children":18171},{"id":18170},"le-suivi-à-90-jours-le-seul-indicateur-qui-compte",[18172],{"type":35,"value":18173},"Le suivi à 90 jours : le seul indicateur qui compte",{"type":29,"tag":37,"props":18175,"children":18176},{},[18177],{"type":35,"value":18178},"L'entretien annuel n'a de valeur que si ses engagements sont suivis. À J+90, un 1-on-1 dédié de 30 minutes :",{"type":29,"tag":1080,"props":18180,"children":18181},{},[18182,18187,18192,18197],{"type":29,"tag":1084,"props":18183,"children":18184},{},[18185],{"type":35,"value":18186},"Quelles actions ont été entreprises ?",{"type":29,"tag":1084,"props":18188,"children":18189},{},[18190],{"type":35,"value":18191},"Quels progrès sont visibles ?",{"type":29,"tag":1084,"props":18193,"children":18194},{},[18195],{"type":35,"value":18196},"Quels obstacles sont apparus ?",{"type":29,"tag":1084,"props":18198,"children":18199},{},[18200],{"type":35,"value":18201},"Les engagements que j'ai pris ont-ils été tenus ?",{"type":29,"tag":37,"props":18203,"children":18204},{},[18205],{"type":35,"value":18206},"Ce suivi à 90 jours envoie un signal fort : l'entretien annuel n'est pas une formalité RH, c'est un engagement réel.",{"type":29,"tag":76,"props":18208,"children":18209},{},[],{"type":29,"tag":80,"props":18211,"children":18212},{"id":12974},[18213],{"type":35,"value":12977},{"type":29,"tag":714,"props":18215,"children":18216},{},[18217,18241],{"type":29,"tag":718,"props":18218,"children":18219},{},[18220],{"type":29,"tag":722,"props":18221,"children":18222},{},[18223,18228,18232,18237],{"type":29,"tag":726,"props":18224,"children":18225},{},[18226],{"type":35,"value":18227},"Bloc",{"type":29,"tag":726,"props":18229,"children":18230},{},[18231],{"type":35,"value":17634},{"type":29,"tag":726,"props":18233,"children":18234},{},[18235],{"type":35,"value":18236},"Contenu",{"type":29,"tag":726,"props":18238,"children":18239},{},[18240],{"type":35,"value":13001},{"type":29,"tag":742,"props":18242,"children":18243},{},[18244,18267,18290,18313,18335,18358],{"type":29,"tag":722,"props":18245,"children":18246},{},[18247,18252,18257,18262],{"type":29,"tag":749,"props":18248,"children":18249},{},[18250],{"type":35,"value":18251},"Préparation",{"type":29,"tag":749,"props":18253,"children":18254},{},[18255],{"type":35,"value":18256},"10 jours avant",{"type":29,"tag":749,"props":18258,"children":18259},{},[18260],{"type":35,"value":18261},"Questionnaire 5 questions",{"type":29,"tag":749,"props":18263,"children":18264},{},[18265],{"type":35,"value":18266},"Réflexion ancrée",{"type":29,"tag":722,"props":18268,"children":18269},{},[18270,18275,18280,18285],{"type":29,"tag":749,"props":18271,"children":18272},{},[18273],{"type":35,"value":18274},"Rétrospective",{"type":29,"tag":749,"props":18276,"children":18277},{},[18278],{"type":35,"value":18279},"25 min",{"type":29,"tag":749,"props":18281,"children":18282},{},[18283],{"type":35,"value":18284},"Contributions + apprentissages",{"type":29,"tag":749,"props":18286,"children":18287},{},[18288],{"type":35,"value":18289},"Reconnaissance partagée",{"type":29,"tag":722,"props":18291,"children":18292},{},[18293,18298,18303,18308],{"type":29,"tag":749,"props":18294,"children":18295},{},[18296],{"type":35,"value":18297},"Diagnostic",{"type":29,"tag":749,"props":18299,"children":18300},{},[18301],{"type":35,"value":18302},"20 min",{"type":29,"tag":749,"props":18304,"children":18305},{},[18306],{"type":35,"value":18307},"Ce qui bloque + frustrations",{"type":29,"tag":749,"props":18309,"children":18310},{},[18311],{"type":35,"value":18312},"Conditions à améliorer",{"type":29,"tag":722,"props":18314,"children":18315},{},[18316,18321,18325,18330],{"type":29,"tag":749,"props":18317,"children":18318},{},[18319],{"type":35,"value":18320},"Plan développement",{"type":29,"tag":749,"props":18322,"children":18323},{},[18324],{"type":35,"value":17658},{"type":29,"tag":749,"props":18326,"children":18327},{},[18328],{"type":35,"value":18329},"Ambitions + plan 12 mois",{"type":29,"tag":749,"props":18331,"children":18332},{},[18333],{"type":35,"value":18334},"Feuille de route carrière",{"type":29,"tag":722,"props":18336,"children":18337},{},[18338,18343,18348,18353],{"type":29,"tag":749,"props":18339,"children":18340},{},[18341],{"type":35,"value":18342},"Contrat",{"type":29,"tag":749,"props":18344,"children":18345},{},[18346],{"type":35,"value":18347},"15 min",{"type":29,"tag":749,"props":18349,"children":18350},{},[18351],{"type":35,"value":18352},"Engagements réciproques",{"type":29,"tag":749,"props":18354,"children":18355},{},[18356],{"type":35,"value":18357},"Commitment clair",{"type":29,"tag":722,"props":18359,"children":18360},{},[18361,18366,18371,18376],{"type":29,"tag":749,"props":18362,"children":18363},{},[18364],{"type":35,"value":18365},"Suivi",{"type":29,"tag":749,"props":18367,"children":18368},{},[18369],{"type":35,"value":18370},"J+90",{"type":29,"tag":749,"props":18372,"children":18373},{},[18374],{"type":35,"value":18375},"Bilan des actions",{"type":29,"tag":749,"props":18377,"children":18378},{},[18379],{"type":35,"value":18380},"Continuité de la dynamique",{"type":29,"tag":76,"props":18382,"children":18383},{},[],{"type":29,"tag":80,"props":18385,"children":18387},{"id":18386},"faq-sur-lentretien-annuel-des-développeurs",[18388],{"type":35,"value":18389},"FAQ sur l'entretien annuel des développeurs",{"type":29,"tag":381,"props":18391,"children":18392},{},[18393,18398],{"type":29,"tag":385,"props":18394,"children":18395},{},[18396],{"type":35,"value":18397},"L'entretien annuel peut-il remplacer les 1-on-1 réguliers ?",{"type":29,"tag":37,"props":18399,"children":18400},{},[18401,18403,18407],{"type":35,"value":18402},"Non, c'est l'inverse : les 1-on-1 réguliers sont le prérequis de l'entretien annuel. Un entretien annuel sans 1-on-1 réguliers pendant l'année est une conversation avec un quasi-inconnu. Les problèmes non-dits se sont accumulés, les tensions sont latentes, et 90 minutes ne suffisent pas à traiter 12 mois de sujets non-abordés. Les 1-on-1 mensuels rendent l'annuel plus riche et moins stressant pour les deux parties. Ces rituels de ",{"type":29,"tag":48,"props":18404,"children":18405},{"href":1846},[18406],{"type":35,"value":1849},{"type":35,"value":18408}," sont le substrat de tout développement individuel efficace.",{"type":29,"tag":381,"props":18410,"children":18411},{},[18412,18417],{"type":29,"tag":385,"props":18413,"children":18414},{},[18415],{"type":35,"value":18416},"Comment conduire un entretien annuel avec un développeur qui ne veut pas évoluer vers le management ?",{"type":29,"tag":37,"props":18418,"children":18419},{},[18420],{"type":35,"value":18421},"La progression de carrière ne passe pas nécessairement par le management. Un excellent développeur senior qui veut rester dans l'excellence technique a un parcours légitime : senior engineer → staff engineer → principal engineer. Ces titres reconnaissent la valeur croissante d'un expert technique sans le forcer vers un rôle qu'il ne veut pas. Si votre organisation n'a que \"développeur → manager\" comme chemin de progression, c'est un problème structurel à corriger, pas un problème du développeur.",{"type":29,"tag":381,"props":18423,"children":18424},{},[18425,18430],{"type":29,"tag":385,"props":18426,"children":18427},{},[18428],{"type":35,"value":18429},"Que faire si un développeur exprime des ambitions que l'organisation ne peut pas satisfaire ?",{"type":29,"tag":37,"props":18431,"children":18432},{},[18433,18435,18440],{"type":35,"value":18434},"Être honnête. \"Tu veux devenir Head of Architecture dans 24 mois : c'est une ambition légitime. Dans notre organisation, ce poste n'est pas disponible dans ce délai. Voilà ce qui est possible : ",{"type":29,"tag":901,"props":18436,"children":18437},{},[18438],{"type":35,"value":18439},"alternatives réalistes",{"type":35,"value":18441},". Et voilà les opportunités externes que je peux t'aider à explorer si notre trajectoire ne correspond pas.\" Un développeur qui part avec honnêteté part bien. Un développeur qui part après des promesses non-tenues part en ennemi potentiel.",{"type":29,"tag":381,"props":18443,"children":18444},{},[18445,18450],{"type":29,"tag":385,"props":18446,"children":18447},{},[18448],{"type":35,"value":18449},"L'entretien annuel est-il différent pour les juniors vs les seniors ?",{"type":29,"tag":37,"props":18451,"children":18452},{},[18453,18455,18460],{"type":35,"value":18454},"Le format est le même, l'emphase diffère. Pour les juniors : plus de temps sur le Bloc 2 (diagnostic des blocages dans la montée en compétence) et le Bloc 3 (plan de développement très concret, avec des jalons trimestriels). Pour les seniors : plus de temps sur le Bloc 1 (reconnaissance de l'impact stratégique) et les ambitions à 24 à 36 mois plutôt que 12. Ces ambitions se concrétisent par une ",{"type":29,"tag":48,"props":18456,"children":18457},{"href":1270},[18458],{"type":35,"value":18459},"délégation progressive",{"type":35,"value":18461}," adaptée au niveau de séniorité.",{"type":29,"tag":381,"props":18463,"children":18464},{},[18465,18470],{"type":29,"tag":385,"props":18466,"children":18467},{},[18468],{"type":35,"value":18469},"Faut-il combiner l'entretien annuel avec la révision salariale ?",{"type":29,"tag":37,"props":18471,"children":18472},{},[18473],{"type":35,"value":18474},"Jamais. Les deux sujets s'inhibent mutuellement. Si la discussion salariale arrive en premier, le développeur filtre le reste de la conversation en fonction de l'impact sur sa rémunération. Si elle arrive en dernier, il a passé 90 minutes à attendre cette partie. Je tiens systématiquement deux réunions séparées, à une semaine d'intervalle minimum. L'entretien de développement d'abord. La révision salariale ensuite.",{"type":29,"tag":76,"props":18476,"children":18477},{},[],{"type":29,"tag":176,"props":18479,"children":18480},{"cta":1243,"href":1244,"title":454,"type":455},[18481],{"type":29,"tag":37,"props":18482,"children":18483},{},[18484],{"type":35,"value":18485},"L'Engineering Maturity Self-Assessment couvre le domaine People & Rétention : évaluez la maturité de vos pratiques de management individuel, de développement de carrière, et de rétention. Score et recommandations concrètes en 10 minutes.",{"title":8,"searchDepth":463,"depth":463,"links":18487},[18488,18489,18490,18496,18497,18498],{"id":17885,"depth":463,"text":17888},{"id":17916,"depth":463,"text":17919},{"id":17976,"depth":463,"text":17979,"children":18491},[18492,18493,18494,18495],{"id":17982,"depth":469,"text":17985},{"id":17998,"depth":469,"text":18001},{"id":18026,"depth":469,"text":18029},{"id":18126,"depth":469,"text":18129},{"id":18170,"depth":463,"text":18173},{"id":12974,"depth":463,"text":12977},{"id":18386,"depth":463,"text":18389},"content:fr:management:entretien-annuel-developpeur-format.md","fr/management/entretien-annuel-developpeur-format.md","fr/management/entretien-annuel-developpeur-format",{"_path":2185,"_dir":2118,"_draft":7,"_partial":7,"_locale":8,"title":18503,"description":18504,"id":6055,"date":18505,"listed":13,"nocomments":7,"hidden":7,"categories":18506,"tags":18507,"--cover":18510,"readingTime":18511,"body":18515,"_type":476,"_id":19480,"_source":478,"_file":19481,"_stem":19482,"_extension":481},"LLMs et sécurité du code : ce qu'il faut savoir","Les LLMs génèrent du code fonctionnel et vulnérable avec la même fluidité. Les vecteurs d'attaque spécifiques au code IA-assisté et les garde-fous à mettre en place.","2026-02-13",[2118],[18508,16076,18509,2125],"LLM","Vulnérabilités","covers/articles/llm-securite-code.jpg",{"text":13194,"minutes":18512,"time":18513,"words":18514},6.94,416400,1388,{"type":26,"children":18516,"toc":19466},[18517,18522,18527,18532,18540,18566,18569,18575,18580,18585,18588,18594,18599,18834,18851,18856,18859,18865,18870,19157,19162,19167,19176,19179,19185,19190,19200,19210,19256,19261,19264,19270,19276,19286,19292,19304,19327,19333,19338,19344,19356,19362,19367,19372,19377,19380,19386,19399,19412,19425,19438,19451,19454,19462],{"type":29,"tag":30,"props":18518,"children":18520},{"id":18519},"llms-et-sécurité-du-code-ce-quil-faut-savoir",[18521],{"type":35,"value":18503},{"type":29,"tag":37,"props":18523,"children":18524},{},[18525],{"type":35,"value":18526},"J'ai passé une heure à examiner le code d'un client dans le secteur financier que j'accompagnais. Ils avaient adopté Copilot depuis 3 mois, sans formation sur les risques spécifiques. Dans les 200 premières lignes d'un nouveau service, j'ai trouvé deux credentials AWS hardcodées et une requête SQL construite par interpolation de chaîne. Le code compilait. Les tests passaient. La PR avait été approuvée.",{"type":29,"tag":37,"props":18528,"children":18529},{},[18530],{"type":35,"value":18531},"Ce n'était pas de la négligence. C'était de l'ignorance des patterns que les LLMs reproduisent naturellement.",{"type":29,"tag":37,"props":18533,"children":18534},{},[18535],{"type":29,"tag":65,"props":18536,"children":18537},{},[18538],{"type":35,"value":18539},"Un LLM génère du code SQL injection et du code parfaitement sécurisé avec la même confiance syntaxique. Il ne distingue pas les deux. Votre processus de review doit le faire, et en 2026, la plupart des équipes n'ont pas adapté leur review au code IA-assisté.",{"type":29,"tag":37,"props":18541,"children":18542},{},[18543,18545,18550,18552,18557,18559,18564],{"type":35,"value":18544},"Deux études publiées en 2023 ont documenté le problème. ",{"type":29,"tag":65,"props":18546,"children":18547},{},[18548],{"type":35,"value":18549},"Stanford University",{"type":35,"value":18551}," : 40% du code suggéré par Copilot dans des contextes de sécurité spécifiques contient des vulnérabilités. ",{"type":29,"tag":65,"props":18553,"children":18554},{},[18555],{"type":35,"value":18556},"NYU",{"type":35,"value":18558}," : les développeurs qui utilisent des assistants IA tendent à produire du code ",{"type":29,"tag":65,"props":18560,"children":18561},{},[18562],{"type":35,"value":18563},"moins sécurisé",{"type":35,"value":18565}," que sans assistant, parce qu'ils font plus confiance au code généré et le reviewent moins rigoureusement. Ce chiffre est contre-intuitif mais cohérent avec ce que j'observe sur le terrain.",{"type":29,"tag":76,"props":18567,"children":18568},{},[],{"type":29,"tag":80,"props":18570,"children":18572},{"id":18571},"pourquoi-les-llms-génèrent-du-code-vulnérable",[18573],{"type":35,"value":18574},"Pourquoi les LLMs génèrent du code vulnérable",{"type":29,"tag":37,"props":18576,"children":18577},{},[18578],{"type":35,"value":18579},"L'explication est simple mais souvent ignorée : les LLMs sont entraînés sur du code public. Le code public contient des vulnérabilités courantes. Les LLMs reproduisent les patterns du code sur lequel ils ont été entraînés.",{"type":29,"tag":37,"props":18581,"children":18582},{},[18583],{"type":35,"value":18584},"Le résultat : les patterns vulnérables les plus fréquents dans le code public (injections, secrets hardcodés, dépendances non vérifiées) sont aussi les plus fréquemment générés par les LLMs. Pas par malveillance. Par statistique.",{"type":29,"tag":76,"props":18586,"children":18587},{},[],{"type":29,"tag":80,"props":18589,"children":18591},{"id":18590},"vulnérabilité-type-1-injections-sql-prompt-command",[18592],{"type":35,"value":18593},"Vulnérabilité type 1 : Injections (SQL, prompt, command)",{"type":29,"tag":37,"props":18595,"children":18596},{},[18597],{"type":35,"value":18598},"Les LLMs génèrent facilement du code vulnérable aux injections, surtout quand le prompt ne spécifie pas explicitement l'usage de requêtes paramétrées.",{"type":29,"tag":651,"props":18600,"children":18602},{"className":2200,"code":18601,"language":2202,"meta":8,"style":8},"# ❌ Code généré par LLM sans précision sur la sécurité\ndef get_user(username: str):\n    query = f\"SELECT * FROM users WHERE username = '{username}'\"  # SQL injection\n    return db.execute(query)\n\n# ✅ Code correct (que le LLM génère si le prompt est précis)\ndef get_user(username: str):\n    query = \"SELECT * FROM users WHERE username = %s\"\n    return db.execute(query, (username,))\n",[18603],{"type":29,"tag":565,"props":18604,"children":18605},{"__ignoreMap":8},[18606,18614,18647,18688,18720,18727,18735,18766,18790],{"type":29,"tag":901,"props":18607,"children":18608},{"class":903,"line":904},[18609],{"type":29,"tag":901,"props":18610,"children":18611},{"style":908},[18612],{"type":35,"value":18613},"# ❌ Code généré par LLM sans précision sur la sécurité\n",{"type":29,"tag":901,"props":18615,"children":18616},{"class":903,"line":463},[18617,18621,18626,18630,18635,18639,18643],{"type":29,"tag":901,"props":18618,"children":18619},{"style":917},[18620],{"type":35,"value":6593},{"type":29,"tag":901,"props":18622,"children":18623},{"style":5362},[18624],{"type":35,"value":18625}," get_user",{"type":29,"tag":901,"props":18627,"children":18628},{"style":5185},[18629],{"type":35,"value":3080},{"type":29,"tag":901,"props":18631,"children":18632},{"style":5380},[18633],{"type":35,"value":18634},"username",{"type":29,"tag":901,"props":18636,"children":18637},{"style":5185},[18638],{"type":35,"value":5760},{"type":29,"tag":901,"props":18640,"children":18641},{"style":5763},[18642],{"type":35,"value":5780},{"type":29,"tag":901,"props":18644,"children":18645},{"style":5185},[18646],{"type":35,"value":5217},{"type":29,"tag":901,"props":18648,"children":18649},{"class":903,"line":469},[18650,18655,18659,18663,18668,18672,18676,18680,18684],{"type":29,"tag":901,"props":18651,"children":18652},{"style":923},[18653],{"type":35,"value":18654},"    query ",{"type":29,"tag":901,"props":18656,"children":18657},{"style":947},[18658],{"type":35,"value":2227},{"type":29,"tag":901,"props":18660,"children":18661},{"style":2230},[18662],{"type":35,"value":2233},{"type":29,"tag":901,"props":18664,"children":18665},{"style":2236},[18666],{"type":35,"value":18667},"\"SELECT * FROM users WHERE username = '",{"type":29,"tag":901,"props":18669,"children":18670},{"style":2242},[18671],{"type":35,"value":2245},{"type":29,"tag":901,"props":18673,"children":18674},{"style":923},[18675],{"type":35,"value":18634},{"type":29,"tag":901,"props":18677,"children":18678},{"style":2242},[18679],{"type":35,"value":2255},{"type":29,"tag":901,"props":18681,"children":18682},{"style":2236},[18683],{"type":35,"value":2260},{"type":29,"tag":901,"props":18685,"children":18686},{"style":908},[18687],{"type":35,"value":2265},{"type":29,"tag":901,"props":18689,"children":18690},{"class":903,"line":968},[18691,18695,18699,18703,18707,18711,18716],{"type":29,"tag":901,"props":18692,"children":18693},{"style":917},[18694],{"type":35,"value":6695},{"type":29,"tag":901,"props":18696,"children":18697},{"style":923},[18698],{"type":35,"value":15755},{"type":29,"tag":901,"props":18700,"children":18701},{"style":5185},[18702],{"type":35,"value":342},{"type":29,"tag":901,"props":18704,"children":18705},{"style":5242},[18706],{"type":35,"value":6353},{"type":29,"tag":901,"props":18708,"children":18709},{"style":5185},[18710],{"type":35,"value":3080},{"type":29,"tag":901,"props":18712,"children":18713},{"style":923},[18714],{"type":35,"value":18715},"query",{"type":29,"tag":901,"props":18717,"children":18718},{"style":5185},[18719],{"type":35,"value":5437},{"type":29,"tag":901,"props":18721,"children":18722},{"class":903,"line":977},[18723],{"type":29,"tag":901,"props":18724,"children":18725},{"emptyLinePlaceholder":13},[18726],{"type":35,"value":974},{"type":29,"tag":901,"props":18728,"children":18729},{"class":903,"line":986},[18730],{"type":29,"tag":901,"props":18731,"children":18732},{"style":908},[18733],{"type":35,"value":18734},"# ✅ Code correct (que le LLM génère si le prompt est précis)\n",{"type":29,"tag":901,"props":18736,"children":18737},{"class":903,"line":1007},[18738,18742,18746,18750,18754,18758,18762],{"type":29,"tag":901,"props":18739,"children":18740},{"style":917},[18741],{"type":35,"value":6593},{"type":29,"tag":901,"props":18743,"children":18744},{"style":5362},[18745],{"type":35,"value":18625},{"type":29,"tag":901,"props":18747,"children":18748},{"style":5185},[18749],{"type":35,"value":3080},{"type":29,"tag":901,"props":18751,"children":18752},{"style":5380},[18753],{"type":35,"value":18634},{"type":29,"tag":901,"props":18755,"children":18756},{"style":5185},[18757],{"type":35,"value":5760},{"type":29,"tag":901,"props":18759,"children":18760},{"style":5763},[18761],{"type":35,"value":5780},{"type":29,"tag":901,"props":18763,"children":18764},{"style":5185},[18765],{"type":35,"value":5217},{"type":29,"tag":901,"props":18767,"children":18768},{"class":903,"line":5354},[18769,18773,18777,18782,18786],{"type":29,"tag":901,"props":18770,"children":18771},{"style":923},[18772],{"type":35,"value":18654},{"type":29,"tag":901,"props":18774,"children":18775},{"style":947},[18776],{"type":35,"value":2227},{"type":29,"tag":901,"props":18778,"children":18779},{"style":2236},[18780],{"type":35,"value":18781}," \"SELECT * FROM users WHERE username = ",{"type":29,"tag":901,"props":18783,"children":18784},{"style":2242},[18785],{"type":35,"value":2294},{"type":29,"tag":901,"props":18787,"children":18788},{"style":2236},[18789],{"type":35,"value":2299},{"type":29,"tag":901,"props":18791,"children":18792},{"class":903,"line":5390},[18793,18797,18801,18805,18809,18813,18817,18821,18825,18829],{"type":29,"tag":901,"props":18794,"children":18795},{"style":917},[18796],{"type":35,"value":6695},{"type":29,"tag":901,"props":18798,"children":18799},{"style":923},[18800],{"type":35,"value":15755},{"type":29,"tag":901,"props":18802,"children":18803},{"style":5185},[18804],{"type":35,"value":342},{"type":29,"tag":901,"props":18806,"children":18807},{"style":5242},[18808],{"type":35,"value":6353},{"type":29,"tag":901,"props":18810,"children":18811},{"style":5185},[18812],{"type":35,"value":3080},{"type":29,"tag":901,"props":18814,"children":18815},{"style":923},[18816],{"type":35,"value":18715},{"type":29,"tag":901,"props":18818,"children":18819},{"style":5185},[18820],{"type":35,"value":3663},{"type":29,"tag":901,"props":18822,"children":18823},{"style":5185},[18824],{"type":35,"value":7839},{"type":29,"tag":901,"props":18826,"children":18827},{"style":923},[18828],{"type":35,"value":18634},{"type":29,"tag":901,"props":18830,"children":18831},{"style":5185},[18832],{"type":35,"value":18833},",))\n",{"type":29,"tag":37,"props":18835,"children":18836},{},[18837,18842,18844,18849],{"type":29,"tag":65,"props":18838,"children":18839},{},[18840],{"type":35,"value":18841},"La prompt injection",{"type":35,"value":18843}," est spécifique au code qui intègre des LLMs dans des applications : si votre application passe de l'input utilisateur directement dans un prompt, un attaquant peut modifier le comportement du modèle via des instructions injectées. C'est une vulnérabilité nouvelle, documentée par l'",{"type":29,"tag":65,"props":18845,"children":18846},{},[18847],{"type":35,"value":18848},"OWASP Top 10 for LLM Applications",{"type":35,"value":18850}," depuis 2023.",{"type":29,"tag":37,"props":18852,"children":18853},{},[18854],{"type":35,"value":18855},"Garde-fou : lors de la review de tout code qui touche à la gestion des inputs utilisateurs, vérifier systématiquement que les requêtes sont paramétrées et que les inputs ne sont pas interpolés directement dans des strings.",{"type":29,"tag":76,"props":18857,"children":18858},{},[],{"type":29,"tag":80,"props":18860,"children":18862},{"id":18861},"vulnérabilité-type-2-gestion-des-secrets-et-credentials",[18863],{"type":35,"value":18864},"Vulnérabilité type 2 : Gestion des secrets et credentials",{"type":29,"tag":37,"props":18866,"children":18867},{},[18868],{"type":35,"value":18869},"C'est le pattern de vulnérabilité le plus fréquemment généré par les LLMs : credentials hardcodées, tokens dans les logs, secrets dans les fichiers de configuration versionnés.",{"type":29,"tag":651,"props":18871,"children":18873},{"className":10784,"code":18872,"language":10783,"meta":8,"style":8},"// ❌ Pattern fréquemment généré\nconst client = new S3Client({\n    accessKeyId: \"AKIAIOSFODNN7EXAMPLE\",      // credential hardcodée\n    secretAccessKey: \"wJalrXUtnFEMI/K7MDENG\" // credential hardcodée\n});\n\n// ❌ Pattern de logging qui expose des secrets\nconsole.log(`Connecting to DB with password: ${process.env.DB_PASSWORD}`);\n\n// ✅ Pattern correct\nconst client = new S3Client({\n    credentials: fromEnv()  // lecture depuis les variables d'environnement\n});\n",[18874],{"type":29,"tag":565,"props":18875,"children":18876},{"__ignoreMap":8},[18877,18885,18918,18944,18966,18981,18988,18996,19069,19076,19084,19115,19142],{"type":29,"tag":901,"props":18878,"children":18879},{"class":903,"line":904},[18880],{"type":29,"tag":901,"props":18881,"children":18882},{"style":908},[18883],{"type":35,"value":18884},"// ❌ Pattern fréquemment généré\n",{"type":29,"tag":901,"props":18886,"children":18887},{"class":903,"line":463},[18888,18892,18897,18901,18905,18910,18914],{"type":29,"tag":901,"props":18889,"children":18890},{"style":917},[18891],{"type":35,"value":14335},{"type":29,"tag":901,"props":18893,"children":18894},{"style":5674},[18895],{"type":35,"value":18896}," client",{"type":29,"tag":901,"props":18898,"children":18899},{"style":947},[18900],{"type":35,"value":6944},{"type":29,"tag":901,"props":18902,"children":18903},{"style":7874},[18904],{"type":35,"value":7877},{"type":29,"tag":901,"props":18906,"children":18907},{"style":5362},[18908],{"type":35,"value":18909}," S3Client",{"type":29,"tag":901,"props":18911,"children":18912},{"style":923},[18913],{"type":35,"value":3080},{"type":29,"tag":901,"props":18915,"children":18916},{"style":5185},[18917],{"type":35,"value":7863},{"type":29,"tag":901,"props":18919,"children":18920},{"class":903,"line":469},[18921,18926,18930,18935,18939],{"type":29,"tag":901,"props":18922,"children":18923},{"style":923},[18924],{"type":35,"value":18925},"    accessKeyId",{"type":29,"tag":901,"props":18927,"children":18928},{"style":7730},[18929],{"type":35,"value":5760},{"type":29,"tag":901,"props":18931,"children":18932},{"style":2236},[18933],{"type":35,"value":18934}," \"AKIAIOSFODNN7EXAMPLE\"",{"type":29,"tag":901,"props":18936,"children":18937},{"style":5185},[18938],{"type":35,"value":3663},{"type":29,"tag":901,"props":18940,"children":18941},{"style":908},[18942],{"type":35,"value":18943},"      // credential hardcodée\n",{"type":29,"tag":901,"props":18945,"children":18946},{"class":903,"line":968},[18947,18952,18956,18961],{"type":29,"tag":901,"props":18948,"children":18949},{"style":923},[18950],{"type":35,"value":18951},"    secretAccessKey",{"type":29,"tag":901,"props":18953,"children":18954},{"style":7730},[18955],{"type":35,"value":5760},{"type":29,"tag":901,"props":18957,"children":18958},{"style":2236},[18959],{"type":35,"value":18960}," \"wJalrXUtnFEMI/K7MDENG\"",{"type":29,"tag":901,"props":18962,"children":18963},{"style":908},[18964],{"type":35,"value":18965}," // credential hardcodée\n",{"type":29,"tag":901,"props":18967,"children":18968},{"class":903,"line":977},[18969,18973,18977],{"type":29,"tag":901,"props":18970,"children":18971},{"style":5185},[18972],{"type":35,"value":2255},{"type":29,"tag":901,"props":18974,"children":18975},{"style":923},[18976],{"type":35,"value":2881},{"type":29,"tag":901,"props":18978,"children":18979},{"style":5185},[18980],{"type":35,"value":7332},{"type":29,"tag":901,"props":18982,"children":18983},{"class":903,"line":986},[18984],{"type":29,"tag":901,"props":18985,"children":18986},{"emptyLinePlaceholder":13},[18987],{"type":35,"value":974},{"type":29,"tag":901,"props":18989,"children":18990},{"class":903,"line":1007},[18991],{"type":29,"tag":901,"props":18992,"children":18993},{"style":908},[18994],{"type":35,"value":18995},"// ❌ Pattern de logging qui expose des secrets\n",{"type":29,"tag":901,"props":18997,"children":18998},{"class":903,"line":5354},[18999,19004,19008,19013,19017,19022,19028,19033,19038,19043,19047,19052,19056,19061,19065],{"type":29,"tag":901,"props":19000,"children":19001},{"style":923},[19002],{"type":35,"value":19003},"console",{"type":29,"tag":901,"props":19005,"children":19006},{"style":7730},[19007],{"type":35,"value":342},{"type":29,"tag":901,"props":19009,"children":19010},{"style":5362},[19011],{"type":35,"value":19012},"log",{"type":29,"tag":901,"props":19014,"children":19015},{"style":923},[19016],{"type":35,"value":3080},{"type":29,"tag":901,"props":19018,"children":19019},{"style":2236},[19020],{"type":35,"value":19021},"`Connecting to DB with password: ",{"type":29,"tag":901,"props":19023,"children":19025},{"style":19024},"--shiki-default:#949CBB;--shiki-dark:#9ECBFF",[19026],{"type":35,"value":19027},"${",{"type":29,"tag":901,"props":19029,"children":19030},{"style":923},[19031],{"type":35,"value":19032},"process",{"type":29,"tag":901,"props":19034,"children":19036},{"style":19035},"--shiki-default:#81C8BE;--shiki-dark:#9ECBFF",[19037],{"type":35,"value":342},{"type":29,"tag":901,"props":19039,"children":19040},{"style":923},[19041],{"type":35,"value":19042},"env",{"type":29,"tag":901,"props":19044,"children":19045},{"style":19035},[19046],{"type":35,"value":342},{"type":29,"tag":901,"props":19048,"children":19049},{"style":5280},[19050],{"type":35,"value":19051},"DB_PASSWORD",{"type":29,"tag":901,"props":19053,"children":19054},{"style":19024},[19055],{"type":35,"value":2255},{"type":29,"tag":901,"props":19057,"children":19058},{"style":2236},[19059],{"type":35,"value":19060},"`",{"type":29,"tag":901,"props":19062,"children":19063},{"style":923},[19064],{"type":35,"value":2881},{"type":29,"tag":901,"props":19066,"children":19067},{"style":5185},[19068],{"type":35,"value":7332},{"type":29,"tag":901,"props":19070,"children":19071},{"class":903,"line":5390},[19072],{"type":29,"tag":901,"props":19073,"children":19074},{"emptyLinePlaceholder":13},[19075],{"type":35,"value":974},{"type":29,"tag":901,"props":19077,"children":19078},{"class":903,"line":5440},[19079],{"type":29,"tag":901,"props":19080,"children":19081},{"style":908},[19082],{"type":35,"value":19083},"// ✅ Pattern correct\n",{"type":29,"tag":901,"props":19085,"children":19086},{"class":903,"line":5506},[19087,19091,19095,19099,19103,19107,19111],{"type":29,"tag":901,"props":19088,"children":19089},{"style":917},[19090],{"type":35,"value":14335},{"type":29,"tag":901,"props":19092,"children":19093},{"style":5674},[19094],{"type":35,"value":18896},{"type":29,"tag":901,"props":19096,"children":19097},{"style":947},[19098],{"type":35,"value":6944},{"type":29,"tag":901,"props":19100,"children":19101},{"style":7874},[19102],{"type":35,"value":7877},{"type":29,"tag":901,"props":19104,"children":19105},{"style":5362},[19106],{"type":35,"value":18909},{"type":29,"tag":901,"props":19108,"children":19109},{"style":923},[19110],{"type":35,"value":3080},{"type":29,"tag":901,"props":19112,"children":19113},{"style":5185},[19114],{"type":35,"value":7863},{"type":29,"tag":901,"props":19116,"children":19117},{"class":903,"line":5911},[19118,19123,19127,19132,19137],{"type":29,"tag":901,"props":19119,"children":19120},{"style":923},[19121],{"type":35,"value":19122},"    credentials",{"type":29,"tag":901,"props":19124,"children":19125},{"style":7730},[19126],{"type":35,"value":5760},{"type":29,"tag":901,"props":19128,"children":19129},{"style":5362},[19130],{"type":35,"value":19131}," fromEnv",{"type":29,"tag":901,"props":19133,"children":19134},{"style":923},[19135],{"type":35,"value":19136},"()  ",{"type":29,"tag":901,"props":19138,"children":19139},{"style":908},[19140],{"type":35,"value":19141},"// lecture depuis les variables d'environnement\n",{"type":29,"tag":901,"props":19143,"children":19144},{"class":903,"line":5919},[19145,19149,19153],{"type":29,"tag":901,"props":19146,"children":19147},{"style":5185},[19148],{"type":35,"value":2255},{"type":29,"tag":901,"props":19150,"children":19151},{"style":923},[19152],{"type":35,"value":2881},{"type":29,"tag":901,"props":19154,"children":19155},{"style":5185},[19156],{"type":35,"value":7332},{"type":29,"tag":37,"props":19158,"children":19159},{},[19160],{"type":35,"value":19161},"La raison : les LLMs ont été entraînés sur du code d'exemple qui contient fréquemment des credentials \"de test\" hardcodées. Ils reproduisent ce pattern naturellement.",{"type":29,"tag":37,"props":19163,"children":19164},{},[19165],{"type":35,"value":19166},"Garde-fou : outil SAST (Semgrep, GitHub Secret Scanning, Gitleaks) dans la CI qui détecte les patterns de credentials hardcodées avant le merge. Ce check doit être bloquant.",{"type":29,"tag":176,"props":19168,"children":19170},{"cta":178,"href":179,"title":19169,"type":181},"Votre équipe utilise des assistants IA mais votre processus de review n'a pas été adapté aux risques spécifiques ?",[19171],{"type":29,"tag":37,"props":19172,"children":19173},{},[19174],{"type":35,"value":19175},"Vous savez que le code IA-assisté comporte des risques spécifiques, mais vous n'avez pas encore adapté vos pratiques de review et votre outillage de sécurité. En 30 minutes, on définit les priorités et le plan d'action adapté à votre contexte et vos contraintes réglementaires.",{"type":29,"tag":76,"props":19177,"children":19178},{},[],{"type":29,"tag":80,"props":19180,"children":19182},{"id":19181},"vulnérabilité-type-3-dépendances-obsolètes-ou-hallucinations",[19183],{"type":35,"value":19184},"Vulnérabilité type 3 : Dépendances obsolètes ou hallucinations",{"type":29,"tag":37,"props":19186,"children":19187},{},[19188],{"type":35,"value":19189},"Quand un LLM génère du code qui importe des librairies externes, deux risques spécifiques apparaissent :",{"type":29,"tag":37,"props":19191,"children":19192},{},[19193,19198],{"type":29,"tag":65,"props":19194,"children":19195},{},[19196],{"type":35,"value":19197},"Dépendances avec CVE connus :",{"type":35,"value":19199}," le LLM suggère une version d'une librairie qui avait des vulnérabilités connues au moment de son entraînement, et qui ont pu être corrigées depuis, mais la version vulnérable reste dans le code généré.",{"type":29,"tag":37,"props":19201,"children":19202},{},[19203,19208],{"type":29,"tag":65,"props":19204,"children":19205},{},[19206],{"type":35,"value":19207},"Package hallucination :",{"type":35,"value":19209}," les LLMs peuvent inventer des noms de packages plausibles qui n'existent pas (ou qui existent sous un nom de typosquat malveillant). C'est le vecteur de l'attaque \"dependency confusion\", documentée par de nombreux chercheurs en sécurité depuis 2021.",{"type":29,"tag":651,"props":19211,"children":19213},{"className":11449,"code":19212,"language":11448,"meta":8,"style":8},"# LLM suggère d'importer \"utility-helper-crypto\" — package qui n'existe pas\n# Un attaquant peut publier ce package sur npm avec du code malveillant\nnpm install utility-helper-crypto  # ❌ vérifier l'existence avant d'installer\n",[19214],{"type":29,"tag":565,"props":19215,"children":19216},{"__ignoreMap":8},[19217,19225,19233],{"type":29,"tag":901,"props":19218,"children":19219},{"class":903,"line":904},[19220],{"type":29,"tag":901,"props":19221,"children":19222},{"style":908},[19223],{"type":35,"value":19224},"# LLM suggère d'importer \"utility-helper-crypto\" — package qui n'existe pas\n",{"type":29,"tag":901,"props":19226,"children":19227},{"class":903,"line":463},[19228],{"type":29,"tag":901,"props":19229,"children":19230},{"style":908},[19231],{"type":35,"value":19232},"# Un attaquant peut publier ce package sur npm avec du code malveillant\n",{"type":29,"tag":901,"props":19234,"children":19235},{"class":903,"line":469},[19236,19241,19246,19251],{"type":29,"tag":901,"props":19237,"children":19238},{"style":5362},[19239],{"type":35,"value":19240},"npm",{"type":29,"tag":901,"props":19242,"children":19243},{"style":2236},[19244],{"type":35,"value":19245}," install",{"type":29,"tag":901,"props":19247,"children":19248},{"style":2236},[19249],{"type":35,"value":19250}," utility-helper-crypto",{"type":29,"tag":901,"props":19252,"children":19253},{"style":908},[19254],{"type":35,"value":19255},"  # ❌ vérifier l'existence avant d'installer\n",{"type":29,"tag":37,"props":19257,"children":19258},{},[19259],{"type":35,"value":19260},"Garde-fou : ne jamais installer un package suggéré par un LLM sans vérifier son existence sur le registre officiel et son score de sécurité (npm audit, Snyk, Socket.dev).",{"type":29,"tag":76,"props":19262,"children":19263},{},[],{"type":29,"tag":80,"props":19265,"children":19267},{"id":19266},"les-5-garde-fous-à-mettre-en-place",[19268],{"type":35,"value":19269},"Les 5 garde-fous à mettre en place",{"type":29,"tag":116,"props":19271,"children":19273},{"id":19272},"garde-fou-1-sast-dans-la-ci",[19274],{"type":35,"value":19275},"Garde-fou 1 : SAST dans la CI",{"type":29,"tag":37,"props":19277,"children":19278},{},[19279,19284],{"type":29,"tag":48,"props":19280,"children":19281},{"href":337},[19282],{"type":35,"value":19283},"SonarQube, Semgrep, ou GitHub Advanced Security",{"type":35,"value":19285}," détectent les patterns de vulnérabilités courants indépendamment de l'origine du code, qu'il soit humain ou IA. Ce check doit être bloquant sur les vulnérabilités Critical et High.",{"type":29,"tag":116,"props":19287,"children":19289},{"id":19288},"garde-fou-2-checklist-de-review-spécifique-au-code-ia",[19290],{"type":35,"value":19291},"Garde-fou 2 : Checklist de review spécifique au code IA",{"type":29,"tag":37,"props":19293,"children":19294},{},[19295,19297,19302],{"type":35,"value":19296},"Au-delà de la review standard, les reviewers vérifient explicitement pour le code IA-assisté (voir la ",{"type":29,"tag":48,"props":19298,"children":19299},{"href":2484},[19300],{"type":35,"value":19301},"checklist complète en 12 points",{"type":35,"value":19303},") :",{"type":29,"tag":1080,"props":19305,"children":19306},{},[19307,19312,19317,19322],{"type":29,"tag":1084,"props":19308,"children":19309},{},[19310],{"type":35,"value":19311},"Aucune credential hardcodée",{"type":29,"tag":1084,"props":19313,"children":19314},{},[19315],{"type":35,"value":19316},"Toutes les requêtes DB sont paramétrées",{"type":29,"tag":1084,"props":19318,"children":19319},{},[19320],{"type":35,"value":19321},"Les dépendances importées ont été vérifiées",{"type":29,"tag":1084,"props":19323,"children":19324},{},[19325],{"type":35,"value":19326},"Les inputs utilisateurs sont validés et sanitisés",{"type":29,"tag":116,"props":19328,"children":19330},{"id":19329},"garde-fou-3-politique-de-prompt",[19331],{"type":35,"value":19332},"Garde-fou 3 : Politique de prompt",{"type":29,"tag":37,"props":19334,"children":19335},{},[19336],{"type":35,"value":19337},"Documentez quelles données peuvent et ne peuvent pas être incluses dans les prompts envoyés à des services IA externes : pas de données personnelles, pas de données clients, pas de credentials, pas de secrets d'infrastructure.",{"type":29,"tag":116,"props":19339,"children":19341},{"id":19340},"garde-fou-4-formation-des-développeurs",[19342],{"type":35,"value":19343},"Garde-fou 4 : Formation des développeurs",{"type":29,"tag":37,"props":19345,"children":19346},{},[19347,19349,19354],{"type":35,"value":19348},"Une session de 2 heures sur les patterns de vulnérabilités spécifiques au code LLM-généré suffit à doubler la détection lors des reviews. Découvrez comment ",{"type":29,"tag":48,"props":19350,"children":19351},{"href":2117},[19352],{"type":35,"value":19353},"intégrer l'IA dans votre code review",{"type":35,"value":19355}," tout en renforçant la sécurité. Les développeurs qui connaissent les patterns les cherchent. Ceux qui ne les connaissent pas ne les voient pas. C'est aussi simple que ça.",{"type":29,"tag":116,"props":19357,"children":19359},{"id":19358},"garde-fou-5-audit-trimestriel-du-code-ia-assisté",[19360],{"type":35,"value":19361},"Garde-fou 5 : Audit trimestriel du code IA-assisté",{"type":29,"tag":37,"props":19363,"children":19364},{},[19365],{"type":35,"value":19366},"Auditer trimestriellement un échantillon du code développé avec assistance IA pour identifier des patterns systémiques de vulnérabilité. C'est une pratique préventive, pas réactive.",{"type":29,"tag":37,"props":19368,"children":19369},{},[19370],{"type":35,"value":19371},"Dans ce même client (18 développeurs), l'introduction de GitHub Advanced Security + une checklist de review spécifique au code IA a détecté en 3 mois 12 instances de secrets hardcodés et 8 vulnérabilités d'injection qui auraient atteint la production. Coût de l'implémentation : 5 jours. Coût évité (estimation conservatrice basée sur le coût moyen d'un incident de sécurité dans le secteur financier) : plus de 500 000€.",{"type":29,"tag":37,"props":19373,"children":19374},{},[19375],{"type":35,"value":19376},"L'IA accélère la production. Elle ne remplace pas le jugement de sécurité.",{"type":29,"tag":76,"props":19378,"children":19379},{},[],{"type":29,"tag":80,"props":19381,"children":19383},{"id":19382},"faq-sur-la-sécurité-du-code-llm",[19384],{"type":35,"value":19385},"FAQ sur la sécurité du code LLM",{"type":29,"tag":381,"props":19387,"children":19388},{},[19389,19394],{"type":29,"tag":385,"props":19390,"children":19391},{},[19392],{"type":35,"value":19393},"1. Les LLMs vont-ils s'améliorer sur la sécurité du code au fil du temps ?",{"type":29,"tag":37,"props":19395,"children":19396},{},[19397],{"type":35,"value":19398},"Oui, progressivement. Les LLMs récents sont significativement meilleurs que leurs prédécesseurs sur les patterns de sécurité de base. Mais ils continuent à faire des erreurs sur les vulnérabilités contextuelles, celles qui dépendent de la logique métier spécifique de votre application. Ces erreurs-là ne pourront pas être éliminées par l'amélioration des modèles seule.",{"type":29,"tag":381,"props":19400,"children":19401},{},[19402,19407],{"type":29,"tag":385,"props":19403,"children":19404},{},[19405],{"type":35,"value":19406},"2. Les outils SAST détectent-ils les vulnérabilités spécifiques au code IA-généré ?",{"type":29,"tag":37,"props":19408,"children":19409},{},[19410],{"type":35,"value":19411},"Les SAST détectent les patterns de vulnérabilités connus indépendamment de l'origine du code. Ils sont efficaces sur les injections, les hardcoded secrets, et les dépendances vulnérables. Ils ne détectent pas les vulnérabilités logiques, c'est-à-dire le code qui fait quelque chose de sécuritairement incorrect mais syntaxiquement valide. Pour celles-là, la review humaine reste indispensable.",{"type":29,"tag":381,"props":19413,"children":19414},{},[19415,19420],{"type":29,"tag":385,"props":19416,"children":19417},{},[19418],{"type":35,"value":19419},"3. Faut-il une politique différente pour Copilot vs Claude vs ChatGPT ?",{"type":29,"tag":37,"props":19421,"children":19422},{},[19423],{"type":35,"value":19424},"La politique doit être basée sur les données traitées et les clauses contractuelles, pas sur l'outil spécifique. Questions à évaluer pour chaque outil : les prompts sont-ils utilisés pour l'entraînement ? Le fournisseur propose-t-il un DPA compatible RGPD ? Les données sont-elles hébergées en EU si requis ? Les réponses varient par outil et par offre : Consumer, Enterprise ou API.",{"type":29,"tag":381,"props":19426,"children":19427},{},[19428,19433],{"type":29,"tag":385,"props":19429,"children":19430},{},[19431],{"type":35,"value":19432},"4. Comment former rapidement une équipe aux vulnérabilités du code LLM-généré ?",{"type":29,"tag":37,"props":19434,"children":19435},{},[19436],{"type":35,"value":19437},"La méthode la plus efficace : présenter des exemples réels de code vulnérable généré par LLM et demander à l'équipe de trouver les problèmes. Cette approche en \"capture the flag\" crée une mémoire musculaire plus durable que des slides. 2 heures de session avec 10 à 15 exemples réels suffisent à développer les réflexes de base.",{"type":29,"tag":381,"props":19439,"children":19440},{},[19441,19446],{"type":29,"tag":385,"props":19442,"children":19443},{},[19444],{"type":35,"value":19445},"5. Les startups sans RSSI dédié peuvent-elles gérer ces risques seules ?",{"type":29,"tag":37,"props":19447,"children":19448},{},[19449],{"type":35,"value":19450},"Oui, avec 3 garde-fous prioritaires : GitHub Secret Scanning (activé gratuitement sur les repos GitHub, détecte les credentials avant le push), une règle de review PR obligatoire qui checke les injections et les hardcoded secrets, et une politique simple : \"aucune donnée client ou credential dans les prompts\". Ces trois mesures couvrent 80% des risques avec 20% de l'effort.",{"type":29,"tag":76,"props":19452,"children":19453},{},[],{"type":29,"tag":176,"props":19455,"children":19456},{"cta":4081,"href":453,"title":4082,"type":455},[19457],{"type":29,"tag":37,"props":19458,"children":19459},{},[19460],{"type":35,"value":19461},"La checklist AI-Ready inclut une section dédiée à la sécurité du code IA-assisté : critères de gouvernance, checklist de review spécifique, et politiques d'usage recommandées. Adaptable à votre contexte réglementaire.",{"type":29,"tag":1252,"props":19463,"children":19464},{},[19465],{"type":35,"value":1256},{"title":8,"searchDepth":463,"depth":463,"links":19467},[19468,19469,19470,19471,19472,19479],{"id":18571,"depth":463,"text":18574},{"id":18590,"depth":463,"text":18593},{"id":18861,"depth":463,"text":18864},{"id":19181,"depth":463,"text":19184},{"id":19266,"depth":463,"text":19269,"children":19473},[19474,19475,19476,19477,19478],{"id":19272,"depth":469,"text":19275},{"id":19288,"depth":469,"text":19291},{"id":19329,"depth":469,"text":19332},{"id":19340,"depth":469,"text":19343},{"id":19358,"depth":469,"text":19361},{"id":19382,"depth":463,"text":19385},"content:fr:intelligence-artificielle:llm-securite-code-vulnerabilites.md","fr/intelligence-artificielle/llm-securite-code-vulnerabilites.md","fr/intelligence-artificielle/llm-securite-code-vulnerabilites",{"_path":4295,"_dir":4106,"_draft":7,"_partial":7,"_locale":8,"title":19484,"description":19485,"id":6029,"date":19486,"listed":13,"nocomments":7,"hidden":7,"categories":19487,"tags":19488,"--cover":19492,"readingTime":19493,"body":19497,"_type":476,"_id":19926,"_source":478,"_file":19927,"_stem":19928,"_extension":481},"Les anti-patterns du backlog : comment en sortir","Un backlog de 400 items n'est pas un outil de planification : c'est un cimetière de bonnes intentions. Les 5 anti-patterns et la méthode pour retrouver un backlog utilisable.","2026-02-11",[4106],[19489,19490,19491],"Backlog","Anti-patterns","Product Management","covers/articles/anti-patterns-backlog.jpg",{"text":497,"minutes":19494,"time":19495,"words":19496},7.525,451500,1505,{"type":26,"children":19498,"toc":19917},[19499,19504,19509,19514,19519,19524,19529,19532,19538,19548,19564,19574,19579,19582,19588,19597,19606,19615,19618,19624,19633,19642,19651,19684,19689,19698,19701,19707,19716,19725,19734,19739,19742,19748,19757,19766,19775,19780,19783,19789,19799,19809,19826,19829,19835,19854,19867,19880,19893,19906,19909],{"type":29,"tag":30,"props":19500,"children":19502},{"id":19501},"les-anti-patterns-du-backlog-comment-en-sortir",[19503],{"type":35,"value":19484},{"type":29,"tag":37,"props":19505,"children":19506},{},[19507],{"type":35,"value":19508},"J'ai ouvert le Jira d'une équipe bancaire que j'accompagnais pour un diagnostic de delivery. 847 tickets. Les plus anciens dataient de 3 ans. Le PO m'a dit : \"On garde tout, on sait jamais.\"",{"type":29,"tag":37,"props":19510,"children":19511},{},[19512],{"type":35,"value":19513},"J'ai ensuite demandé combien d'items avaient été développés parmi ceux créés il y a plus de 6 mois. La réponse : moins de 8%.",{"type":29,"tag":37,"props":19515,"children":19516},{},[19517],{"type":35,"value":19518},"92% de ce backlog ne serait jamais traité. Mais il existait. Il occupait de l'espace cognitif à chaque session de planning, chaque affinage, chaque conversation sur les priorités. C'est le paradoxe du backlog aspirateur : plus il grossit, moins il est utile, et plus il coûte.",{"type":29,"tag":37,"props":19520,"children":19521},{},[19522],{"type":35,"value":19523},"La promesse du backlog est simple : tout ce qu'on veut faire est documenté, priorisé, et prêt à être planifié. La réalité dans 80% des équipes que j'accompagne : le backlog grossit plus vite qu'il ne se vide, personne ne le lit entièrement, et les vrais sujets urgents se trouvent dans des messages Slack plutôt que dans Jira.",{"type":29,"tag":37,"props":19525,"children":19526},{},[19527],{"type":35,"value":19528},"Voici les 5 anti-patterns responsables de 90% des backlogs inutilisables, et la méthode de sortie.",{"type":29,"tag":76,"props":19530,"children":19531},{},[],{"type":29,"tag":80,"props":19533,"children":19535},{"id":19534},"anti-pattern-1-le-backlog-aspirateur",[19536],{"type":35,"value":19537},"Anti-pattern 1 : Le backlog aspirateur",{"type":29,"tag":37,"props":19539,"children":19540},{},[19541,19546],{"type":29,"tag":65,"props":19542,"children":19543},{},[19544],{"type":35,"value":19545},"Symptôme",{"type":35,"value":19547}," : tout ce qui est mentionné lors d'une réunion, d'une conversation Slack, ou d'un email devient un ticket. Le volume augmente de 10 à 20 items par semaine. Les tickets créés ne sont jamais fermés sauf quand ils sont développés.",{"type":29,"tag":37,"props":19549,"children":19550},{},[19551,19556,19558,19562],{"type":29,"tag":65,"props":19552,"children":19553},{},[19554],{"type":35,"value":19555},"Coût",{"type":35,"value":19557}," : un backlog aspirateur génère une charge cognitive invisible. Chaque session de ",{"type":29,"tag":48,"props":19559,"children":19560},{"href":4304},[19561],{"type":35,"value":4307},{"type":35,"value":19563}," ou d'affinage nécessite de parcourir des centaines d'items pour trouver les 5 à 10 pertinents pour le prochain sprint. En termes de temps : 2 à 4 heures par semaine de chasse aux items pertinents sur un backlog de 400 items.",{"type":29,"tag":37,"props":19565,"children":19566},{},[19567,19572],{"type":29,"tag":65,"props":19568,"children":19569},{},[19570],{"type":35,"value":19571},"Sortie",{"type":35,"value":19573}," : instaurer un critère d'entrée dans le backlog. Un item n'entre dans le backlog que si le PO l'a validé comme pertinent, s'il a une valeur business identifiable, et s'il sera probablement traité dans les 3 prochains mois.",{"type":29,"tag":37,"props":19575,"children":19576},{},[19577],{"type":35,"value":19578},"Les idées \"peut-être un jour\" vont dans un document séparé (Notion, Confluence, même un Google Sheets), non accessible dans le backlog de sprint. La frontière entre \"backlog de travail\" et \"liste d'idées\" est l'une des distinctions les plus importantes qu'une équipe peut établir.",{"type":29,"tag":76,"props":19580,"children":19581},{},[],{"type":29,"tag":80,"props":19583,"children":19585},{"id":19584},"anti-pattern-2-les-stories-sans-critères-dacceptation",[19586],{"type":35,"value":19587},"Anti-pattern 2 : Les stories sans critères d'acceptation",{"type":29,"tag":37,"props":19589,"children":19590},{},[19591,19595],{"type":29,"tag":65,"props":19592,"children":19593},{},[19594],{"type":35,"value":19545},{"type":35,"value":19596}," : des tickets avec un titre, parfois une description vague, et aucun critère d'acceptation. \"Améliorer le dashboard.\" \"Corriger les problèmes de performance.\" Aucune mesure de succès.",{"type":29,"tag":37,"props":19598,"children":19599},{},[19600,19604],{"type":29,"tag":65,"props":19601,"children":19602},{},[19603],{"type":35,"value":19555},{"type":35,"value":19605}," : une story sans critères d'acceptation entre en sprint et génère des aller-retours entre le développeur et le PO pendant le sprint. En moyenne, 3 à 5 interruptions par story floue, à 30 minutes chacune. Sur un sprint avec 4 stories floues : 6 à 10 heures perdues, sans compter le contexte-switching.",{"type":29,"tag":37,"props":19607,"children":19608},{},[19609,19613],{"type":29,"tag":65,"props":19610,"children":19611},{},[19612],{"type":35,"value":19571},{"type":35,"value":19614}," : appliquer la règle \"if it's not testable, it's not ready\". Chaque story qui ne peut pas être vérifiée par un test (automatique ou manuel) est retirée du backlog jusqu'à ce que ses critères d'acceptation soient définis. Le PO est responsable de cette définition.",{"type":29,"tag":76,"props":19616,"children":19617},{},[],{"type":29,"tag":80,"props":19619,"children":19621},{"id":19620},"anti-pattern-3-labsence-de-priorisation-explicite",[19622],{"type":35,"value":19623},"Anti-pattern 3 : L'absence de priorisation explicite",{"type":29,"tag":37,"props":19625,"children":19626},{},[19627,19631],{"type":29,"tag":65,"props":19628,"children":19629},{},[19630],{"type":35,"value":19545},{"type":35,"value":19632}," : le backlog est trié par date de création, alphabétiquement, ou pas du tout. La priorité de chaque item est \"implicite\", connue du PO mais pas visible dans l'outil.",{"type":29,"tag":37,"props":19634,"children":19635},{},[19636,19640],{"type":29,"tag":65,"props":19637,"children":19638},{},[19639],{"type":35,"value":19555},{"type":35,"value":19641}," : lors de chaque sprint planning, la question \"par quoi on commence ?\" déclenche une discussion de 30 à 60 minutes. Le résultat dépend de qui est le plus vocal dans la salle, pas de la valeur business réelle. C'est une forme de prise de décision politique déguisée en planification.",{"type":29,"tag":37,"props":19643,"children":19644},{},[19645,19649],{"type":29,"tag":65,"props":19646,"children":19647},{},[19648],{"type":35,"value":19571},{"type":35,"value":19650}," : priorisation explicite par une méthode cohérente. La méthode importe moins que la cohérence :",{"type":29,"tag":1080,"props":19652,"children":19653},{},[19654,19664,19674],{"type":29,"tag":1084,"props":19655,"children":19656},{},[19657,19662],{"type":29,"tag":65,"props":19658,"children":19659},{},[19660],{"type":35,"value":19661},"RICE",{"type":35,"value":19663}," (Reach × Impact × Confidence / Effort) : chiffré, comparable",{"type":29,"tag":1084,"props":19665,"children":19666},{},[19667,19672],{"type":29,"tag":65,"props":19668,"children":19669},{},[19670],{"type":35,"value":19671},"MoSCoW",{"type":35,"value":19673}," (Must/Should/Could/Won't) : simple, rapide",{"type":29,"tag":1084,"props":19675,"children":19676},{},[19677,19682],{"type":29,"tag":65,"props":19678,"children":19679},{},[19680],{"type":35,"value":19681},"Weighted Shortest Job First",{"type":35,"value":19683}," : ratio valeur/effort, utilisé dans SAFe",{"type":29,"tag":37,"props":19685,"children":19686},{},[19687],{"type":35,"value":19688},"Ce qui compte : la priorité est visible dans l'outil et mise à jour au moins une fois par sprint.",{"type":29,"tag":176,"props":19690,"children":19692},{"cta":178,"href":179,"title":19691,"type":181},"Votre sprint planning dure trop longtemps parce qu'il faut chercher les priorités dans un backlog illisible ?",[19693],{"type":29,"tag":37,"props":19694,"children":19695},{},[19696],{"type":35,"value":19697},"Un backlog dysfonctionnel est souvent le symptôme d'un processus de product discovery manquant ou d'une tension PO/équipe non résolue. En 30 minutes, j'identifie la cause racine et vous donne le plan de \"backlog détox\" adapté à votre contexte.",{"type":29,"tag":76,"props":19699,"children":19700},{},[],{"type":29,"tag":80,"props":19702,"children":19704},{"id":19703},"anti-pattern-4-les-epics-zombies",[19705],{"type":35,"value":19706},"Anti-pattern 4 : Les epics zombies",{"type":29,"tag":37,"props":19708,"children":19709},{},[19710,19714],{"type":29,"tag":65,"props":19711,"children":19712},{},[19713],{"type":35,"value":19545},{"type":35,"value":19715}," : des epics créées il y a 12, 18, 24 mois, toujours \"en cours\", avec 3 stories terminées sur 20. Elles ne sont pas fermées parce que \"on va y revenir un jour.\"",{"type":29,"tag":37,"props":19717,"children":19718},{},[19719,19723],{"type":29,"tag":65,"props":19720,"children":19721},{},[19722],{"type":35,"value":19555},{"type":35,"value":19724}," : les epics zombies créent une illusion de planification. Les items sous ces epics apparaissent dans les recherches et les rapports, gonflant artificiellement le backlog et perturbant les métriques de vélocité. Plus insidieux : elles occupent mentalement le PO et l'équipe dans des discussions de planification sur des sujets qui ne seront statistiquement jamais développés.",{"type":29,"tag":37,"props":19726,"children":19727},{},[19728,19732],{"type":29,"tag":65,"props":19729,"children":19730},{},[19731],{"type":35,"value":19571},{"type":35,"value":19733}," : lors d'une session de \"backlog détox\", appliquer la règle des 90 jours sur les epics. Une epic qui n'a pas eu de story développée dans les 90 jours est soit fermée avec les stories non-terminées marquées \"won't do\", soit réarchivée dans un document de vision produit, soit continuée uniquement si une décision consciente est prise de l'inclure dans la roadmap des 3 prochains mois.",{"type":29,"tag":37,"props":19735,"children":19736},{},[19737],{"type":35,"value":19738},"Dans l'équipe bancaire mentionnée en introduction, la suppression des epics zombies a réduit le backlog de 847 à 312 items en une session de 2 heures. La clarté retrouvée a été immédiate.",{"type":29,"tag":76,"props":19740,"children":19741},{},[],{"type":29,"tag":80,"props":19743,"children":19745},{"id":19744},"anti-pattern-5-le-backlog-comme-outil-de-micro-management",[19746],{"type":35,"value":19747},"Anti-pattern 5 : Le backlog comme outil de micro-management",{"type":29,"tag":37,"props":19749,"children":19750},{},[19751,19755],{"type":29,"tag":65,"props":19752,"children":19753},{},[19754],{"type":35,"value":19545},{"type":35,"value":19756}," : des tickets créés par des managers avec des descriptions de solutions techniques plutôt que de problèmes à résoudre. Ou des tickets de suivi créés pour chaque sous-tâche d'un développement, utilisés pour monitorer l'avancement heure par heure.",{"type":29,"tag":37,"props":19758,"children":19759},{},[19760,19764],{"type":29,"tag":65,"props":19761,"children":19762},{},[19763],{"type":35,"value":19555},{"type":35,"value":19765}," : les développeurs passent plus de temps à mettre à jour les tickets qu'à développer. La création de tickets devient une activité à part entière, et la qualité du code baisse parce que le focus est sur les sous-tâches visibles, pas sur la livraison de valeur.",{"type":29,"tag":37,"props":19767,"children":19768},{},[19769,19773],{"type":29,"tag":65,"props":19770,"children":19771},{},[19772],{"type":35,"value":19571},{"type":35,"value":19774}," : distinguer les tickets de valeur (ce qu'on cherche à accomplir pour l'utilisateur) des tâches techniques (comment on va l'accomplir). Les tâches techniques sont gérées par le développeur dans sa branche Git, pas dans Jira. Le manager voit l'avancement de la story, pas des sous-tâches.",{"type":29,"tag":37,"props":19776,"children":19777},{},[19778],{"type":35,"value":19779},"Ce n'était jamais un problème de confiance individuelle. C'était un problème de système de pilotage inadapté.",{"type":29,"tag":76,"props":19781,"children":19782},{},[],{"type":29,"tag":80,"props":19784,"children":19786},{"id":19785},"la-méthode-backlog-détox-en-3-sessions-de-2h",[19787],{"type":35,"value":19788},"La méthode \"backlog détox\" en 3 sessions de 2h",{"type":29,"tag":37,"props":19790,"children":19791},{},[19792,19797],{"type":29,"tag":65,"props":19793,"children":19794},{},[19795],{"type":35,"value":19796},"Session 1 : Le tri brutal",{"type":35,"value":19798}," (PO + Tech Lead) : parcourir tous les items avec une règle binaire : ce ticket sera-t-il développé dans les 3 prochains mois ? Si non, archiver sans remords. Un ticket archivé peut toujours être réactivé. Résultat attendu : réduction de 40 à 60% du backlog.",{"type":29,"tag":37,"props":19800,"children":19801},{},[19802,19807],{"type":29,"tag":65,"props":19803,"children":19804},{},[19805],{"type":35,"value":19806},"Session 2 : La priorisation",{"type":35,"value":19808}," (PO + équipe) : sur les items conservés, appliquer une méthode de priorisation explicite. Trier le backlog par priorité décroissante. Résultat attendu : un backlog où les 20 premiers items sont les 20 items les plus importants.",{"type":29,"tag":37,"props":19810,"children":19811},{},[19812,19817,19819,19824],{"type":29,"tag":65,"props":19813,"children":19814},{},[19815],{"type":35,"value":19816},"Session 3 : La DoR",{"type":35,"value":19818}," (PO + Tech Lead) : pour les 15 à 20 premiers items (ceux qui pourraient entrer dans les 2 prochains sprints), vérifier que chaque item respecte la ",{"type":29,"tag":48,"props":19820,"children":19821},{"href":13127},[19822],{"type":35,"value":19823},"Definition of Ready",{"type":35,"value":19825},". Les items qui ne la respectent pas sont enrichis ou reportés. Résultat attendu : un backlog actionnable, priorisé, avec les premiers items \"DoR-validés\".",{"type":29,"tag":76,"props":19827,"children":19828},{},[],{"type":29,"tag":80,"props":19830,"children":19832},{"id":19831},"faq-sur-le-backlog-agile",[19833],{"type":35,"value":19834},"FAQ sur le backlog Agile",{"type":29,"tag":381,"props":19836,"children":19837},{},[19838,19843],{"type":29,"tag":385,"props":19839,"children":19840},{},[19841],{"type":35,"value":19842},"1. Quelle taille maximale devrait avoir un backlog ?",{"type":29,"tag":37,"props":19844,"children":19845},{},[19846,19848,19852],{"type":35,"value":19847},"Il n'y a pas de règle universelle, mais un backlog utilisable devrait contenir 2 à 3 mois de travail maximum pour les items priorisés. Un backlog surchargé augmente mécaniquement le ",{"type":29,"tag":48,"props":19849,"children":19850},{"href":50},[19851],{"type":35,"value":4113},{"type":35,"value":19853}," et allonge le lead time. Au-delà, la priorisation devient abstraite et les items du bas ne seront statistiquement jamais développés. Pour une équipe qui livre 20 à 30 story points par sprint, cela représente 80 à 120 items priorisés, avec un volume illimité d'idées dans une liste séparée \"future\".",{"type":29,"tag":381,"props":19855,"children":19856},{},[19857,19862],{"type":29,"tag":385,"props":19858,"children":19859},{},[19860],{"type":35,"value":19861},"2. Qui est responsable du nettoyage du backlog ?",{"type":29,"tag":37,"props":19863,"children":19864},{},[19865],{"type":35,"value":19866},"Le PO est responsable de la santé du backlog, mais le nettoyage est un travail collectif. Le PO décide quoi garder et quoi archiver, mais l'équipe et le Tech Lead valident que les items conservés sont techniquement réalistes et suffisamment détaillés. Un backlog propre est le résultat d'une collaboration, pas d'un seul rôle.",{"type":29,"tag":381,"props":19868,"children":19869},{},[19870,19875],{"type":29,"tag":385,"props":19871,"children":19872},{},[19873],{"type":35,"value":19874},"3. Comment convaincre un PO de supprimer des items qu'il a créés ?",{"type":29,"tag":37,"props":19876,"children":19877},{},[19878],{"type":35,"value":19879},"Utiliser les données. Dans les 6 derniers mois, combien d'items vieux de plus de 6 mois ont été développés ? En général, moins de 10%. Montrer que les 90% restants génèrent du bruit sans produire de valeur. L'argument qui fonctionne : \"Un backlog propre nous permet de nous concentrer sur les 20 items qui comptent vraiment. Les 380 autres nous distraient de ces 20.\"",{"type":29,"tag":381,"props":19881,"children":19882},{},[19883,19888],{"type":29,"tag":385,"props":19884,"children":19885},{},[19886],{"type":35,"value":19887},"4. Faut-il un outil différent pour les \"idées futures\" séparées du backlog ?",{"type":29,"tag":37,"props":19889,"children":19890},{},[19891],{"type":35,"value":19892},"Pas nécessairement. Une section ou un label différent dans le même outil suffit. L'important est la séparation visuelle et fonctionnelle : les items \"futures\" n'apparaissent pas dans le sprint planning, ne sont pas inclus dans les métriques de vélocité, et ne nécessitent pas de DoR. Confluence, Notion, ou un simple Google Sheets fonctionnent très bien pour cette liste d'idées.",{"type":29,"tag":381,"props":19894,"children":19895},{},[19896,19901],{"type":29,"tag":385,"props":19897,"children":19898},{},[19899],{"type":35,"value":19900},"5. À quelle fréquence faut-il faire un backlog détox ?",{"type":29,"tag":37,"props":19902,"children":19903},{},[19904],{"type":35,"value":19905},"Une session initiale de détox (les 3 sessions de 2h décrites ci-dessus), puis une maintenance hebdomadaire de 30 minutes en affinage suffit pour maintenir le backlog sain. Sans maintenance régulière, le backlog reviendra à son état précédent en 3 à 4 mois : les mécanismes d'accumulation sont structurels, pas accidentels.",{"type":29,"tag":76,"props":19907,"children":19908},{},[],{"type":29,"tag":176,"props":19910,"children":19911},{"cta":4551,"href":453,"title":4552,"type":455},[19912],{"type":29,"tag":37,"props":19913,"children":19914},{},[19915],{"type":35,"value":19916},"Le framework pour réduire votre lead time en 90 jours inclut une section complète sur l'optimisation du backlog et des processus de priorisation, avec les templates de session de backlog détox prêts à l'emploi.",{"title":8,"searchDepth":463,"depth":463,"links":19918},[19919,19920,19921,19922,19923,19924,19925],{"id":19534,"depth":463,"text":19537},{"id":19584,"depth":463,"text":19587},{"id":19620,"depth":463,"text":19623},{"id":19703,"depth":463,"text":19706},{"id":19744,"depth":463,"text":19747},{"id":19785,"depth":463,"text":19788},{"id":19831,"depth":463,"text":19834},"content:fr:pratiques-agiles:anti-patterns-backlog.md","fr/pratiques-agiles/anti-patterns-backlog.md","fr/pratiques-agiles/anti-patterns-backlog",1778103261002]