DanLevy.net

Méfiez-vous des gens à objectif unique

Si pur que ça en fait mal

Le Single Responsibility Principle (Principe de Responsabilité Unique) est l’une de ces idées qui semblent si sensées qu’elles peuvent passer inaperçues auprès de votre jugement.

Faire une seule chose. Bien la faire. Garder les modules focalisés. Donner au code une raison de changer. De bons conseils.

Ensuite, quelqu’un transforme ce conseil en mètre étalon et commence à déclarer que toute fonction de plus de cinq lignes est une odeur de code.

Le problème n’est pas le SRP. Le problème est de traiter le « petit » comme un substitut au « cohérent ».

À ce stade, vous avez rencontré les gens à objectif unique : des développeurs qui n’ont pas tout à fait tort sur la modularité, exactement, mais qui ont confondu les limites utiles avec la fragmentation maximale.

Violence en architecture logicielle
Des composants, des composants partout

I. L’idée utile en dessous

Ajouter une seule case à cocher à un formulaire ne devrait idéalement affecter qu’un seul fichier. Pas 8 fichiers répartis dans 5 répertoires… Je vous regarde, React/Redux.

Lorsque le SRP est appliqué avec discernement, il aide. Les unités de code concentrées sur une seule tâche conceptuelle sont plus faciles à comprendre. Les tests peuvent cibler le comportement à une limite raisonnable. Des modules clairs facilitent la modification d’une partie du système sans entraîner le reste de l’application dans la pièce.

Même les exemples classiques d’Unix sont plus pragmatiques que le slogan ne le laisse entendre. ls liste les fichiers, oui, mais il coordonne également des appels comme opendir, readdir, closedir et stat. L’unité utile n’est pas la plus petite opération possible. L’unité utile est la plus petite chose cohérente qui résout la tâche.

La philosophie Unix originale portait sur la composition et la simplicité, pas sur la réduction de tout à une seule fonction ou un seul fichier.

Cette distinction est importante. « Une seule responsabilité » n’est pas la même chose qu’« une seule ligne de comportement ».

II. Sur-abstraction : quand la simplicité vire au chaos

Notre architecte insiste sur le fait que toute fonction de plus de 5 lignes est une « odeur de code ». Notre base de code sent maintenant vaguement le désespoir clueless.

Le mode d’échec est facile à repérer après qu’il a déjà rendu votre semaine pire.

La base de code a plus de fichiers, mais moins de forme. Chaque assistant a un assistant. Chaque concept a été divisé en dossiers nommés d’après des rôles techniques au lieu du sens métier. Ajouter une case à cocher nécessite de toucher un composant, un hook, un sélecteur, une action, un réducteur, une constante, un fixture de test et un export en baril qui existe surtout pour empêcher les chemins d’importation d’avoir l’air coupables.

Pas d’échappatoire à ce modèle de travail infini
Des composants, des composants partout

Qu’est-ce que toute cette pureté a acheté ?

J’ai fixé l’abysse de bases de code où une fonctionnalité simple de 100 lignes a été disséquée à travers plus de 15 fichiers, chacun étant un petit ange « pur » contenant peut-être une ou deux fonctions. Le rayon d’explosion cognitif d’essayer de garder ce désordre dans votre tête a complètement annulé tout gain théorique de la séparation. Ce n’était pas plus simple ; c’était juste dispersé.

III. Le coût de la perfection : impact sur les développeurs

Nous passons plus de temps à débattre de la structure des fichiers et des conventions de nommage qu’à livrer réellement des fonctionnalités. Est-ce de l’Agile ?

Tellement désordonné que ça frôle l’art
Tellement désordonné que ça frôle l'art

Cette fragmentation pathologique n’est pas seulement un problème esthétique. Elle change la façon dont les développeurs consacrent leur attention :

La perte de productivité : Oubliez la dette technique ; c’est une dette organisationnelle accumulée par un nesting obsessionnel-compulsif de couches d’abstraction. Chaque ajustement mineur devient une fouille archéologique à travers des couches d’abstraction. Le temps disparaît dans le trou noir de cd .. et grep.

La taxe de test : Au lieu de fournir de la confiance, la suite de tests devient une source de friction. Des heures fondent en réparant des tests cassés par des refactorisations triviales, des tests qui étaient trop étroitement couplés aux détails microscopiques qu’ils étaient censés vérifier.

La charge cognitive : Il y a une limite stricte au nombre d’informations déconnectées qu’un cerveau humain peut jongler. Forcer les développeurs à reconstituer le flux du programme à partir d’une douzaine de fichiers dispersés entrave activement la compréhension et rend les modifications confiantes plus difficiles.

IV. Embrasser le pragmatisme : une alternative pratique

J’ai suggéré de mettre deux fonctions liées dans le même fichier. La pièce a réagi comme si j’avais proposé de supprimer la mise en scène. — Un lecteur puriste en convalescence

La porte de sortie n’est pas d’abandonner le SRP. La réponse est de l’appliquer au bon niveau de signification.

Voici à quoi cela ressemble en pratique :

L’objectif n’est pas la perfection théorique digne d’une thèse de doctorat ; c’est de créer du code que vos collègues (et votre futur vous) peuvent naviguer, comprendre et modifier sans avoir envie de mettre le feu au bâtiment.

Parfois, cela signifie qu’un fichier fait 200 lignes au lieu de 50. Parfois, une fonction gère la récupération des données et les transforme légèrement. Parfois, une classe a deux responsabilités si étroitement couplées qu’elles devraient vivre ensemble. Si cela rend le système plus facile à travailler globalement, c’est probablement la bonne décision.

Restez résolument concentré sur les questions pratiques :

V. Conclusion : Favoriser un code cohérent et maintenable

Le Principe de Responsabilité Unique est un outil utile. Ce n’est pas un mandat pour pulvériser votre base de code en poussière atomique. Comme tout outil, sa valeur dépend du jugement de la personne qui l’utilise.

Alors, lorsque vous rencontrez les gens à objectif unique, prêts à faire la guerre à toute fonction osant dépasser trois lignes, prenez une respiration. Rappelez-vous de la case à cocher en 12 fichiers.

Notre travail n’est pas de construire des flocons de neige fonctionnels théoriquement immaculés. Notre travail est de construire des logiciels qui fonctionnent, résolvent des problèmes et ne punissent pas la prochaine personne qui doit les toucher.

Restez pragmatique. Concentrez-vous sur les résultats. Ne laissez pas la poursuite de la pureté parfaite devenir l’ennemi du code maintenable. Votre santé mentale, et la vélocité de votre équipe, en dépendent.

¹ L’ironie étant qu’atteindre un véritable objectif unique aux niveaux les plus bas nécessite une immense complexité cachée juste sous la surface.

² Nous parlons ici de pureté conceptuelle : l’idée qu’une fonction ne devrait faire qu’« une seule chose » logiquement. Ne confondez pas cela avec le concept de « fonction pure » de la programmation fonctionnelle sans effets secondaires, qui est une idée différente, bien que parfois liée.