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.

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.

Qu’est-ce que toute cette pureté a acheté ?
- Fragmentation du système de fichiers : Les répertoires sources gonflent en paysages cauchemardesques d’innombrables petits fichiers, contenant souvent une seule fonction, tragiquement solitaire. La navigation devient un exercice de spéléologie.
- Enchevêtrements de dépendances : Un réseau d’imports et d’exports si dense que tracer l’exécution nécessite un grand tableau blanc et plus de patience que la fonctionnalité n’en mérite. Les fichiers importés exactement une fois sont là, prétendant être réutilisables.
- Trahison des tests : Les tests deviennent fragiles, des sentinelles hyper-spécifiques gardant des détails d’implémentation minuscules. Changez une signature de fonction ? Regardez des dizaines de tests s’effondrer comme de l’argile ancienne. La suite de tests se transforme d’un filet de sécurité en un champ de mines.
- Disparition de la vélocité : Les modifications simples se métastasent en sagas de modifications multi-fichiers. L’intégration de nouveaux développeurs implique de leur remettre des cartes et des boussoles pendant des semaines juste pour trouver où le composant
UserProfilevit réellement cette semaine. Les avancées ralentissent jusqu’à une allure géologique sous le poids écrasant de cette « organisation ».
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 ?

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 :
- Concentrez-vous sur la cohésion, pas sur les atomes : Regroupez les choses qui changent ensemble et appartiennent ensemble conceptuellement. Un module peut gérer plusieurs aspects liés de l’authentification des utilisateurs. C’est bien. C’est probablement mieux que six fichiers séparés contenant chacun une fonction liée à l’état de connexion.
- Gardez le kin ensemble : Ne divisez pas le code lié sauf s’il y a un avantage tangible et criant – comme une véritable réutilisabilité en pratique, pas dans un futur hypothétique qui n’arrive jamais. La proximité compte pour la compréhension.
- Laissez la réalité conduire : Organisez en fonction des fonctionnalités et des flux de travail réels de votre application, pas d’un idéal abstrait de pureté fonctionnelle³. Cette structure facilite-t-elle ou rend-elle plus difficile pour quelqu’un de comprendre et de modifier
Feature X? - Pensez au Meatware : N’oubliez pas le pauvre développeur. Quelle organisation minimise le jonglage mental requis pour travailler sur le code ? Optimisez pour la compréhension humaine.
- Testez ce qui compte : Écrivez des tests qui vérifient le comportement à une limite raisonnable, pas des tests intimement soudés au câblage interne de chaque petite fonction. Visez la confiance, pas seulement le théâtre du pourcentage de couverture.
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 :
- Quelqu’un de nouveau peut-il s’y retrouver ?
- Pouvons-nous changer
Xsans casserYsans rapport ? - Ce test me dit-il réellement si la fonctionnalité fonctionne ?
- Livrons-nous de la valeur, ou ne faisons-nous que réorganiser des dossiers ?
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.