Archi clean

« Depuis que j’ai commencé à parler de la nécessité de nettoyer notre architecture, j’ai remarqué une résistance surprenante à l’idée. Apparemment, l’idée qu’il est bon de cacher le framework, l’interface utilisateur ou la base de données du code d’application n’est pas universellement acceptée.

Une vue quelque peu dissidente, écrite par The Frustrated Architect dans son blog de coding {the} architecture est ici. Il montre une image que je vais répéter : Le point qu’il essaie de faire est que si l’interface utilisateur et la base de données sont une partie beaucoup plus grande du système que les règles commerciales, alors l’architecture du système devrait être plus orientée autour de ces éléments plus grands. Bien sûr, je ne suis pas d’accord. Peu importe la taille d’une partie du système, les autres parties doivent en être découplées.

D’autres points de vue dissidents (ou peut-être qu’un meilleur mot est « sceptiques ») ont été moins formels. Une personne m’a simplement demandé : « Avez-vous déjà réellement fait cela – dans un projet Rails« , comme si Rails était en quelque sorte spécial et changeait tellement la donne que les règles normales d’un bon design ne s’appliquent pas.

D’autres personnes ont craint que le résultat net de mes conseils ne soit beaucoup de code dupliqué, et beaucoup de copie mécanique de données d’une structure de données à une autre à travers les couches du système. Certainement, je ne veux pas non plus cela ; et rien de ce que j’ai suggéré ne conduirait inévitablement à la répétition de structures de données et à une copie excessive de champs. J’explique pourquoi ci-dessous.

Une plainte particulièrement colorée était : « Cela ressemble à un discours dogmatique, je veux voir du code. » Bien que je sympathise avec ce point de vue, les concepts ici ne sont tout simplement pas si difficiles à saisir ; et, en fait, beaucoup de code les obscurcirait plus qu’il n’aiderait.

Ce n’est pas de la science de haute volée

L’idée de base est très simple : vous séparez l’interface utilisateur des règles métier en passant des structures de données simples entre les deux. Vous ne laissez pas vos contrôleurs savoir quoi que ce soit sur les règles métier. Au lieu de cela, les contrôleurs traitent l’objet HttpRequest dans une structure de données simple, puis passent cette structure de données à un objet interacteur qui implémente le cas d’utilisation en invoquant des objets métiers. L’interacteur rassemble ensuite les données de réponse dans une autre structure de données de base et la renvoie à l’interface utilisateur. Les vues ne connaissent pas les objets métiers. Ils regardent simplement dans cette structure de données et présentent la réponse. Il y a, bien sûr, plus de détails que cela ; et ils sont bien décrits dans les références ci-dessus. Mais au fond, c’est tout ce qu’il y a à faire.

L’avantage devrait être évident. Le code d’application est complètement découplé de l’interface utilisateur. Vous pouvez tester le code d’application sans que l’interface utilisateur soit présente. Vous n’avez pas besoin de démarrer le serveur Web, ou le conteneur, ou Rails, ou l’un des autres frameworks pour exécuter vos tests. De plus, si vous n’aimez pas votre interface utilisateur actuelle, vous pouvez la modifier en la remplaçant par une autre.

Est-ce un schéma parfait ? Bien sûr que non. Un type d’interface utilisateur pourrait-il être si différent d’un autre qu’ils ne pourraient pas partager une interface commune ? Bien sûr, c’est possible. Cela signifie-t-il que ce type de découplage est un gaspillage ? Vous plaisantez ?

Ça va me ralentir.

Non, ça ne le fera pas. Pour l’amour du ciel, cela vous accélérera. Vous pourrez exécuter vos tests sans délai. Vous pourrez différer les décisions concernant l’interface utilisateur. Vous pourrez tester les règles métier sans que l’interface utilisateur soit présente. Ce genre de flexibilité et de découplage vous accélère toujours. S’il y a une chose que nous avons apprise sur le couplage au cours des cinquante dernières années, c’est que rien n’est mieux pour vous ralentir.

Nous ne devrions pas différer les décisions.

L’un des commentaires les plus véhéments que j’ai faits sur l’architecture est qu’une bonne architecture vous permet de différer des décisions critiques comme l’interface utilisateur, les frameworks, la base de données, etc. Un point soulevé par plusieurs personnes est que les clients ne veulent pas que le développement de l’interface utilisateur soit différé. Les DBA ne veulent pas que la base de données soit différée. D’une itération à l’autre, ils veulent voir tout le système fonctionner, y compris l’interface utilisateur, la base de données et les frameworks. Ils ne veulent pas qu’une itération soit consacrée uniquement aux règles métiers. En effet, de bonnes pratiques agiles exigent spécifiquement de longues tranches minces à travers toute l’architecture.

Bien sûr, je suis d’accord avec tout cela. Cependant, de longues tranches minces n’ont pas à être couplées. Une bonne architecture vous permet de différer des décisions critiques, elle ne vous oblige pas à les différer. Cependant, si vous pouvez les différer, cela signifie que vous avez beaucoup de flexibilité. Par exemple, vous pourriez créer une interface utilisateur simple intérimaire pour les premiers sprints, puis la remplacer par une interface utilisateur plus complète plus tard.

Mais cela génère plus de code.

C’est là que cela devient intéressant. Oui, il y a plus de code ; mais pas beaucoup plus. La plupart du code supplémentaire se trouve dans les structures de données de requête et de réponse qui sont passées entre l’interface utilisateur et les objets interacteurs. Cependant, ces structures de données sont généralement très simples et sont souvent simplement des structures de données génériques. Elles ne contiennent pas de logique métier. Elles ne contiennent aucune logique liée à la base de données. Elles sont juste des transporteurs de données, et à ce titre, elles sont très simples et rapides à écrire et à maintenir.

En effet, ces structures de données sont une forme de communication entre les programmeurs. Elles sont un contrat entre l’interface utilisateur et les règles métier. Comme tel, elles ont tendance à stabiliser le système. Elles rendent également les règles métier beaucoup plus faciles à comprendre et à maintenir parce qu’elles ne sont pas mélangées avec d’autres préoccupations.

Copier des données

Les gens se plaignent que ces structures de données nécessitent que des données soient copiées d’une structure à une autre ; et ils considèrent cela comme une sorte de fardeau inutile. Pourtant, nous faisons cela tout le temps. Chaque fois que nous écrivons une interface, nous faisons exactement cela. Chaque fois que nous écrivons une méthode abstraite, nous faisons exactement cela. Les données d’entrée sont déballées dans des variables locales. Les données de sortie sont emballées dans des objets de retour. Cette sorte de chose est la vie quotidienne de tout programmeur.

En outre, considérer cela comme une sorte de fardeau est une erreur. Ce genre de copie de données est une forme de communication. Il sépare les préoccupations. Il stabilise les interfaces. Il cache les détails d’implémentation. Ce sont toutes des choses que nous voulons que notre code fasse.

Duplication

Le danger de la duplication est toujours présent. Nous ne voulons pas de structures de données dupliquées. Nous ne voulons pas de champs dupliqués. Mais rien dans ce que j’ai décrit ne mène inévitablement à la duplication. En effet, si vous découvrez que vous dupliquez des structures de données ou des champs, vous faites probablement quelque chose de mal. Vous devriez probablement revoir votre design.

La duplication est un problème, mais ce n’est pas un problème spécifique à l’architecture propre. C’est un problème auquel tous les développeurs de logiciels sont confrontés, quel que soit le design ou l’architecture qu’ils utilisent. La clé pour éviter la duplication n’est pas d’abandonner la séparation des préoccupations, c’est d’être vigilant et de refondre lorsque la duplication devient apparente.

Conclusion

Les bénéfices de découpler les règles métier de l’interface utilisateur, et de découpler les deux de la base de données, sont énormes. La flexibilité, la testabilité, et la maintenabilité du système sont grandement améliorées. Les risques de couplage, de duplication, et de fardeaux excessifs sont bien gérés par les principes du design et de l’architecture que nous avons tous appris.

Ce n’est pas nouveau. Nous faisons cela depuis des décennies. Les seules choses nouvelles ici sont les frameworks qui ont essayé de nous convaincre que le couplage est une bonne chose parce qu’il est plus pratique. Ne soyez pas dupé par cette sirène. Le couplage est notre ennemi, et il a toujours été notre ennemi. Nous devons être toujours vigilants contre cela. »

Robert C. Martin, 22 Novembre 2011


Publié

dans

par

Étiquettes :

Commentaires

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *