Vous souhaitez nous soutenir ? Devenez sponsor de l'association sur notre page Github

qsdqsdqsdq

Publié le ? par Mathieu De Gracia
Couverture de l'article qsdqsdqsdq

fvCet article est la suite directe de notre article sur la mise en place d'une clean architecture dans une application Laravel avec un fort legacy.

Le précédent article se concentrait essentiellement sur notre compréhension de la clean architecture, sur les stratégies techniques et les différentes implémentations que nous avons pu mettre en place.

Celui-ci se concentrera sur un autre aspect, bien moins technique, mais tout aussi important si vous décidez de vous lancer dans l’amélioration de vos architectures : comment, en tant que lead développeur, j’ai embarqué les développeurs de l’équipe dans cette refonte

Cet article s'adresse à toutes personnes

Les développeurs

Durant toutes ces refontes, vos principaux intermédiaires seront les développeurs.

Après tout, ce sont eux qui auront la charge de développer et de maintenir l'application et qui seront, au jour le jour, directement confrontés à la complexité de l'architecture.

Obtenir leur adhésion est donc un prérequis tout simplement essentiel.

Vous ne pourrez jamais vous permettre une refonte laborieuse si vos développeurs ne sont pas pleinement impliqués dans le processus.

En tant que lead, votre principale responsabilité sera la bonne compréhension de ces concepts par vos développeurs. Cela vous amènera à prendre le temps d'expliquer les choses, à créer des supports résumant les concepts clés, à présenter les informations en groupe ou de manière plus ciblée pour les développeurs bloqués sur certaines notions.

Vous allez probablement répéter les mêmes choses, encore et encore, et si des points de blocage subsistent vous serez alors contraint de revoir votre approche différemment. Si vous n'appréciez pas l'idée de répéter quelque chose que vous pensiez avoir déjà transmis alors le poste de Lead n'est probablement pas fait pour vous.

De par votre rôle de leader, vous êtes le seul responsable de l'incompréhension de vos développeurs.

Un tableau collaboratif, comme excalidraw, sera alors salvateur pour vous et vos équipes, vous permettant de prendre de la hauteur et de mieux visualiser les synergies entre les différentes couches de votre application.

La pédagogie sera le principal levier d'adhésion des développeurs, il est fort à parier que vous vous retrouverez rapidement avec des dizaines de schémas explicatifs :

Qelques schémas parmi tant d'autres

Passez un deal avec vos développeurs : celui que vous prendrez toujours le temps nécessaire pour les faire monter en compétences sur ces notions, tant qu'ils resteront ouverts d'esprit face à leur propre incertitude.

Ne pas comprendre un concept n’est pas grave, c’est même inévitable. D'autant que les architectures en layers ne sont pas toujours accessibles ou évidentes à appréhender, ne dites jamais, au grand jamais, que ces choses sont simples, car déjà, cela serait mentir et vous ajouterez une barrière supplémentaire à leur bonne compréhension : celle du jugement personnel.

Si je ne comprends pas cette chose simple, est-ce que je suis bête ?

Au contraire, embrasser cette complexité, présenter les choses telles qu'elles sont, avec toute leur richesse et leur complexité. Restez sincère dans ce que vous abordez et constituez un environnement de travail sain dans lequel les développeurs pourront exprimer leurs craintes sans peur du jugement.

Percevez le refus de s’investir comme un mécanisme d’auto-défense : face à la peur de l’échec, du jugement ou de la surcharge cognitive, certains préféreront bloquer l’apprentissage, cherchant une faille susceptible de remettre en cause la théorie, plutôt que d’affronter leur vulnérabilité.

Cette situation est d’autant plus problématique que vous n’aurez pas toujours réponse à toutes leurs interrogations. Votre propre compréhension de la clean architecture peut encore être partielle ou incomplète et votre incapacité à répondre peut les laisser dans l’incertitude, voire pire, être perçue comme une faiblesse confirmant leurs doutes.

C’est précisément dans ces moments de flottement que votre posture de Lead compte le plus : vous n’avez pas besoin d’avoir réponse à tout pour incarner une direction.

Faites-leur prendre conscience que la Clean Architecture est un concept robuste et éprouvé, cela n’est pas une lubie personnelle, ni une mode passagère, mais une architecture pensée, testée et validée par des développeurs à toutes les échelles.

Cette posture de rejet protège temporairement leur estime de soi, mais pourrait devenir délétère pour le projet et l'équipe car elle freine la progression collective et empêche de dépasser les obstacles techniques.

Si cette situation perdure, deux options s’offrent à vous.

Dans le cas où la notion problématique ne bloque pas la mise en place de la clean architecture, concentrez-vous sur les points essentiels et ne vous attardez pas sur les détails. Acceptez que le code produit par vos développeurs ne corresponde pas toujours exactement à ce que vous espériez d'eux.

Si au contraire le point de blocage est central, invitez alors le développeur à suspendre momentanément son besoin de comprehension et proposez-lui de passer à la pratique, même à l’aveugle. Non pour imposer quoi que ce soit mais pour laisser l’idée mûrir, car il est fort probable que ce blocage s’estompe avec le temps à mesure que le concept global de la clean architecture s’enracine et que la compréhension s’installe naturellement.

Dans tous les cas, pédagogie, bienveillance et confiance doivent rester vos maîtres-mots : à vous de trouver le bon équilibre à adopter en tant que Lead.

Les choses essentielles

Bien que les architectures en layers soient complexe, il est toujours possible de résumer ces concepts de manière simpliste, voire naïve.

Avec du recul et le retour d'expérience de plus d'une dizaine d'applications PHP / Laravel en Clean Architecture, j’apprécie désormais de les simplifier à l’extrême avec la phrase suivante : les choses essentielles ne dépendent pas des choses triviales.

Cette phrase est volontairement floue et abstraite mais elle reprend à mes yeux l’essence même de la clean architecture, ou du moins ce qu’elle cherche à nous transmettre.

Cette relation ne peut cependant aller que dans un sens, une chose importante ne doit jamais dépendre d’une chose moins importante : c'est aussi simple que ca.

Tentons maintenant de l'illustrer avec un exemple plus concret.

Imaginez la logique de facturation de votre application, ce composant est probablement l’un des plus critiques de votre système, utilisé et réutilisé par de nombreux autres. À ce titre, il ne devrait en aucun cas connaître les détails insignifiants de l’interface utilisateur.

🚨
Cela serait comme si le moteur d'une voiture dépendait de la couleur de la carrosserie.

Et pourtant c’est exactement ce qui se passe quand les couches centrales de votre architecture commencent à dépendre de l’interface utilisateur, du framework, d'une API ou tout simplement de la base de données.

Il est parfois difficile de mettre des mots sur ces "choses" alors la Clean Archi propose habituellement ce fameux découpage en 4 layers :

Les choses les plus triviales se trouvent à la base de ce schéma : la logique de présentation et d'infrastructure. La logique applicative s'appuie dessus et sert au bon fonctionnement de la logique métier qui se situe tout en haut du schéma.

Mais ce découpage n’est pas qu’un simple empilement de composants : il vise à isoler ensemble les éléments qui évoluent au même rythme et pour les mêmes raisons.

Ainsi, la couche domaine, qui change peu et uniquement pour des raisons métier, reste indépendante des couches techniques, plus sujettes à des changements fréquents liés aux évolutions technologiques. Ce regroupement cohérent, et le respect des frontières, permettent de limiter la propagation du changement et de préserver la stabilité du cœur de votre application.

Essayons maintenant de mettre des mots sur ces différentes couches :

Plus une couche est haute dans ce schéma et plus elle est centrale, stable et précieuse : c’est le cœur de votre métier, ce qui donne un sens à votre application. Et plus on descend, plus on s’approche du sol et des détails concrets, changeants et remplaçables.

Cela ne signifie pas que les couches du bas sont inutiles, elles sont simplement moins fondamentales. Une interface utilisateur peut évoluer, une base de données peut être migrée, un framework remplacé ... mais la logique métier, elle, perdure.

Les règles de calcul des taxes de votre entreprise, présentes dans la couche domaine, évolueront ponctuellement tandis que le package permettant d'effectuer des appels API, dans votre couche d'infrastructure, recoit probablement des mises à jour hebdomadaires.

Le découpage proposé par la Clean Architecture met en lumière cette différence : les détails techniques évoluent vite, la logique métier beaucoup plus lentement.

En tant que Lead, vous devrez transmettre cette philosophie car plus que des schémas complexes, la Clean Architecture repose sur une idée simple : construire une architecture stable, c’est savoir distinguer ce qui doit durer de ce qui est amené à changer et à organiser le code en conséquence.

Une architecture progressive

Appliquer à la lettre les concepts de la Clean Architecture tels que décrits par Robert C. Martin est une tâche difficile, parfois même inatteignable, lorsque l'on travaille sur un projet avec plusieurs années (voir décennie) de legacy.

Vous ne pourrez pas tout refactoriser, peut-être car votre couverture de tests n’est pas suffisante pour sécuriser ces travaux. Peut-être que la codebase est trop vaste et le temps trop limité. Ou peut-être tout simplement que votre compréhension, ou celle de vos développeurs, n’est pas encore assez solide pour envisager une implémentation complète.

En somme, vous êtes confronté au monde réel et à cela, je ne répondrai qu’une seule chose : détendez vous, tout n’a pas besoin d’être parfait.

Aujourd’hui encore, la plupart de nos implémentations restent partielles, car la qualité architecturale doit toujours être en corrélation avec la valeur de ce que l’on développe : tous les développements n’ont pas besoin d’être coûteux pour répondre de maniére adéquates à nos utilisateurs.

💡
J'insiste sur le partielles, même les développements peu qualitatifs doivent embarquer un minimum de réflexion architecturale.

Dans ce processus d’apprentissage, il serait vain d’espérer une conformité totale avec la théorie dès la première implémentation, cela n’est tout simplement pas humainement possible : il y a énormément de notion à transmettre, à comprendre, à expérimenter.

Les implémentations seront donc forcément progressives, parfois maladroites, souvent incomplètes … et c’est normal.

Le plus important sera toujours de comprendre les concepts, de bien saisir les règles pour réussir à en capter l’essence et peut-être, avec le temps, apprendre à les détourner.

ADP, CCP, CRP, DIP, ISP, LSP, OCP, REP, SAP, SDP ... Si vous ignorez la signification de l’un de ces acronymes, vous ne pourrez peut être pas appliquer à la lettre la Clean Architecture, mais ce n’est pas grave : comprendre les grandes idées, les expérimenter pas à pas, sera un excellent début

Voyons maintenant la lente progression que nous avons pu observer dans l’implémentation de la Clean Architecture au fil de nos projets.

Les premiers pas

Pour commencer, nul besoin de parler directement de Clean Architecture, vous devrez d’abord transmettre des réflexions sur l’isolation des couches et l’action se prêtera très bien à l'exercice.

L'architecture n'est pas qu'un empilement de choses ou une organisation de dossiers, c'est avant tout une réflexion plus globale sur la manière dont les composants interagissent entre eux et dépendent (ou non) les uns des autres.

Le pattern action est à la mode depuis quelques années, la plupart du temps les développeurs l’utilisent pour encapsuler du code auparavant situé dans les controllers, c’est un bon début mais insuffisant si nous réfléchissons en terme d'architecture.

Ce qui compte vraiment, c’est l’isolation de l’action.

Une action ne doit pas savoir qui l’utilise : un contrôleur, une commande, un job ? Peu importe, tout cela n’est qu’un détail technique, un bruit extérieur qui ne doit jamais influencer son comportement.

Il est donc inacceptable de voir une action dépendre de quoi que ce soit qui trahirait son contexte d’exécution. Par exemple, passer une instance de Request à une action revient à la lier implicitement à un contrôleur HTTP : c’est une transgression du principe même d’isolation.

L’action n’a que faire de ces détails, son rôle est simple : faire une chose, bien, et sans dépendre du monde extérieur.

Une action declare donc un besoin, à travers un DTO Input et retourne des informations sous la forme d'un autre DTO, le Output.

Cette première étape sera relativement simple à mettre en place, consistant essentiellement à déplacer du code, mais cela vous permettra d'entamer les premières discussions sur l'isolation des couches et de comment l'information et le contexte d'utilisation peuvent fortement influencer les composants : en somme, vos premières réflexions d'architectures.

Maintenant que l'action contient tout le code d'un cas d'utilisation, la logique d'affichage se trouve toujours dans un contrôleur, dégradant sa testabilité, il sera désormais temps d'ajouter un nouveau composant : la logique de présentation.

Cette étape consistera surtout à déplacer tout le code ayant trait à la réponse de l'utilisateur : les redirections, les flash messages, préparer les messages d'erreur, afficher les pages, etc

En isolant ces préoccupations dans un composant dédié, vous pourrez les tester de manière exhaustive, en dehors du contrôleur et donc sans la nécessité de simuler une requête HTTP dans vos tests : pouvoir tester comment votre application réagit à l'output d'une action est une chose précieuse que vous apprécierez certainement.

Cette seconde étape ne devrait pas poser d'interrogation supplémentaire, les réflexions étant les mêmes que celles qui vous auront poussé à découper votre action précédemment : regrouper les logiques vivant pour les mêmes raisons et au même rythme et les isoler du monde extérieur

À ce moment là, toute la logique de présentation devrait se trouver dans le Presenter, celui ci reçoit l'output de l'action, prépare les données et les restitue à l'utilisateur.

Pour aller un peu plus loin dans le composant de presentation, vous pourrez mettre en place deux nouveaux composants : un View et un ViewModel :

Préparer et restituer sont deux préoccupations différentes, afin de respecter plus finement le principe de responsabilité unique, nous pourrions déplacer ces logiques dans deux nouveaux composants : le ViewModel, un DTO contenant les informations à afficher, et la View, un composant chargé de restituer ces informations à l’utilisateur en manipulant le ViewModel.

Nous obtenons ainsi un triptyque de classe ayant chacune une responsabilité marquée et unique :

💡
Ce découpage supplémentaire devient pertinent dès lors que la logique de présentation se complexifie et se doit être testée en profondeur

Encore une fois, ces nouveaux composants ne sont qu’une continuité des réflexions initiées avec l’Action et le Presenter et ne devraient pas représenter un défi complexe, d’autant que leur utilisation ne sera ni systématique ni réellement avantageuse en dehors des fonctionnalités présentant une certaine richesse de présentation.

Nous arrivons désormais à un point de bascule, jusqu’à présent les modifications apportées au code consistaient essentiellement à identifier et à encapsuler la logique applicative et de présentation en les isolant des interactions avec le monde extérieur : en particulier celles provenant de l’utilisateur via les points d’entrée de l’application.

Désormais, notre attention doit se porter sur les dépendances de notre Action provenant de l’autre côté de notre schéma : celles qui viennent de l’architecture de l’application.

Fondamentalement, les réflexions restent les mêmes : toujours orientées autour du découplage et de la testabilité des composants. Les éléments présents dans la couche architecture sont ceux qui font le lien avec la base de données, les API, ou encore le système de fichiers.

Ces contraintes techniques ne doivent en aucun cas influencer le fonctionnement de notre action car ce ne sont que des détails. Au contraire, il est important de réaffirmer auprès des développeurs que l’action est responsable d’orchestrer la logique métier de l’application, c’est à dire ce que l’application propose concrètement comme fonctionnalités à ses clients.

Par exemple, une application possède une action pour accueillir un nouvel utilisateur, pour fonctionner, cette action a besoin d’intermédiaires pour déléguer les détails techniques et c’est là que l’infrastructure entre en jeu : une action déclare des besoins via des interfaces que la couche d’infrastructure devra implémenter.

Cette contrainte vous amènera à créer de multiples interfaces pour répondre aux besoins spécifiques de vos actions. Chaque interface sera le fruit d’une réflexion visant à identifier précisément les dépendances fonctionnelles nécessaires au bon déroulement des traitements métier.

Vos développeurs pourraient s’étonner de voir des interfaces implémentées par une seule et unique autre classe, comme c’est le cas dans notre schéma ci-dessous : rappeler leur que les interfaces jouent un rôle architectural crucial, bien au delà de simples contrats.

💡
Ce postulat est de toute façon erroné : ces interfaces seront implémentées de multiple manière dans vos tests.

Ces interfaces constituent une indirection essentielle : elles séparent le besoin exprimé par l’action de son implémentation technique concrète. Cette indirection permet de différer les choix techniques et favorise un découplage fort entre les couches. Ainsi, l’évolution du code reste maîtrisée car les modifications techniques n’impactent pas les couches supérieures de l’application.

Le code contenu dans la couche d’infrastructure est mouvant, souvent très technique et de bas niveau, il est pourtant trivial car décoléré des enjeux métier.

Tout le monde peut écrire des appels HTTP, des requêtes en base de données, manipuler un système de fichiers … Cela n’a aucune valeur intrinsèque pour vos clients. La véritable valeur se trouve dans les couches supérieures (applicative et domaine) car ce sont elles qui incarnent ce que vous vendez réellement à vos clients.

💡
Casser le mythe du framework tout puissant c’est remettre la logique métier au coeur de votre architecture là où se trouve votre vraie valeur.

Par moments, surtout avec du code legacy, il peut être difficile d’identifier clairement ce qui relève de la logique applicative et ce qui appartient à l’infrastructure. Peut-être que le code que vous cherchez à remanier est en réalité un effet de bord d’une implémentation technique ?

Dans ce cas, et pour des raisons de pragmatisme et de simplicité, je vous conseille fortement de simplement déplacer ce code dans la couche d’infrastructure. À moins d’une refonte majeure, il sera en effet coûteux de remanier ces éléments en profondeur.

Arrivé à cette étape, la nature de vos architectures aura déjà considérablement évolué : les logiques seront bien mieux découplées et leur testabilité grandement facilitée.

Vous pourriez probablement vous arrêter là car l’essentiel aura déjà été transmis … et c’est d’ailleurs ce que je vous conseillerais de faire : laissez vos développeurs expérimenter, faire leurs propres erreurs, pour que toutes ces notions de découplage s’enracinent durablement avant d’aborder la dernière (et non des moindres) couche ... la couche domaine, qui contient notamment les entités de votre projet.

D’expérience, la couche domaine sera la plus complexe à présenter aux développeurs et la plus difficile à introduire dans un projet existant, il y aurait énormément à dire sur cette couche et sur la nature du code qu’elle contient.

Permettez vous d’aborder les choses de manière naïve : la couche domaine porte la logique métier de plus haut niveau, celle qui caractérise votre entreprise et la rend unique.

« The domain layer code encapsulates the most fundamental and high-level rules of the system »
— Robert C. Martin

Les composants qu’on y trouve contiennent l’intelligence et les règles métier réutilisables par les autres couches : ce sont les composants les plus centraux et critiques de votre projet.

La couche domaine n’a aucune connaissance des couches inférieures : insistez sur le fait que cette indépendance vis-à-vis du monde extérieur rend le code du domaine extrêmement testable. Il devient facile de créer des entités via des builders, puis de les éprouver à travers de véritables tests unitaires, sans (trop) dépendre du framework, d’une interface graphique ou d’une quelconque infrastructure.

Essayons d’illustrer ces notions à l’aide d’un exemple concret : celui d’une prise de commande dans une application de e-commerce.

Vous trouverez dans la couche application une action PasserCommande qui orchestre l’ensemble du processus et la communication avec les autres couches.

Mais la logique métier, comme la règle stipulant qu’un client ne peut commander que si son compte est actif, ou la manière de calculer les taxes selon le pays de livraison, se trouve, elle, dans la couche domaine : ces règles sont encapsulées dans des entités ou des services métier car elles sont de plus haut niveau et potentiellement réutilisables par plusieurs actions.

Cependant, tout cela reste abstrait et l’appréciation de la "hauteur" d’une couche est subjective … ce qui explique probablement pourquoi ces enjeux sont si difficiles à transmettre à vos développeurs.

Rien n’interdit non plus l’existence de couches encore plus hautes que le domaine, si des logiques stratégiques ou interdomaines le justifient, l’essentiel est ailleurs : il s’agit de toujours respecter le sens des dépendances, ainsi que l’isolation des couches.

🚨
En plus de ces différents niveaux de logique, les composants de la couche domaine devraient être à la fois stables et abstraits, conformément au Stable Abstraction Principle (SAP). Ce principe devrait également guider la construction des relations entre les couches : les couches les plus concrètes doivent dépendre des plus abstraites et jamais l’inverse. Malheureusement, je n’ai pas eu le temps d’aborder ces notions pendant cette année de refactorisation et elles ne figureront donc pas dans ce RETEX de la Clean Architecture.

Au delà de ces considérations théoriques, on peut se poser une question simple : pourquoi l’ajout d’une couche domaine est il si difficile dans un projet avec un fort legacy ?

La réponse pourrait tenir en un seul mot : le couplage.

Malgré les efforts nécessaires, l’introduction des premières couches (Presenter, Applicative et Infrastructure) se fait relativement naturellement : il s’agit avant tout de déplacer du code existant, de clarifier les intentions et de poser des frontières dans un code déjà en place.

Même les nouvelles interfaces, parfois verbeuses, obéissent à une logique utilitaire simple : elles matérialisant un besoin déjà exprimé par l’action et leur extraction améliore le découplage et la testabilité sans bouleverser l’existant.

Mais introduire une couche domaine est une histoire bien plus complexe.

Contrairement aux autres couches, le domaine ne se résume pas à une simple réorganisation du code, il ne s’agit plus seulement de déplacer des lignes ou de regrouper des préoccupations similaires : il faut identifier une logique qui, bien souvent, n’a jamais été explicitement formulée.

L’architecture, dans sa rôle fondamentale, organise les interactions entre composants et les classes à travers des règles strictes permettant d’identifier et d’isoler les logiques les unes des autres. Sans cet effort, ces logiques se retrouvent entremêlées au sein des mêmes composants, voire pire, des mêmes classes ... rendant toute réflexion architecturale laborieuse.

Dans ce contexte, introduire une couche domaine revient à extraire des idées claires d’un enchevêtrement de responsabilités souvent implicites et à reconstruire une séparation qui, en réalité, n’a jamais vraiment existé.

Le couplage, omniprésent et souvent invisible, génère une dette technique difficile à mitiger, qui freine toute tentative de refonte. Ce n’est pas tant l’ajout de la couche domaine qui est difficile, que le fait de devoir d’abord démêler ce qui n’a jamais été véritablement structuré.

ssss

La couche domaine n'a aucune connaissance des couches inférieures. Soulignez que cette indépendance vis-à-vis du monde extérieur rend le code du domaine extrêmement testable. Il devient facile de créer des entités à l’aide de builders, puis de les éprouver à travers de véritables tests unitaires, sans (trop) dépendre d’un framework, d'une interface. graphique ou d’une quelconque infrastructure.

Cette contrainte est de loin la plus fondamental : le domaine ne dépend de rien d’autre que de lui-même.

💡
Souvent les principes d'architectures se limitent à ça : décrire ce que vous ne devez pas faire ... laissant libre cours à votre imagination
« First make it works, then make it right »
— Kent Beck
First make it work, then make it right
— Kent Beck

Adopter une approche pragmatique, c’est reconnaître que cette couche doit rester la plus autonome possible. Elle constitue le cœur réutilisable de votre application, au service de multiples actions, sans jamais dépendre d’un environnement extérieur.

Autorisez-vous à présenter la couche domaine de manière très théorique, en prenant par exemple un agrégat, des entités et des Value Objects.

Soulignez également que le code présent dans la couche domaine, étant décorrélé de toute contrainte d'affichage et d'infrastructure, devient extrêmement testable de manière exhaustive. Il sera aisé de créer des entités à l'aide de builders et de les éprouver dans une série de véritables tests unitaires.

car les framework, dans leur communication, cherche

ce fut notre chemin, cela serait mentir de dire que tout fut facile et sans aller retour

qsdsqd

  • le besoin de se détacher du code
  • Tout n'a pas besoin d'être parfait
  • les differentes implementations
  • en tant que lead, attention à l'inertie des bugs, laisser les devs prendre des initatives la refacto importuniste

Accepter des solutions imparfaites

qsdqsd

qsdqsd

quand tous les problemes deviennent des clous

enthousiasme,

🧭
TL;DR : L'architecture est l’art de structurer une application autour de ses besoins métier, en séparant clairement le « quoi » du « comment » pour en faciliter l’évolution, la compréhension et la maintenance.

dans cette siutation, deux options : soit c'est pas grave et on laisse pour plus tard, on se concentre sur des choses plus essentielles - soit le developpeur accepte sans comprendre et applique (ce qui est une bonne chose) car il comprendra probablement plus tard, quand les choses commenceront à faire sens : à vous en tant que lead de trouver le bon curseur à adopter

pedagogie, bienvaillance et confiance seront les mots à adopter

Dans cette situation, concentrez-vous sur les points clés, et ne vous attardez pas sur les détails. Acceptez surtout que le code produit par vos développeurs ne soit pas exactement ce que vous aimeriez avoir.

Vos développeurs ne sont pas là pour respecter à la lettre ce que le lead de votre équipe avait en tête. La programmation est un exercice intellectuel dans lequel vos développeurs doivent pouvoir exprimer leurs gimmicks, leurs habitudes, leur sensibilité.

ne perdez pas la confiance des clients / parties prenantes expliquer investissement sur l'avenir les developpeurs sont responsables de la qualité du code, mais les devs et les parties prenantes doivent s'aligner sur la qualité à atteindre

https://substackcdn.com/image/fetch/$s_!2Jbr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fbucketeer-e05bbc84-baa3-437e-9518-adb32be77984.s3.amazonaws.com%2Fpublic%2Fimages%2F6602d994-53cd-4d36-b033-6c9272d2e725_2080x1922.jpeg

Mathieu De Gracia avatar
Mathieu De Gracia
Des fois, mon chat code à ma place 🐱

A lire

Autres articles de la même catégorie