Nous l'avons tous fait, nous avons étiqueté du code (souvent des éléments dont nous avons hérité) comme "hérité"? Mais il est toujours utilisé dans les systèmes de production - est-ce vraiment un héritage? Et qu'est-ce qui en fait un héritage? Faut-il éviter cet étiquetage injustifié d'un code fonctionnant parfaitement; où l'étiquetage est une pure convivialité qui nous permet de pousser à travers de nouvelles choses et de garder la haute direction Nice et heureux?
En regardant les réponses, je vois quatre thèmes généraux. Voici comme je vois la ventilation:
Je suis plutôt partial envers résumé de Wikipedia moi-même:
Un système hérité est une ancienne méthode, technologie, système informatique ou programme d'application qui continue d'être utilisé, généralement parce qu'il fonctionne toujours pour les besoins des utilisateurs, même si une technologie plus récente ou des méthodes plus efficaces d'exécution d'une tâche sont maintenant disponibles.
Beaucoup de ce que les autres décrivent dans leurs réponses sont raisons pourquoi le code devient "hérité". Mais la question essentielle elle-même est la suivante:
Mais il est toujours utilisé dans les systèmes de production - est-ce vraiment un héritage? Et qu'est-ce qui en fait un héritage?
Le fait qu'il soit toujours utilisé en production est précisément ce qui en fait un héritage . Si le code ne fonctionne pas correctement ou n'est plus utilisé en production, alors ce code est "cassé" ou "retiré", respectivement. Legacy signifie qu'il est toujours utilisé et fonctionne bien, mais intègre des conceptions ou des techniques qui ne sont plus couramment utilisées.
Tout code ou système que vous (a) souhaitez mettre à niveau/mettre à jour, mais ne pouvez pas, ou (b) êtes toujours en cours de mise à niveau, est un système hérité. Cela ne signifie pas refactoring ou nettoyage de code général, cela signifie significatif modifications de la conception, éventuellement en utilisant un nouveau framework ou même une nouvelle plateforme.
Il existe un certain nombre de raisons pour lesquelles les systèmes ou le code pourraient devenir hérités:
Manque d'entretien régulier ou pourriture du logiciel . De toute évidence, si l'application n'est pas maintenue régulièrement, elle ne suivra pas les changements majeurs dans le monde du logiciel. Cela peut être dû à une simple négligence ou à des choix délibérés en fonction des priorités commerciales ou des contraintes budgétaires.
Manque de tests. ne autre réponse fait référence à la revendication hyperbolique d'un auteur populaire de tout code non couvert par les tests étant du code hérité. Ce n'est vraiment pas une définition précise mais c'est c'est une cause racine possible; sans bons tests (automatisés ou manuels), les développeurs deviennent timides et ont peur de faire des changements majeurs car ils craignent de casser quelque chose, menant ainsi la "pourriture logicielle" ci-dessus.
Le verrouillage des révolutions, un facteur souvent négligé qui est particulièrement insidieux dans les projets utilisant de grandes bibliothèques ou frameworks open-source (même si je l'ai vu avec des outils commerciaux également). Souvent, il y aura une personnalisation majeure du framework/bibliothèque, rendant une mise à niveau prohibitive ou coûteuse. Ainsi, le système devient hérité car il s'exécute sur une plate-forme plus ancienne (et éventuellement plus prise en charge).
Le code source n'est plus disponible, ce qui signifie que le système ne peut être ajouté qu'à jamais changé. Étant donné que ces systèmes doivent être réécrits afin d'être mis à niveau - par opposition à une révision incrémentielle/itérative - de nombreuses entreprises ne s'en préoccuperont pas.
Tout ce qui ralentit ou arrête les mises à jour d'une base de code peut faire en sorte que cette base de code devienne héritée.
Maintenant, la question séparée, non déclarée mais implicite est, qu'est-ce qui ne va pas avec le code hérité? Il est souvent utilisé comme terme péjoratif, d'où la question:
Faut-il éviter cet étiquetage injustifié d'un code fonctionnant parfaitement?
Et la réponse est non, nous ne devrions pas; l'étiquetage est garanti et le terme lui-même implique clairement un code de fonctionnement. Le point n'est pas ça c'est la fonction, mais comment ça fonctionne.
Dans certains cas, il n'y a rien de mal avec le code hérité. Ce n'est pas un mauvais mot. Les codes/systèmes hérités ne sont pas mauvais. Ils viennent de ramasser de la poussière - parfois un peu, parfois beaucoup.
Legacy devient obsolète lorsque le système ne peut plus répondre (à la totalité) aux besoins du client. Ça label est celui que nous devons faire attention. Sinon, c'est simplement une équation coûts/avantages; si le coût de la mise à niveau serait inférieur au coût de ses avantages (y compris les coûts de maintenance futurs inférieurs), alors mettez à niveau, sinon, laissez-le tranquille. Pas besoin de cracher le mot "héritage" sur le même ton que vous réservez normalement pour "contrôle fiscal". C'est une situation parfaitement OK.
Habituellement, cela signifie qu'il est écrit dans une langue ou basé sur un système dans lequel vous ne faites généralement pas de nouveau développement.
Par exemple, la plupart des endroits n'écrivent pas de nouveaux programmes en Cobol. Cependant, une grande partie de leur entreprise peut fonctionner sur des applications écrites en Cobol. Par conséquent, ces applications sont étiquetées "Legacy".
Legacy signifie tout code que vous préférez remplacer plutôt que travailler. Étant donné l'attitude de la plupart des programmeurs envers la plupart des codes existants, cela inclut généralement presque tout sauf ce que vous écrivez activement en ce moment (et sur un grand projet où vous devez coder sur une conception figée, même ce que vous écrivez sur le moment peut également être inclus).
Le dernier point mène à deux autres points qui, je pense, sont souvent vrais.
Premièrement, le code est souvent conservé comme héritage, même s'il ne devrait vraiment pas l'être. Les gestionnaires de niveau supérieur supposent généralement que la mise en œuvre d'un système coûtera autant ou plus que la mise en œuvre initiale, ce qui est rarement vrai.
Deuxièmement, les tests unitaires sont une épée à double tranchant. Ils rendent trop facile de penser que les changements localisés dans l'implémentation sont ce qui compte vraiment. Pour apporter des améliorations significatives dans un système plus vaste, vous devez souvent (généralement?) Modifier suffisamment la conception globale pour que la plupart (sinon la plupart) des tests unitaires deviennent inutiles. Malheureusement, la présence de tests unitaires et l'attitude qu'ils engendrent peuvent rendre trop facile d'ignorer les changements qui sont vraiment nécessaires.
Peut-être qu'un exemple de cela aiderait: supposons qu'un programme possède une bibliothèque UI avec de grands tests unitaires et plusieurs programmes qui utilisent cette bibliothèque. Quelqu'un dans la haute direction devient convaincu que le "Web activé" est important (et, juste pour les besoins de l'argument, supposons que dans ce cas, il a en fait raison). Après un examen attentif, les cadres intermédiaires constatent que leurs tests unitaires actuels sont suffisants pour qu'ils puissent passer d'une interface utilisateur affichée via la capacité de fenêtrage du système d'exploitation local à un affichage à distance via HTML/CSS/AJAX, tout en conservant toute la validation d'entrée d'origine.
C'est super, non? Il montre à quel point les tests unitaires peuvent être utiles. Nous avons échangé toute l'implémentation de l'ensemble de l'interface utilisateur, mais nous nous sommes assurés que l'apparence, la convivialité et les fonctionnalités restent pratiquement cohérentes, et que toutes les entrées utilisateur sont validées pour garantir l'intégrité des données. Les tests unitaires ont sauvé la journée!
Ou pas! Cette grande bibliothèque d'interface utilisateur, hautement flexible et soigneusement testée, a aidé toutes les personnes impliquées à se rendre compte que pour ce programme sur son marché avec ses utilisateurs, une interface utilisateur Web n'est pas du tout la bonne chose à travailler. Ce dont nous avons vraiment besoin, c'est d'un service Web avec une interface RESTful et une interface utilisateur absolue sans propre.
Maintenant, il est certainement vrai que les tests unitaires ne suppriment pas en soi la capacité des gens à comprendre leur marché ou à réaliser que c'est vraiment nécessaire. Dans le même temps, la vieille ligne sur les marteaux et les clous saute pratiquement à l'esprit. Cela peut être encore pire lorsque vous avez non seulement un marteau , mais aussi un lot d'expérience avec ce marteau, et sachez que c'est vraiment un marteau de haute qualité qui fonctionne incroyablement bien dans de nombreuses situations différentes. Le fait même qu'il soit si bon dans tant de choses dans tant de situations rend encore plus difficile de reconnaître quand ce n'est pas le bon outil pour le travail à accomplir.
Le code hérité est généralement orphelin d'une manière ou d'une autre. Le développeur principal, le seul qui l'a compris, a été heurté par un bus et ses notes ont été écrites dans son dialecte ukrainien natif, qui est maintenant une langue morte. Ou, alternativement, tout ce qui est écrit en Visual Basic 6. .
Je travaille tout le temps sur du code hérité. Je dirais que les caractéristiques sont:
S'il n'a pas ces caractéristiques, ce n'est probablement pas un héritage. Si vous n'aimez pas les scripts Perl de vos prédécesseurs, je sympathise, mais je ne pense pas que ce soit un héritage. J'ai récemment modernisé un script Perl de 15 ans qui était lié à une base de données obsolète Sybase . C'était un gâteau comparé à apporter le moindre changement à notre système de comptabilité COBOL .
Dans son livre, Travailler efficacement avec le code hérité, Michael Feathers définit le code hérité comme un code qui n'est pas couvert par des tests unitaires. C'est une définition avec laquelle je suis d'accord. Je vois également le code hérité comme ancien, mais toujours utilisable.
Techniquement, l'héritage est tout code prêt à être écrit. Donc, dès qu'il est en production, c'est un héritage. Parce qu'il y a déjà de la valeur, vous ne pouvez pas simplement la jeter ... Vous devez y faire face.
C'est "avant votre temps" mais "toujours votre mal de tête".
Le code hérité est un code qui ne reste que dans la base de code car beaucoup de choses cesseraient de fonctionner autrement. En d'autres termes: sa seule raison d'être est la compatibilité descendante.
Vous préférez le changer ou même le jeter, mais vous ne pouvez pas, car vous casserez tout le code qui en dépend (ce qui pourrait être du code que vous ne pouvez pas adapter en conséquence). Par conséquent, vous devez le conserver (et parfois même le maintenir), mais vous souhaitez que tout nouveau code ne soit pas écrit contre lui.
Un exemple sont les méthodes obsolètes de l'API d'une bibliothèque. Ils sont toujours là, de sorte que si quiconque met à jour la bibliothèque peut toujours construire son projet, mais ils sont marqués comme obsolètes et votre compilateur devrait vous donner un avertissement.
Un autre exemple est toutes ces astuces étranges que Microsoft fait pour exécuter des programmes qui ont été écrits pour des versions de leur système d'exploitation qu'ils ont complètement dépréciées. Le summum de cet être:
J'en ai entendu parler pour la première fois par l'un des développeurs du jeu à succès SimCity, qui m'a dit qu'il y avait un bug critique dans son application: il utilisait la mémoire juste après l'avoir libérée, un non-non majeur qui fonctionnait bien sous DOS mais ne fonctionnerait pas sous Windows où la mémoire libérée est susceptible d'être récupérée immédiatement par une autre application en cours d'exécution. Les testeurs de l'équipe Windows examinaient diverses applications populaires, les testant pour s'assurer qu'ils fonctionnaient bien, mais SimCity continuait de planter. Ils l'ont signalé aux développeurs Windows, qui ont désassemblé SimCity, l'ont exploré dans un débogueur, ont trouvé le bogue et ont ajouté un code spécial qui vérifiait si SimCity était en cours d'exécution et, dans l'affirmative, exécutait l'allocateur de mémoire dans un mode spécial dans lequel vous pourrait encore utiliser la mémoire après l'avoir libérée.
- Joel sur le logiciel
L'héritage implique l'héritage. Le code hérité est simplement du code hérité du passé. C'est du code hérité même si vous l'avez écrit vous-même auparavant!
Toutes les autres considérations découlent essentiellement du fait que vous ne l'avez pas écrit spécifiquement pour votre projet actuel. Ce n'est pas nécessairement une mauvaise chose en soi.
Mon opinion est que ce qui est considéré comme du code hérité dépend de plusieurs choses, et le tag "hérité" est probablement spécifique à l'organisation.
Si le matériel/le système d'exploitation sur lequel il fonctionne est ancien et a été interrompu par le fournisseur - frappe 1.
S'il est plus difficile d'essayer de le réparer que de le réécrire, pour quelque raison que ce soit,
faire cela
Grève 2.
Une fusion de plusieurs organisations en une seule - Strike 3 - une seule partie va probablement être marquée comme héritage.
Existe-t-il une alternative meilleure et moins chère vendue en tant qu'application et/ou service tiers - grève 4.
L'organisation ressemble-t-elle à un hôpital ou à un district scolaire où la cohérence est valorisée par rapport aux nouvelles technologies en ce qui concerne les opérations quotidiennes? Il faudra plus de temps pour qu'une application soit considérée comme héritée par rapport à la même application dans une organisation commerciale/compétitive.
Si l'entreprise est une petite entreprise de développement qui continue d'améliorer/de soutenir l'application pour faire ce dont les clients ont besoin, est-elle considérée comme un code hérité, ou simplement comme un "ancien" code. Je connais une société nommée Mc2Ok - ils ont développé le logiciel sur ce qui semble avoir été Windows 3.1 et ne font que continuer. Il a toujours beaucoup l'apparence de Windows 3.1, mais ils y ont également ajouté une interface Web. Il s'agit d'une société de développement composée de deux hommes (je suppose), et je dirais que lorsqu'ils cesseront de travailler dessus, cela sera considéré comme hérité et qu'il sera temps de migrer un an ou deux après si vous l'utilisez. Mais cela pourrait être encore 10 ans ou plus.
Parfois, lorsque la gestion change, elle peut changer par vagues qui ont de nombreux effets de ruissellement ... En fonction de l'influence de la nouvelle gestion, elle peut rendre de nombreuses applications héritées qui pourraient autrement être très bien.
Je pense que chaque organisation doit définir ce que le "code hérité" signifie pour elle. J'avais l'habitude de parcourir The Sunday Times petites annonces chaque semaine pour voir ce que les organisations recherchaient. C'était mon baromètre pour ce qui n'était plus pertinent (c'est-à-dire l'héritage). Eh bien, Le Sunday Times n'est plus pertinent :-) Et nous pouvons généraliser que COBOL est hérité, ASP Classic est hérité , etc ... Mais je crois que chaque organisation doit décider quand une candidature est considérée comme héritée pour elle.
Le code est hérité quand on a peur de le changer, car il peut le casser. C'est encore plus douloureux lorsque l'ensemble du système peut être détruit par des modifications de ce code.
C'est pourquoi je suis également d'accord avec la définition de Michael Feathers. Le code qui a de bons tests unitaires peut être modifié sans crainte.
Je pense également que le code hérité n'a rien à voir avec son âge. On peut écrire du code hérité dès le début.