L'architecture comme fardeau

Au cours de ma carrière, j'ai travaillé sur divers projets hérités, chacun souffrant de divers défauts.


Bien sûr, souvent le principal problème était la mauvaise qualité du logiciel (manque de tests unitaires, refus d'utiliser les principes du code propre ...), mais il y avait aussi des difficultés, dont la source était les décisions architecturales prises au début du projet ou même lors de la création du système d'entreprise. À mon avis, cette classe de problèmes est la cause de la plus grande douleur pour de nombreux projets.


Essentiellement, l'amélioration du code est assez simple, surtout maintenant que le mouvement de l'artisanat logiciel promeut les bonnes pratiques d'équipe. Cependant, changer les parties centrales des systèmes, les restrictions imposées au tout début de leur cycle de vie, est une tâche extrêmement difficile.


Je vais vous parler de plusieurs types de solutions architecturales que j'ai rencontrées, qui peuvent devenir un véritable fardeau pour les équipes impliquées dans la prise en charge de tels systèmes.



Toute votre entreprise partage votre base de données


C'est peut-être l'un des problèmes les plus courants que j'ai vus. Lorsque plusieurs applications doivent utiliser des données partagées, pourquoi ne leur donnons-nous pas simplement un accès partagé à une base de données partagée? Après tout, la duplication est considérée comme mauvaise dans le développement de logiciels, non? Eh bien, ce n'est pas toujours vrai, surtout en ce qui concerne la base de données. Venkat Subramaniam l'a exprimé ainsi: «La base de données est comme une brosse à dents: ne laissez personne l'utiliser.» Qu'y a-t-il de si mal à partager une base de données? En fait, beaucoup ...


La première chose qui me vient à l'esprit est le couplage du modèle de données. Imaginez que deux applications, A et B, traitent des données sur les voitures. L'annexe A est utilisée par l'équipe responsable des travaux de réparation, et donc ils ont besoin de stocker beaucoup d'informations techniques: sur la mécanique, les pannes, l'historique des interventions dans la voiture ... L'annexe B est utilisée pour définir les tâches de l'équipe technique, de sorte qu'elle n'a besoin que d'informations de base sur la voiture, suffisantes pour son identification. Dans ce cas, l'utilisation de la même structure de données pour les deux programmes n'a pas de sens: ils utilisent des données différentes, chacun doit donc utiliser sa propre structure de données. Ceci est rendu plus facile car la voiture est facile à identifier, il n'est donc pas nécessaire d'avoir une référence générale.


Le deuxième problème est également dû à ce maillage du modèle de données. Imaginez que l'application B souhaite renommer l'identifiant de la voiture - donnez-lui un nom plus logique en termes de domaine. Dans ce cas, l'application A devra également être mise à jour - le nom de la colonne a changé ... Par conséquent, afin de ne pas déranger l'équipe de l'application A, les développeurs B commenceront à dupliquer les informations dans une autre colonne, car ils ne peuvent pas modifier une colonne existante ... Bien sûr, les développeurs A diront que ils prévoient de changer le nom de la colonne à l'avenir afin de ne pas stocker les mêmes informations dans deux colonnes, mais nous le savons tous: très probablement, cela ne se fera jamais ...


Tout devient encore plus dégoûtant lorsque les applications non seulement lisent les données d'une seule source, mais les changent également! Qui est le propriétaire des données dans ce cas? À qui faire confiance? Comment l'intégrité des données peut-elle être garantie? C'est difficile même lorsque les mêmes données sont modifiées par différentes parties de la même application, mais lorsque plusieurs applications différentes le font, le problème devient beaucoup plus grave ...


Le dernier cas que j'ai vu: deux applications qui partagent la même structure de données pour stocker des informations sur deux objets métier, relativement similaires, mais en même temps suffisamment différentes pour compliquer sérieusement la compréhension de l'application à laquelle les données se réfèrent. Les deux applications ont utilisé le même tableau pour modéliser les exécutions sur le marché financier, mais avec différents niveaux d'agrégation. Rien n'indiquait que la table contenait des données de deux types, nous avons donc dû regarder une autre table (appartenant à la deuxième application) pour déterminer les lignes générées par chacun des programmes ... Chaque nouveau développeur qui devait travailler avec cette table est venu inévitablement sur le même rake que tous ses prédécesseurs, et a utilisé des données incorrectes (vulnérables), avec tous les risques qui en découlent pour l'entreprise.


Votre système est lié au logiciel utilisé dans l'entreprise


Toutes les entreprises ne peuvent pas développer des logiciels qui répondent à tous les besoins de leur entreprise. En fait, dans de nombreux cas, ce serait une invention du vélo, car les besoins de nombreuses entreprises sont les mêmes, et il est facile de trouver sur le marché des logiciels qui possèdent déjà les fonctionnalités nécessaires.


En général, il est souvent moins cher d'acheter un produit que de le créer. Mais, bien sûr, le produit que vous venez d'acheter ne fonctionne pas immédiatement de manière transparente avec le logiciel que vous utilisez déjà, vous devez donc créer un pont entre les deux applications (dans la plupart des cas, propriétaires). Vous développerez sûrement vos propres outils pour des parties spécifiques de votre entreprise, et tant que ce logiciel coûteux que vous avez déjà acheté a un modèle approprié, il vous suffit d'utiliser sa base de données et d'ajouter vos données aux tableaux de cette base de données ...


Plusieurs années s'écoulent, une douzaine de développeurs ou d'équipes effectuent ces actions encore et encore, et vous êtes alors dans une impasse: vous ne pouvez tout simplement pas utiliser d'autres logiciels si le développeur du logiciel que vous avez acheté le ferme, ou arrête de prendre en charge le produit, ou si un nouveau logiciel s'avère être mieux adapté à vos besoins. Dans certains cas, vous pouvez même avoir des dépendances techniques sur des logiciels externes. Si l'auteur de la solution logicielle que vous utilisez souhaite que vous utilisiez la version du langage / framework / autre chose dont il a besoin, cela signifie que l'architecture de votre système ne vous appartient pas. Si vous souhaitez vendre une nouvelle version pour fournir une fonction dont vous avez absolument besoin, mais que cette version est sujette à une modification des exigences techniques, vous serez obligé de mettre à niveau votre pile technologique pour répondre aux recommandations des autres. Je sais ce que ça fait, et vous ne voudriez pas qu'une telle migration forcée soit fréquente ...


J'ai travaillé sur un projet où les développeurs du produit que nous utilisions ne voulaient pas ajouter de nouvelles fonctionnalités pour tous nos clients, car il leur était trop difficile de maintenir des changements compétitifs et plusieurs versions actuelles (chaque client avait sa propre version avec des fonctions nécessaires uniquement pour lui). Ils ont donc décidé de nous vendre le SDK afin que nous puissions implémenter nos propres fonctionnalités. Naturellement, ils n'ont pas fourni suffisamment de documentation sur la façon de procéder, et, de plus, nous avons été obligés d'utiliser leurs entités commerciales, que nous avons dû décompiler pour comprendre leur structure - parce que nous n'avions ni code source, ni documentation ... la fonctionnalité la plus simple a pris plusieurs jours, et il était presque impossible de la tester, car tout était trop compliqué, et exigeait même la connaissance d'un langage de script que personne dans l'équipe avec une pile technologique déjà complexe ne connaissait ...


Maillage solide entre plusieurs applications


Rappelez-vous le début des années 2000: à quel point il était agréable d'utiliser Enterprise Java Beans (EJB) pour gérer les appels à distance entre les applications de votre système d'information. À l'époque, cela aurait pu sembler une bonne idée. Le partage de votre code avec d'autres équipes pour éviter la duplication semble également bien. Oui, toutes les équipes ont été obligées de déployer leurs applications en même temps pour s'assurer que les dépendances binaires ne se cassaient pas, mais c'était des soirées amusantes - manger de la pizza avec des collègues en attendant la livraison de l'application pendant 2 heures, non?


Eh bien, en fait, ce n'était pas si amusant. Et l'impossibilité de refactoriser une classe distincte dans votre propre code - simplement parce que quelqu'un d'autre dans l'entreprise a aimé votre code et a décidé de l'utiliser dans leur application non testée - est toujours un plaisir.


Une fois que vous vous rendez compte à quel point ces premières décisions sont confuses, l'effort requis pour séparer votre application du reste du monde est énorme. Vous voyez, au sens littéral, il faudra des années pour découper votre projet en divers composants afin que d'autres applications ne puissent plus utiliser le cœur de votre domaine, votre client ou le mécanisme de mise en cache; supprimer tous les appels à des classes externes qui conduisent à une forte liaison avec d'autres projets; pour remplacer tous les appels EJB par des API REST ... Cependant, pour tous ces efforts, chaque employé associé au projet sera plus que récompensé: le développement et les tests seront simplifiés, le processus de livraison s'accélérera, puisqu'il n'y a plus besoin de synchroniser votre travail avec quelqu'un d'autre ; les concepts de votre propre code seront mieux séparés; la gestion des dépendances sera simplifiée, les problèmes de dépendances transitives disparaîtront lorsque vous importerez un tas de dépendances d'autres applications dans votre chemin de classe ... Tous ces changements coûteux ne feront que sauver la vie de l'équipe et ils pourraient être beaucoup plus faciles à implémenter si vous les faisiez à l'aube du projet!


Vous construisez votre projet sur la base du projet de quelqu'un d'autre


Vous ne rencontrerez probablement pas ce problème, mais il peut toujours se produire, et si cela se produit, alors c'est le pire des cas, car il combine plusieurs des problèmes discutés précédemment. En vérité, je suis tombé sur un semblable dans l'un des premiers projets de ma carrière professionnelle.


Quand j'ai rejoint le projet, on m'a dit que le système d'entreprise était complètement réécrit et que le travail sur le projet n'avait commencé que récemment, il y a 2 mois. Imaginez ma surprise quand j'ai vu une application Web complexe avec un module d'administration à part entière, déjà implémenté des fonctionnalités commerciales complexes et un cadre développé pour écrire d'autres modules. Bientôt, j'ai découvert que la plupart de tout cela n'était pas écrit par mon équipe: afin de ne pas repartir à zéro, il a été décidé de réutiliser le framework développé par une autre entreprise de notre groupe. Le problème était que ce cadre n'était pas isolé du projet pour lequel il avait été développé. Notre équipe a donc simplement reçu une archive avec tout le code source du projet d'une autre entreprise, y compris leur logique métier, qui n'avait rien à voir avec notre propre entreprise. Pour aggraver les choses, nous en avons également hérité le schéma de la base de données et les données elles-mêmes ...


Il n'était pas facile pour un nouveau venu dans l'équipe de comprendre quel code se rapporte au framework, qui se réfère à notre projet, et qui se réfère aux affaires d'une autre entreprise. L'équipe a voulu éclaircir ce gâchis, mais plusieurs tentatives pour ce faire ont abouti à de graves erreurs de régression en raison de dépendances entre les parties du code (le langage ne tourne pas pour l'appeler modules car il n'y avait qu'un seul module!), Et, bien sûr, il n'y a pas de tests automatisés là-bas était. De plus, nous avons dû abandonner l'idée d'utiliser un autre serveur d'applications, car il avait un code spécifique utilisé par une autre société dans tout le système, ce qui a rendu une telle migration trop coûteuse pour notre petite équipe.


À un moment donné, nous voulions ajouter de belles fonctionnalités au cadre, mais on nous a dit que cela avait déjà été fait dans une autre société. On nous a donc demandé de fusionner notre version actuelle avec la version actuelle du code d'une autre société ... L'équipe a réussi à éviter ce cauchemar en redirigeant simplement (cerise sur le gâteau) certains des commits associés à la nouvelle fonction, mais c'était toujours trop compliqué et sophistiqué par rapport à cela ce dont nous avions besoin ...


Nous avons réussi à terminer ce projet, mais sa qualité a été une vraie douleur. Au moins 40% du code et du contenu de la base de données étaient des ballasts inutilisés, et la suppression de ce code mort n'était pas une priorité. J'espère que l'équipe a enfin eu l'opportunité de séparer son propre code - je ne sais pas, j'ai quitté l'équipe avant que cela n'arrive!


Toute votre logique métier est stockée dans un système de gestion de règles


Mettre une partie de votre logique métier dans un système de gestion des règles est une pratique courante. Cela, par exemple, est utile si certaines de vos règles métier doivent être mises à jour fréquemment et que le processus de livraison de votre application monolithique nécessite une longue phase de test avant de pouvoir vérifier la version candidate, ce qui rend impossible la configuration de certaines de vos «volatiles» "Règles. Bien que je préfère une approche où toutes les règles du domaine sont dans le code source, je peux comprendre que dans certaines situations, un système de gestion des règles peut être utile.


Cependant, je suis tombé sur une application où presque TOUTES les logiques métier étaient dans le système de gestion des règles, et parfois les règles étaient générées à partir d'un fichier Excel! De plus, les règles n'étaient pas censées être modifiées très souvent, car le projet était, dans l'ensemble, un simple paquet ETL . Le projet Java, sur lequel tout cela était basé, consistait uniquement en des détails techniques sur le cadre de traitement par lots et en lecture-écriture pure à partir des systèmes source et cible, sans aucun lien avec le sujet.


En conséquence, toutes les règles ont été écrites dans un langage spécial que personne ne connaissait vraiment bien dans l'équipe, qui était difficile à écrire (nos IDE ne le supportaient pas) et qui était pratiquement impossible à déboguer et à tester. Lorsqu'une nouvelle règle ou une modification d'une règle existante était demandée, la plupart des développeurs des équipes copiaient simplement la règle existante, ce qui conduisait à des fichiers complètement identiques, à l'exception d'une modification spécifique (souvent la seule telle modification était le champ auquel la règle s'appliquait).


Si cela semble déjà être un problème, alors voici autre chose: il n'y avait absolument aucun indice sur son objectif dans aucune règle. Les règles ont été nommées comme Rule1, Rule2, et ainsi de suite, avec un total de plus de 100! Et fondamentalement, chaque règle consistait en des vérifications et en l'affectation de valeurs codées en dur sans aucun terme de domaine. Même le nom du projet n'a pas clarifié le but de l'ETL dans son ensemble.


Conclusion


Comme l'oncle Bob l'a expliqué dans son livre «Architecture propre», en pensant à l'architecture de son projet, certaines décisions devraient être reportées jusqu'à ce que nous ayons vraiment besoin de faire un choix, sans lequel nous ne pouvons pas continuer à ajouter de la valeur à notre produit (comme le choix d'une base de données par exemple). D'autres décisions doivent être prises très tôt - n'attendez pas que les choses tournent mal. Heureusement, ce type de décisions critiques est facile à identifier car elles sont ce qu'on peut appeler «l'architecture avec une âme»: quand vous pensez à de telles idées, vous ne voyez rien de bon en elles - juste un problème qui reviendra tôt ou tard et vous hanter. Malheureusement, lorsque vous travaillez avec des projets hérités, ce type de fardeau est souvent enfoui profondément dans le code, ce qui rend son élimination très coûteuse.


Mais nous ne devons pas avoir peur. Oui, nettoyer le gâchis qui s'est accumulé au fil des années et même des décennies n'est pas une tâche facile, mais en tant que développeurs de logiciels professionnels, nous ne pouvons tout simplement pas permettre à de tels problèmes de continuer à pourrir et à tuer la motivation des développeurs, la confiance des clients et notre capacité à en bénéficier, intégrés dans notre produit.


Bien sûr, chaque type de fardeau architectural que j'ai décrit peut être éliminé de diverses manières - il n'y a pas de solution miracle pour résoudre l'un de ces problèmes. Cependant, je suis sûr que n'importe quelle équipe peut trouver quelque chose pour enfin se débarrasser de ce fardeau. Alors affrontons nos problèmes ensemble et commençons à mettre les choses en ordre!

Source: https://habr.com/ru/post/fr427591/


All Articles