Les patterns d’architecture vus à travers Python
(cosmicpython.com)- Les applications Python complexes deviennent, à mesure qu’elles grandissent, difficiles à tester et à faire évoluer avec de simples approches d’implémentation, et ce livre présente comme réponse des patterns d’architecture à travers des exemples de code
- En prenant comme exemple la vente de meubles en ligne chez MADE.com et une chaîne d’approvisionnement mondiale, il place au centre la modélisation de domaine, c’est-à-dire la transposition des problèmes opérationnels du monde réel en modèles logiciels
- Les axes principaux sont le TDD, le DDD et l’architecture orientée événements, avec pour objectif des tests unitaires rapides, peu de tests E2E, des modèles séparés de l’infrastructure et une intégration fondée sur les messages
- Le livre utilise Flask, SQLAlchemy, pytest, Docker et Redis, mais met surtout l’accent sur la création d’une structure où ces choix techniques deviennent des détails d’implémentation
- Il est accessible à quiconque a déjà travaillé sur des applications Python complexes, sans exiger de connaissance préalable du DDD ni des patterns classiques d’architecture applicative
Partir d’une structure facile à tester
- Après le précédent livre de Harry, Test-Driven Development with Python, une question restait ouverte : comment structurer une application pour qu’elle soit facile à tester ?
- L’enjeu central est de construire une architecture où la logique métier est largement couverte par des tests unitaires, tout en réduisant au minimum le nombre de tests d’intégration et de tests E2E
- Des concepts comme "Hexagonal Architecture", "Ports and Adapters" ou "Functional Core, Imperative Shell" étaient évoqués, mais à l’époque ils n’étaient pas encore suffisamment compris ni réellement mis en pratique
- Bob est devenu architecte faute de quelqu’un pour tenir ce rôle dans l’équipe, et a appris auprès d’Ian Cooper une nouvelle manière d’écrire du code et de penser les systèmes
Le cas MADE.com : modéliser la supply chain en logiciel
- Les deux auteurs ont travaillé chez MADE.com, une entreprise européenne d’e-commerce, et y ont appliqué les techniques du livre à la construction de systèmes distribués modélisant de vrais problèmes métier
- Le domaine d’exemple s’appuie sur le premier système construit par Bob chez MADE et vise aussi à formaliser ce qu’il fallait transmettre aux nouveaux programmeurs rejoignant l’équipe
- MADE.com exploite une chaîne d’approvisionnement mondiale composée de partenaires de fret et de fabricants
- Pour réduire les coûts, l’entreprise cherche à optimiser les expéditions afin d’éviter que le stock ne reste trop longtemps immobilisé en entrepôt
- L’idéal serait qu’un canapé acheté par un client arrive au port le jour même de l’achat, puis soit livré directement chez lui sans stockage intermédiaire
- Comme l’acheminement des marchandises par porte-conteneurs peut prendre trois mois, le calage temporel est difficile
- Dans l’exploitation réelle, des variables comme la casse, les dégâts des eaux, les retards dus aux tempêtes, les erreurs de traitement des partenaires logistiques, l’absence de documents ou les changements de commande des clients se produisent en permanence
- Pour gérer ces problèmes, l’objectif est de représenter les opérations du monde réel dans le logiciel et d’automatiser autant de travail que possible
Les limites qui apparaissent quand un projet Python grossit
- Python a connu une croissance rapide et a gagné en maturité, mais il commence seulement à prendre en charge à grande échelle des problèmes que les écosystèmes C# et Java traitent depuis longtemps
- Les startups deviennent de vraies entreprises, et les applications web comme l’automatisation par scripts évoluent vers du logiciel d’entreprise
- La philosophie de Python affirme “There should be one—and preferably only one—obvious way to do it”, mais quand un projet change d’échelle, la manière la plus obvious n’est pas toujours adaptée pour gérer la complexité et l’évolution des besoins
- Les techniques et patterns abordés dans le livre ne sont pas nouveaux, mais ils restent relativement récents dans l’univers Python
- Le livre ne cherche pas à remplacer Domain-Driven Design d’Eric Evans ni Patterns of Enterprise Application Architecture de Martin Fowler ; il s’y réfère souvent et en recommande la lecture
- Comme les exemples de code de la littérature existante sont souvent écrits en Java ou en C++/#, ils peuvent être plus difficiles d’accès pour les développeurs Python
Trois outils pour maîtriser la complexité
- Le développement piloté par les tests (TDD) aide à produire du code correct et à refactorer ou ajouter des fonctionnalités sans craindre les régressions
- Le livre explique comment exécuter les tests le plus vite possible
- Comment obtenir un maximum de couverture et de feedback avec des tests unitaires rapides et sans dépendances
- Et comment réduire au minimum les tests E2E, lents et fragiles
- La conception pilotée par le domaine (DDD) aide à se concentrer sur la création d’un bon modèle du domaine métier
- Le livre montre comment éviter que le modèle ne soit prisonnier des préoccupations d’infrastructure
- Et comment éviter qu’il ne devienne difficile à faire évoluer
- Les microservices faiblement couplés intégrés par messages, parfois appelés reactive microservices, sont présentés comme une réponse à la complexité entre plusieurs applications ou domaines métier
- En revanche, il n’est pas toujours évident de voir comment cela s’articule avec les outils déjà présents dans l’écosystème Python comme Flask, Django ou Celery
- Même sans utiliser de microservices, ou sans intérêt particulier pour eux, la plupart des patterns du livre ainsi qu’une bonne partie de l’architecture orientée événements restent applicables à une architecture monolithique
Lecteurs visés et connaissances préalables
- Le livre s’adresse à des lecteurs ayant déjà côtoyé des applications Python d’une certaine complexité
- Il est pensé pour celles et ceux qui ont déjà ressenti la douleur liée à la gestion de la complexité
- Aucune connaissance préalable du DDD ni des patterns classiques d’architecture applicative n’est nécessaire
- Les explications s’accumulent chapitre après chapitre autour d’une application d’exemple
- Comme les auteurs utilisent le TDD dans leur travail, ils montrent souvent d’abord les tests, puis l’implémentation
- Flask, SQLAlchemy, pytest, Docker et Redis sont utilisés, mais les connaître à l’avance aide sans être indispensable
- L’un des objectifs majeurs est de construire une architecture dans laquelle les choix techniques particuliers deviennent de simples détails d’implémentation
Structure du livre
- Le livre est divisé en deux parties
-
Partie 1 : une architecture au service de la modélisation de domaine
- La modélisation de domaine et le DDD sont traités dans les chapitres 1, 2 et 7
- Le livre part du principe qu’un modèle de domaine dans le code doit refléter des problèmes métier complexes
- Il explique comment commencer par un modèle sans dépendances externes, testable rapidement via des tests unitaires
- Il revient ensuite sur le choix des aggregates pertinents et sur les problèmes d’intégrité des données
- Les patterns Repository, Service Layer et Unit of Work sont abordés dans les chapitres 2, 4 et 5
- Ces patterns se complètent pour isoler le modèle de dépendances inutiles
- Ils introduisent une couche d’abstraction autour du stockage persistant ainsi qu’une couche de service qui capture les points d’entrée du système et les principaux cas d’usage
- Le livre montre une structure qui facilite la création de points d’entrée fins, comme une API Flask ou une CLI
- La discussion sur l’abstraction et les tests se poursuit dans les chapitres 3 et 5
- Après l’introduction du pattern Repository, il traite de la manière de choisir une abstraction et du rôle de l’abstraction dans les modes de couplage
- Après le pattern Service Layer, il aborde la pyramide des tests et la manière d’écrire des tests unitaires au niveau d’abstraction le plus élevé possible
-
Partie 2 : architecture orientée événements
- L’architecture orientée événements est abordée dans les chapitres 8 à 11
- Les patterns Domain Events, Message Bus et Handler y sont introduits
- Les Domain Events servent à exprimer l’idée qu’une interaction dans le système peut déclencher d’autres actions
- Le Message Bus permet à une action de déclencher un événement et d’appeler le handler approprié
- Le livre montre comment utiliser les événements comme pattern d’intégration entre services dans une architecture de microservices
- Il distingue commands et events, l’application devenant fondamentalement un système de traitement de messages
- Le chapitre 12 présente un exemple de CQRS, avec et sans recours aux événements
- Le chapitre 13 clarifie les dépendances explicites et implicites et implémente un framework simple d’injection de dépendances
- L’épilogue explique non pas comment repartir de zéro avec un exemple simple, mais comment appliquer ces principes à un logiciel existant, avec des pistes de lecture complémentaires
Code d’exemple et mise en pratique
- Le livre est construit autour d’un projet d’exemple unique, enrichi progressivement au fil des chapitres
- Il accorde de l’importance au fait que le lecteur manipule réellement le code pour acquérir une intuition sur le fonctionnement des patterns
- Tout le code est disponible sur GitHub, avec une branche distincte pour chaque chapitre
- La liste des branches est disponible sur la page branches de GitHub
- Trois façons de suivre le livre sont proposées
- Créer son propre dépôt, construire l’application en suivant les exemples du livre et consulter le dépôt des auteurs quand nécessaire
- Essayer d’appliquer chaque pattern, chapitre par chapitre, à l’un de ses petits projets
- Pratiquer rapidement à l’aide des "Exercise for the Reader" de chaque chapitre et du code GitHub partiellement laissé vide
- Pour les lecteurs qui veulent surtout appliquer les patterns à leur propre projet, commencer par les exemples simples constitue un terrain d’entraînement sûr
- Il est au minimum recommandé, à la lecture de chaque chapitre, de récupérer le code avec
git checkoutdans le dépôt pour l’examiner dans le contexte d’une application réellement fonctionnelle
Licence et conventions typographiques
- Le code et la version en ligne sont publiés sous licence Creative Commons CC BY-NC-ND
- Usage non commercial
- Attribution
- Copie et partage autorisés
- L’édition imprimée suit une licence distincte, et en cas de doute sur la réutilisation il est conseillé de contacter O’Reilly
- Le livre distingue plusieurs conventions typographiques : italique, chasse fixe, chasse fixe en gras et chasse fixe en italique
- L’italique sert à signaler les nouveaux termes, les URL, les adresses e-mail, les noms de fichiers et les extensions
- La chasse fixe représente les listings de programme et les éléments de code
- La chasse fixe en gras désigne les commandes ou textes que l’utilisateur doit saisir tels quels
- La chasse fixe en italique désigne les textes à remplacer par des valeurs fournies par l’utilisateur ou définies par le contexte
2 commentaires
Il existe une édition en coréen : Architecture Patterns with Python
Avis sur Hacker News
Ce livre est une véritable mine d’or pour apprendre les patterns d’architecture : il entre vite dans le sujet et permet d’en saisir facilement l’essentiel.
Cela dit, d’un point de vue pratique, certains de ces patterns peuvent fortement accroître la complexité et poser des problèmes de performance en Python, surtout lorsqu’ils sont utilisés avec des frameworks comme Django, qui reposent déjà sur le pattern ActiveRecord.
Après avoir travaillé dans des entreprises de toutes tailles utilisant Python, j’ai constaté que les grandes entreprises qui appliquaient des patterns d’architecture stricts avaient certes un code « propre », mais que des tâches qui semblaient simples au départ devenaient excessivement complexes et inutilement lentes.
À l’inverse, les grandes entreprises qui ne se préoccupaient pas de ces patterns avaient parfois du code vraiment laid, comme d’énormes fichiers remplis de if-else ou des modèles Django contenant toute la logique métier, mais il était plus productif, parce qu’on pouvait le lire, le comprendre et modifier un if-else de 1 000 lignes.
Je n’aime pas admettre que j’étais plus productif dans les entreprises où le code n’était pas propre, mais cela évitait aussi beaucoup de débats sans fin sur ce qui est vraiment propre.
Quelqu’un décide que « pour faire X ou Y, il faut d’abord créer N autres choses », si bien qu’une tâche simple oblige à modifier plusieurs fichiers, fonctions et classes.
Dans les entreprises qui ne se soucient pas des patterns d’architecture, il peut y avoir beaucoup de code disgracieux, mais il y a souvent moins d’indirections et la zone à modifier est regroupée au même endroit, ce qui la rend plus facile à comprendre pour une nouvelle personne.
Une fonction de 100 lignes, dans laquelle on peut naviguer, modifier et déboguer facilement, vaut souvent mieux que de petites fonctions dispersées dans plusieurs fichiers.
Cela ne veut pas dire que toutes les abstractions sont mauvaises, mais plus je travaille longtemps, plus j’ai l’impression que moins il y a d’abstractions, plus il est facile de raisonner sur les unités ou fonctionnalités individuelles du code ; j’en conclus qu’il vaut mieux n’abstraire que ce qui est vraiment difficile, et ne pas abstraire ce qui est simple.
Quand on a les deux, l’exploration de la base de code est intuitive ; s’il manque l’un des deux, une fonction de 1 000 lignes peut sembler plus facile à lire.
Un vaisseau spatial est un produit hautement conçu et fonctionne en grande partie comme un dispositif contrôlé par logiciel ; il contient donc déjà un modèle de conception propre que l’on peut découvrir et copier.
La modélisation de domaine ne devrait pas consister à copier un modèle existant, mais à tirer parti des avantages du logiciel pour faire mieux que les technologies physiques ou sociales que le nouveau logiciel vise à remplacer.
Les modèles de domaine existants contiennent aussi d’excellentes abstractions, dont beaucoup d’éléments clés doivent être repris dans le nouveau modèle, et il est également important de comprendre ce que les parties prenantes cherchent à accomplir avec le système actuel.
Mais les modèles du monde de l’entreprise et de la culture ne sont pas optimisés pour le code, sont souvent anciens ou brouillons, et les cas limites ainsi que les parties moins explicites sont interprétés et traités par des humains.
Il faut considérer ces modèles comme une source d’inspiration, pas comme l’objectif final.
Ces patterns d’architecture ressemblent à la gestion de projet : les deux créent de l’overhead, et si on les utilise sans discernement, leur coût dépasse largement la valeur obtenue, ce qui leur donne une mauvaise réputation.
Mais utilisés avec prudence, ils peuvent être décisifs pour la réussite d’un projet.
Par exemple, si je devais construire une simple API REST de calendrier, je n’utiliserais pas une architecture complexe.
En revanche, dans un système de trading, respecter une architecture ports et adaptateurs était très important pour passer sans heurts du mode simulation au mode production.
Il fallait pouvoir remplacer facilement le simulateur par le moteur de trading réel, ainsi que les flux d’événements historiques par les flux en temps réel, car il était impossible de maintenir deux versions synchronisées de la logique métier.
Un pattern n’est pas une implémentation ; c’est plutôt un processus de réflexion sur ce que l’on fait, un plan pour le traiter, et la conception de haut niveau de l’API que l’on veut offrir au reste du code.
En Python, les fonctions étant des objets, une machine à états peut souvent se résumer à un ensemble de fonctions qui se renvoient les unes les autres, avec une répétition de
f = f(x).On suggère parfois d’utiliser le pattern Borg à la place de Singleton, mais dans la pratique, il suffit souvent d’utiliser un module, et
sysfournit déjà quelque chose qui se comporte comme un singleton.« L’injection de dépendances » n’est souvent qu’un terme chic pour dire que l’on passe des arguments à une fonction, parfois une autre fonction.
Flyweight n’est pas une entité séparée, mais une technique d’interning, et le pattern Command mentionné dans le texte original était l’un des points centraux de la célèbre conférence critique de Jack Diederich (https://www.youtube.com/watch?v=o9pEzgHorH0) ; il suffit souvent de bien utiliser
functools.partial.La dichotomie entre code propre et code laid peut n’être qu’une illusion due au fait qu’on n’a pas encore vu de meilleurs exemples.
Une fonction courte n’exige pas une hiérarchie de classes complexe, et il se peut même qu’une classe ne soit pas nécessaire au départ.
La programmation orientée objet concerne les objets, pas les classes ; si les classes avaient été le cœur du sujet, on l’aurait appelée programmation orientée classes.
Dans ce livre, les concepts qui dépassent Python ou un langage particulier, par exemple l’architecture événementielle, les commandes ou CQRS, sont très utiles.
Cela dit, d’autres parties posent problème, et cela peut devenir dangereux quand des développeurs peu expérimentés les prennent comme un dogme et essaient de tout implémenter d’un coup.
Le pattern repository est généralement utile, mais dans de nombreux cas, y compris dans les exemples du livre, il devient un choix excessif qui apporte très peu de bénéfices tout en augmentant la complexité.
Surtout si l’on utilise SQLAlchemy, car SQLAlchemy joue déjà en quelque sorte le rôle de repository — plus exactement, celui d’une couche d’abstraction de base de données relationnelle avec un ORM par-dessus.
La couche de services et l’unité de travail sont aussi utiles pour des applications avec de nombreux cas d’usage complexes, mais dans un système composé de petits services à responsabilité étroite, elles gonflent vite.
Il en va de même pour l’injection de dépendances en Python.
Les design patterns sont au fond des outils : les développeurs doivent donc comprendre quand les utiliser et, plus important encore, quand ne pas les utiliser.
Ce conseil existe aussi dans le livre, mais j’aurais aimé qu’il soit mis davantage en avant dès le début plutôt qu’à la fin de chaque chapitre.
Dès qu’un accès à la base de données est nécessaire, je le vois comme un pattern léger que je recommanderais presque toujours pour séparer les responsabilités.
Au fond, il s’agit simplement de faire passer tous les accès à la base de données pour une entité donnée par un seul repository propre à cette entité ; à l’intérieur du repository, on peut exécuter directement des requêtes ou utiliser un ORM, comme on veut.
Une bonne partie de ce qui est dit dans la section sur le pattern repository relève davantage de détails propres à Python, Django et SQLAlchemy que du pattern lui-même.
J’utilise surtout Python, et je comprends l’injection de dépendances comme le fait de « faire en sorte qu’une fonction reçoive en paramètres toutes les entrées nécessaires à son calcul » ; cela m’a semblé être un principe central valable pour concevoir un projet.
La couche de services et l’injection de dépendances m’ont pas mal aidé à écrire des programmes fonctionnels.
J’utilise un script complexe de traitement d’images écrit en Python comme une sorte de plugin pour un service distribué de traitement d’images basé sur Celery ; la couche de services et l’injection de dépendances transforment le code de
dependency.do_thing(params)endo_thing(dependency, params).Cela rend les tests beaucoup plus faciles.
On peut exécuter des tâches de traitement d’images avec toutes les E/S remplacées par des fausses dans l’environnement de production réel, ou exécuter de vraies tâches de traitement d’images sur un faux Celery.
On peut tester plusieurs fonctions de bout en bout avant le déploiement complet, et avec un type Result dans la couche de services, il était aussi plus facile de transmettre au client web les informations d’erreur pertinentes sans faire planter le programme.
Il est intéressant de voir ces patterns, mais ce serait encore mieux d’avoir au début un guide indiquant dans quelles situations ils sont les plus utiles à implémenter.
Si les patterns sont des outils, il est utile d’expliquer quand les utiliser et quand les éviter.
Les sections avantages/inconvénients en parlent dans une certaine mesure, donc c’est peut-être surtout une question d’ordre et d’accent.
En construisant une petite application web pour une nouvelle activité tout en apprenant Python, certains patterns m’ont donné des idées pour simplifier, tandis que d’autres m’ont fait conclure qu’il valait mieux les éviter.
Je pense qu’avec des choses comme « Clean Code », il a endoctriné des développeurs peu expérimentés et causé d’énormes dégâts.
Le génie logiciel n’est pas une science naturelle rigoureuse : il existe rarement de solution miracle, et tout est une question de compromis.
Les personnes qui affirment connaître la seule vraie voie sont dangereuses, ou proches du niveau débutant.
Je suis développeur TypeScript, mais ce livre fait partie de mes livres d’architecture préférés, et je m’y réfère souvent.
J’aime particulièrement les fausses unités de travail et le pattern service pour les tests, et je les utilise presque religieusement dans tous mes projets quand il s’agit de remplacer des services tiers par des faux.
Le point important ici, c’est qu’il s’agit de faux objets, pas de mocks.
Le livre m’a aussi aidé pour les questions de nommage : par exemple, il recommande de nommer les événements de façon spécifique au domaine, plutôt que centrée sur l’infrastructure ou les patterns.
Autrement dit,
CART_ITEM_BECAME_UNAVAILABLEest préférable àUSER_NOTIFICATION.Certaines de ces choses sont évidentes, mais pénibles à expliquer à une équipe ; comme cosmic python est disponible en ligne, il est facile d’envoyer un lien.
Globalement, c’est une excellente ressource, qui m’a beaucoup influencé.
https://www.obeythetestinggoat.com/pages/book.html
C’est aussi un livre auquel je suis attaché, et même si je n’ai presque jamais utilisé Python en pratique, j’y reviens souvent quand j’utilise d’autres langages.
J’apprécie aussi qu’il soit disponible à la fois en ligne et en version papier.
Je compte vraiment lire celui-ci aussi.
Je vois Python comme un bon langage de collage.
J’en ai assez de la mentalité objet forcée qui impose l’encapsulation et l’héritage partout, avec uniquement des champs privés à modifier via des méthodes.
J’en ai aussi assez de SOLID, du clean coding, de la clean architecture, des patterns GoF et d’Uncle Bob.
J’en ai assez du royaume des noms et de FizzBuzz Enterprise Edition.
Désormais, je réduis l’orienté objet autant que possible et je suis plutôt des flux impératifs ou fonctionnels.
Quand j’utilise Python de temps en temps — principalement parce que j’utilise .NET au travail, pas parce que je n’aime pas Python — je veux une expérience libérée des objets et des patterns.
Cela ne veut pas dire que ce livre n’a pas de valeur : il est utile pour apprendre les patterns.
Mais il ne faut pas faire entrer toute la programmation réelle dans le moule des patterns, des objets et de SOLID.
Ainsi, la complexité sans lien direct reste en dehors du domaine, et l’on peut réutiliser ces fonctions sans devoir toujours créer un objet complet dont on n’a pas besoin.
Si ce qui est tenté ici ressemble grosso modo à ça, ça paraît vraiment excessif
On réimplémente les modèles SQLAlchemy en appelant ça un « dépôt », on réimplémente les sessions SQLAlchemy en appelant ça une « unité de travail », et on ajoute une « couche de services » qui n’utilise même pas les modèles
Au nom de la réduction du couplage, on déroule tous les attributs des modèles en paramètres de fonctions séparés, et on disperse tout dans un bus de messages, comme pour supprimer toute possibilité de débogage
Mais tout cela ne concerne que le chemin d’écriture
Pour la lecture, il y a des tables dénormalisées séparées et des requêtes en SQL brut
C’est effectivement ce qu’on voit au chapitre 12
Si l’on regarde le trafic de MADE.com, le mois dernier il y a eu environ 500 000 visites au total sur desktop et mobile, soit environ 12 vues par minute
Dans ce contexte, on ne peut s’empêcher de penser avec cynisme qu’ils ont de la chance d’avoir un boulot où l’on peut parler de DDD toute la journée
Chaque pattern est accompagné d’un résumé de ses avantages et inconvénients, et même s’il y a des manques, ils disent clairement qu’il faut réfléchir à l’adéquation du pattern aux besoins de l’application
Peu d’applications auront besoin de tout ce qui est dans le livre, mais il y en a certainement beaucoup auxquelles on peut appliquer un ou plusieurs patterns
Mais si c’est un compte jetable, ça ressemble surtout à une réaction négative de passage sans grande valeur
J’ai commencé à utiliser Python professionnellement il y a quelques années
Je venais de Kotlin et de TypeScript, et même si le langage lui-même était accessible, j’ai eu du mal à obtenir le faible couplage et la testabilité auxquels j’étais habitué tout en restant idiomatique en Python
Sur recommandation d’un collègue, j’ai acheté ce livre et l’ai lu de bout en bout ; il m’a beaucoup aidé à comprendre comment gérer la complexité dans une base de code Python non triviale
Je ne suis pas tous les patterns qu’il recommande, mais il m’a montré ce qui était possible et comment appliquer à Python l’expérience acquise dans d’autres paradigmes sans donner l’impression d’être « un développeur Java qui fait du Python »
Je le recommande vivement, et je n’ai pas regretté l’argent dépensé
C’est vraiment l’un des excellents livres de programmation Python
La seule chose que j’ai regrettée, c’est le manque de typage statique dans le code, mais c’était un choix délibéré des auteurs
La difficulté à ajouter des annotations de type à du code est un très bon indicateur de la difficulté qu’on aura plus tard à comprendre ce code
Il y a bien des annotations de type comme ici : https://www.cosmicpython.com/book/chapter_08_events_and_mess...
Certaines parties du livre n’ont toutefois pas d’annotations de type
dataclasses, ce qui impose des annotations de typePython ne prend pas en charge le typage statique
Les outils fondés sur les annotations de type n’ont pas d’effet sur le processus de compilation et, sauf dans les cas qui utilisent de la métaprogrammation comme
dataclasses, ils ne peuvent pas non plus faire en sorte que Python rejette le codeIls ne font que fournir des diagnostics
J’ai ce livre dans ma bibliothèque
C’est un petit livre, comme K&R, et il porte pas mal de traces d’usure à force d’être feuilleté
C’était une très bonne lecture, et un très bon résumé
Il y a environ trois ans, je travaillais dans un environnement DDD basé sur C#/.NET, et en revoyant aujourd’hui ces concepts avec Python, l’essentiel me paraît mieux dégagé
Je le recommande vivement à quiconque s’intéresse à ce type de contenu
J’ai lu la version papier de ce livre il y a environ deux ans et demi à trois ans, et je l’ai beaucoup appréciée
Il réussit très bien à garder les tests comme sujet de premier plan et à les mettre régulièrement à jour à chaque ajout de fonctionnalité
Certains anciens livres d’architecture ne donnent pas une priorité aussi élevée aux tests
Si l’on fait en sorte que les tests soient faciles à préparer, à écrire et à mettre à jour, on passe moins de temps à exécuter le code manuellement pour vérifier les problèmes, ce qui rend le développement plus agréable
Cela donne une boucle de feedback plus rapide
La partie orientée événements du livre était très intéressante, mais elle ne m’a pas semblé très pratique à implémenter réellement dans mon travail actuel