web-dev-qa-db-fra.com

Quand un BIG Rewrite la réponse?

Il suffit de lire la question sur les Big Rewrites et je me suis souvenu d'une question à laquelle je voulais répondre moi-même.

J'ai un horrible projet qui m'a été transmis, écrit en ancien Java, en utilisant Struts 1.0, des tables avec des relations incohérentes, ou aucune relation du tout et même des tables sans clés primaires ou champs destinés à être des clés primaires mais qui ne sont pas uniques du tout. D'une manière ou d'une autre, la plupart des applications "fonctionnent tout simplement". La plupart des pages sont réutilisées (copiez le code collé) et codées en dur. Tous ceux qui ont déjà travaillé sur le projet l'ont maudit sous une forme ou une autre.

Maintenant, je pensais depuis longtemps à proposer à la haute direction une réécriture totale de cette horrible application. J'essaie lentement de passer du temps personnel, mais je pense vraiment que cela mérite des ressources dédiées pour y arriver. Après avoir lu les articles sur les grosses réécritures, j'ai des doutes. Et ce n'est pas bon quand je veux convaincre mes supérieurs de soutenir ma réécriture. (Je travaille dans une assez petite entreprise donc la proposition a la possibilité d'être approuvée)

TL; DR Quand est une grosse réécriture de la réponse et quels arguments pouvez-vous utiliser pour la soutenir?

288
Jonn

Désolé, cela va être long, mais il est basé sur une expérience personnelle en tant qu'architecte et développeur sur plusieurs projets de réécriture.

Les conditions suivantes devraient vous amener à envisager une sorte de réécriture. Je vais vous expliquer comment décider lequel faire après cela.

  • Le temps de montée en puissance des développeurs est très élevé. S'il faut plus de temps que ci-dessous (par niveau d'expérience) pour monter en puissance un nouveau développeur, alors le système doit être repensé. Par temps de montée en puissance, je veux dire le temps avant que le nouveau développeur soit prêt à effectuer son premier commit (sur une petite fonctionnalité)
    • Frais de sortie du collège - 1,5 mois
    • Toujours vert, mais ont déjà travaillé sur d'autres projets - 1 mois
    • Niveau intermédiaire - 2 semaines
    • Expérimenté - 1 semaine
    • Niveau senior - 1 jour
  • Le déploiement ne peut pas être automatisé, en raison de la complexité de l'architecture existante
  • Même les corrections de bugs simples prennent trop de temps en raison de la complexité du code existant
  • Les nouvelles fonctionnalités prennent trop de temps et coûtent trop cher en raison de l'interdépendance de la base de code (les nouvelles fonctionnalités ne peuvent pas être isolées et affectent donc les fonctionnalités existantes)
  • Le cycle de test formel prend trop de temps en raison de l'interdépendance de la base de code existante.
  • Trop de cas d'utilisation sont exécutés sur trop peu d'écrans. Cela provoque des problèmes de formation pour les utilisateurs et les développeurs.
  • La technologie utilisée par le système actuel l'exige
    • Les développeurs de qualité ayant une expérience dans la technologie sont trop difficiles à trouver
    • Il est obsolète (il ne peut pas être mis à niveau pour prendre en charge de nouvelles plates-formes/fonctionnalités)
    • Il existe simplement une technologie de niveau supérieur beaucoup plus expressive
    • Le coût de maintenance de l'infrastructure de l'ancienne technologie est trop élevé

Ces choses vont de soi. Quand décider d'une réécriture complète par rapport à une reconstruction incrémentielle est plus subjectif, et donc plus politiquement chargé. Ce que je peux dire avec conviction, c'est que déclarer catégoriquement que c'est jamais une bonne idée est fausse.

Si un système peut être remodelé progressivement et que vous avez le plein soutien du parrainage de projet pour une telle chose, alors vous devriez le faire. Voici le problème, cependant. De nombreux systèmes ne peuvent pas être repensés de manière incrémentielle. Voici quelques-unes des raisons que j'ai rencontrées qui empêchent cela (à la fois technique et politique).

  • Technique
    • Le couplage des composants est si élevé que les modifications apportées à un seul composant ne peuvent pas être isolées des autres composants. Une refonte d'un seul composant entraîne une cascade de modifications non seulement pour les composants adjacents, mais indirectement pour tous les composants.
    • La pile technologique est si compliquée que la future conception de l'état nécessite de multiples changements d'infrastructure. Cela serait également nécessaire dans une réécriture complète, mais si cela est nécessaire dans une refonte incrémentielle, vous perdez cet avantage.
    • La refonte d'un composant entraîne de toute façon une réécriture complète de ce composant, car la conception existante est tellement fubar qu'il n'y a rien à sauvegarder. Encore une fois, vous perdez l'avantage si c'est le cas.
  • Politique
    • On ne peut pas faire comprendre aux sponsors qu'une refonte progressive nécessite un engagement à long terme dans le projet. Inévitablement, la plupart des organisations perdent l'appétit pour la fuite budgétaire continue qu'une refonte incrémentielle crée. Cette perte d'appétit est inévitable pour une réécriture également, mais les sponsors seront plus enclins à continuer, car ils ne veulent pas être répartis entre un nouveau système partiellement complet et un ancien système partiellement obsolète.
    • Les utilisateurs du système sont trop attachés à leurs "écrans actuels". Si tel est le cas, vous n'aurez pas la licence pour améliorer une partie vitale du système (le front-end). Une refonte vous permet de contourner ce problème, car ils commencent par quelque chose de nouveau. Ils insisteront toujours pour obtenir "les mêmes écrans", mais vous avez un peu plus de munitions à repousser.

Gardez à l'esprit que le coût total de la refonte incrémentielle est toujours plus élevé que la réécriture complète, mais l'impact sur l'organisation est généralement plus faible. À mon avis, si vous pouvez justifier une réécriture et que vous avez des développeurs de superstars, faites-le.

Ne le faites que si vous pouvez être certain qu'il existe une volonté politique de le mener à terme. Cela signifie à la fois l'adhésion des dirigeants et des utilisateurs finaux. Sans cela, vous échouerez. Je suppose que c'est pourquoi Joel dit que c'est une mauvaise idée. Executive et l'adhésion de l'utilisateur final ressemble à une licorne à deux têtes pour de nombreux architectes. Vous devez le vendre agressivement et faire campagne pour sa continuation en continu jusqu'à ce qu'il soit terminé. C'est difficile, et vous parlez de jalonner votre réputation sur quelque chose que certains ne voudront pas voir réussir.

Quelques stratégies de réussite:

  • Si vous le faites, cependant, n'essayez pas de convertir le code existant. Concevez le système à partir de zéro. Sinon, vous perdez votre temps. Je n'ai jamais vu ni entendu parler d'un projet de "conversion" qui ne s'est pas terminé lamentablement.
  • Migrez les utilisateurs vers le nouveau système une équipe à la fois. Identifiez les équipes qui ont le PLUS de problèmes avec le système existant et migrez-les en premier. Qu'ils diffusent la bonne nouvelle par le bouche à oreille. De cette façon, votre nouveau système sera vendu de l'intérieur.
  • Concevez votre framework selon vos besoins. Ne commencez pas avec un framework que j'ai passé 6 mois à construire, qui n'a jamais vu de vrai code.
  • Gardez votre pile technologique aussi petite que possible. Ne pas trop concevoir. Vous pouvez ajouter des technologies au besoin, mais les retirer est difficile. De plus, plus vous avez de couches, plus les développeurs ont de travail à faire. Ne rendez pas les choses difficiles dès le départ.
  • Impliquez les utilisateurs directement dans le processus de conception, mais ne les laissez pas dicter comment de le faire. Gagnez leur confiance en leur montrant que vous pouvez leur donner ce qu'ils veulent mieux si vous suivez de bons principes de conception.
328
Michael Meadows

J'ai participé à deux grosses réécritures. Le premier était un petit projet. Le second était le produit principal d'une société de logiciels.

Il y a plusieurs écueils:

  • les réécritures prennent toujours plus de temps que prévu.
  • les réécritures n'ont aucun effet/avantage direct pour le client.
  • la capacité consacrée à la réécriture n'est pas utilisée pour soutenir le client.
  • vous perdrez la fonctionnalité avec une réécriture, sauf si vous avez une documentation à 100%.

Les réécritures sont rarement la vraie réponse. Vous pouvez refaçonner une grande partie du code sans rien perdre et sans trop de risques.

Les réécritures peuvent être la réponse si:

  • vous passez à une autre langue ou plate-forme.
  • vous changez de frameworks/composants externes.
  • la base de code existante n'est plus maintenable.

Mais je conseille fortement l'approche lente en utilisant le refactoring. C'est moins risqué et vous gardez vos clients satisfaits.

112
Toon Krijthe

Il est temps de réécrire quand:

Le coût de réécriture de l'application + de maintenance de l'application réécrite est inférieur au coût de maintenance du système actuel dans le temps.

Quelques facteurs qui rendent le maintien de l'actuel plus cher:

  • La langue est tellement ancienne que vous devez payer des gens qui la connaissent beaucoup d'argent pour la programmer (COBOL).
  • (par expérience, malheureusement) Le système repose sur une architecture matérielle qui est si ancienne qu'ils doivent parcourir les pièces Ebay et COLLECT pour les ajouter à la machine sur laquelle il fonctionne, car elles ne sont plus fabriquées. C'est ce que l'on appelle le "support de la durée de vie du matériel" et cela coûte cher car à mesure que les pièces se raréfient, elles peuvent (peut-être) augmenter leur prix ou elles (absolument) finiront par s'épuiser.
  • Il est devenu si complexe que le //Here be dragons. le commentaire est partout dans votre code.
  • Vous ne pouvez pas écrire d'autres projets et ajouter de la valeur à l'entreprise parce que vous corrigez toujours cette bête laide.
74
Ryan Hayes

Si vous avez besoin d'un changement fondamental dans l'architecture du projet, il est éventuellement temps de recommencer.

Même avec cela, il y aura potentiellement de grandes portions de code qui méritent toujours d'être réutilisées dans votre nouveau projet.

Attention à l'avertissement juste cependant. Un projet actuel aura vu ses règles métier testées et affinées avec d'innombrables heures-homme d'utilisation réelle, ce qui ne sera pas le cas d'un projet démarré à partir de zéro.

Je doute qu'un délai ou un sentiment d'intestin soit une mesure appropriée d'une telle mesure drastique. Vous devez avoir clair, défendable et bien compris des raisons de participer à cette ligne de conduite.

17
Dan McGrath

Bien que je sois d'accord avec la réponse de Kramii et l'opinion de Joel, il y a des moments où il convient de faire une réécriture. Dans les applications à longue durée de vie (je parle de 10 à 20 ans ou plus), la maintenance devient de plus en plus coûteuse au fil du temps. Cela est dû au fait que le code devient de plus en plus spaghetti car l'architecture originale est sacrifiée pour des correctifs de maintenance rapides. De plus, les développeurs de technologies plus anciennes deviennent plus rares et plus chers. Enfin, le matériel commence à vieillir et il devient de plus en plus difficile de trouver du nouveau matériel, des systèmes d'exploitation, des cadres, etc. pour exécuter l'ancienne application par-dessus. De plus, les entreprises évoluent et, très probablement, un système plus ancien ne répondra pas aux besoins commerciaux de l'organisation, contrairement à un tout nouveau système.

Vous devez donc peser tous les coûts de maintenance en cours, ainsi que les avantages potentiels d'un nouveau système pour l'entreprise, par rapport au coût de réécriture de la chose à partir de zéro. Soyez très pessimiste dans vos estimations concernant le coût d'une réécriture. Cela coûte presque toujours plus cher et prend plus de temps que vous ne le pensez.

12
RationalGeek

Arrêtez! La réécriture est presque jamais la réponse. Le plus souvent, le refactoring est un meilleur pari.


Bien sûr, il y a fois quand une réécriture est justifiée:

  • Vous passez à une nouvelle plateforme où les outils de migration n'existent pas (ou ne peuvent pas être écrits à moindre coût).
  • La demande à réécrire est triviale.
  • Le code source de l'application d'origine est perdu et la récupération est plus coûteuse que la réécriture.
  • La grande majorité des règles métier encapsulées par l'application existante ne s'appliquent plus.
  • Il y a peu d'utilisateurs actifs du code existant.
  • Vous avez la ressource (temps, talent et outils) pour entreprendre la réécriture.
  • L'application existante ne peut pas être exécutée dans un environnement de production, pour des raisons juridiques ou pratiques.

Pour comprendre pourquoi je recommande la refactorisation plutôt que la réécriture, considérez ce qui est impliqué dans une réécriture. Vous devez:

  1. Comprenez les nuances de ce que fait l'application existante. Ce n'est généralement pas anodin lorsque vous tenez compte de toutes les règles commerciales subtiles qu'il encapsule, de l'environnement (humain et technique) dans lequel il opère et des avantages et des inconvénients de la solution actuelle. Plus souvent qu'autrement, le seul endroit où ces informations existent (le cas échéant) est dans le code source de l'application existante. Il est regrettable que l'une des principales raisons d'effectuer une réécriture soit que le code existant soit difficile à comprendre et à maintenir.

  2. Reproduisez cette fonctionnalité (ou une version mise à jour de celle-ci) dans une nouvelle application testée et fiable. Le code existant peut ne pas être compris par les développeurs, mais est généralement bien compris par ses utilisateurs. Il peut ne pas répondre à leurs besoins commerciaux actuels, mais ils peuvent au moins vous dire ce que fait l'application dans diverses circonstances.

Les grands avantages du refactoring sont les suivants:

  • Vous pouvez prendre les choses un petit morceau à la fois.
  • Toutes les modifications peuvent être testées dans le contexte de l'application existante et fonctionnelle.
  • Les hypothèses sur le fonctionnement du code existant peuvent être testées en faisant de petits changements et en observant ce qui se passe.
  • Les modifications peuvent souvent être fournies aux utilisateurs par phases plutôt que d'un seul coup.
  • L'apprentissage des premières étapes de la refactorisation peut informer les étapes ultérieures de la refactorisation.
  • Si vous abandonnez le processus à mi-chemin, il y aura toujours des avantages en termes de base de code plus propre (par opposition à une réécriture qui doit être terminée pour offrir des avantages à l'utilisateur ou aux développeurs).

Rappelez-vous également que si vous faites une réécriture, vous êtes assuré d'introduire de nombreux nouveaux bogues et de gâcher dans la nouvelle base de code.

11
Kramii

Ce graphique pourrait aider, il est fonction de la qualité de la base de code et de la valeur commerciale de l'application:

enter image description here

Le graphique prétend être un guide sur le moment où une réingénierie des logiciels hérités est justifiée et quand elle ne l'est pas. Par exemple, si le logiciel a une valeur commerciale élevée et que la qualité du code est médiocre, une réingénierie est justifiée.

10
Tulains Córdova

Je pense que je suis dans la seule situation de ma carrière où la grosse réécriture est la réponse:

Fusion d'entreprise, énorme chevauchement des fonctionnalités des systèmes. Beaucoup, beaucoup de systèmes ont été fusionnés et mis hors service, et d'autres encore en cours.

J'ai hérité d'un système de l'autre société qui existe toujours. Il a une énorme base de code, qui supportait auparavant plusieurs départements très similaires aux nôtres, mais avec une conception et des cadres complètement différents. Il n'y a qu'un seul secteur commercial qui l'utilise, ce qui fait suffisamment d'argent pour que cette chose reste en vie dans un état zombie. Toute l'ancienne expertise a disparu, il n'y a pas de documentation. Le fardeau du support est élevé, avec des échecs chaque semaine. Il n'a pas été fusionné dans les systèmes de nos entreprises, car notre entreprise n'a jamais pris en charge ce secteur particulier de l'entreprise, nous n'avons donc pas la fonctionnalité ou l'expertise.

Il semble que ce soit le seul cas où la réécriture est nécessaire. Il semble que je vais devoir comprendre ce monstre, retirer les éléments de fonctionnalité dédiés à cette entreprise et réécrire les éléments qui doivent être ajoutés à nos systèmes existants. Une fois cela fait, nos systèmes existants peuvent soutenir ce nouveau secteur, et cette bête peut être mise hors de sa misère. Sinon, je vais perdre ma raison.

8
Jay

J'ai travaillé pour une petite société de logiciels qui avait quelques applications DOS qui ont été mises à niveau pour gérer Y2K, réécrites en tant qu'application Windows 16 bits, puis totalement réécrites en application 32 bits avec une `` petite '' fonctionnalité supplémentaire (finalement uniquement utilisée par un client) qui a eu un impact sur l'ensemble de la structure.

Déplacer le code 16 bits vers 32 aurait pu être fait en un mois par une seule personne, mais NOOOOOOOOO, nous avons dû le réécrire pour rendre Soooooooooo bien meilleur. Cette chose pourrait être adaptée à d'autres industries, aurait des spécifications complètes et un code pseudo avant même de commencer. Les spécifications ont été créées, mais il a fallu si longtemps qu'il n'y avait même pas de temps pour écrire le vrai code. Il a été publié tardivement, avec plus de bugs que le 16 bits 'commencé' (c'était sur la v.3.0 et finalement au point où nous avons presque réussi une semaine sans que quelqu'un ne signale un nouveau bug).

On pourrait penser que réécrire la même application 3-4 fois apporterait des améliorations, mais je ne pense pas qu'un frontal d'interface graphique puisse être autant justifié.

Ce fut mon premier travail informatique en tant que responsable du support technique. Je devrais écrire un livre sur la façon de ne pas développer de logiciels pour la distribution. De toute évidence, nous avons commis de nombreuses erreurs, mais le fait que nous ayons continué à réécrire les applications a aggravé l'incompétence.

7
JeffO

J'avais un cas très similaire au vôtre, seul le code n'utilisait même pas Struts. Ce que j'ai fait à la place, c'était cibler des zones qui étaient particulièrement minables ET causant beaucoup de problèmes. Cette approche ciblée nous a amélioré progressivement.

Sur une période de 2 ans, nous avons travaillé sur la refactorisation de morceaux et pièces parallèlement à des travaux d'amélioration. Nous avons toujours intégré une tâche de "durcissement" dans un plan de projet. En nous concentrant sur les domaines spécifiques qui ne fonctionnaient pas bien, nous en avons tiré le meilleur parti. Les trucs qui ont fonctionné nous ont laissé seuls. Il est également essentiel que ce travail ait été effectué au cours d'un développement normal et ait été publié. Le problème avec une grosse réécriture, vous partez pendant un an ou plus, puis au moment où vous revenez, tout a changé de toute façon et certains des bugs désagréables ont été lissés et vous avez perdu votre retour sur investissement.

Nous n'avons jamais réécrit le tout. Nous avons cependant cessé d'utiliser cette plate-forme pour de nouveaux travaux et avons proposé une nouvelle plate-forme pour un nouveau grand projet. Cela a été approuvé et nous avons livré un excellent produit dans un délai raisonnable.

5
Bill Leeper

Donc, ici, je suis assis à mon bureau, j'ai commencé à réécrire le code de ce gâchis absolu d'un gros fichier aspx, la base de données derrière, et à remplacer l'interface MS Access par MsSQL.

Ce programme asp est jonché de choses comme

  • include(close.aspx) qui à l'intérieur a une ligne de code qui ferme la dernière connexion de base de données ouverte.
  • Le code hérité vient d'être commenté au hasard
  • Aucune considération pour la sécurité
  • Code de spaghetti, des milliers de lignes. Le tout dans un seul fichier.
  • Fonctions et variables sans signification claire derrière leurs noms

Si jamais nous devons faire un petit changement, c'est comme jouer à cinq jeux simultanés de kal-toh en mode cauchemar.

J'ai été embauché pour répliquer des fonctionnalités et créer un produit qui pourrait être personnalisable et vendable à d'autres dans l'industrie. Le problème est que cette chose a été écrite au cours des 10 dernières années pour répondre à tous les besoins des entreprises (enfin, je dirais environ cinq ou six sigma de toute façon).

Si nous ne voulions pas vendre le produit, ils n'auraient probablement pas eu besoin d'une réécriture car il fait la plupart de ce qu'ils veulent - peut-être pas avec élégance, mais il n'était pas prudent de dépenser l'argent sur faire du code Nice 'faire la même chose.'

5
Incognito

La solution existante n'est pas évolutive.

Je vous regarde, MS Access.

4
user21007

Joel Spolsky a un excellent article à ce sujet: Choses que vous ne devriez jamais faire, partie I

D'après le titre que vous pouvez dire, c'est un peu unilatéral (il parle de pourquoi vous ne devriez jamais lancer de code) IMO, il y a beaucoup de vérité, j'ai récemment vu une vidéo de channel9 sur le 25e anniversaire d'Excel où certains développeurs ont dit, comment même aujourd'hui, si vous regardiez la source, vous vérifieriez la révision et reviendriez au code qu'Excel a utilisé il y a 20 ans.

Vous ne pouvez pas être sûr à 100% (quand même Netscape fait des erreurs (de l'article de Joels)), [~ # ~] i [~ # ~] Je me sentais comme si l'article de Joel avait été envoyé par Dieu, parce que je peux être pessimiste et aimer jeter du code en pensant que je peux toujours mieux l'écrire une deuxième fois, mais je ne me suis rendu compte que maintenant cela coûte juste un beaucoup .

Pour donner une réponse concrète, je dirais simplement que vous devez effectuer une analyse approfondie du coût par rapport à la valeur .

Mon monde réel: une application silverlight Im développant la v0.6 jusqu'à présent a un gâchis d'appels asynchrones qui rendent le code si compliqué. Depuis que j'ai découvert Reactive Extensions cette semaine, je veux vraiment réécrire la plupart du code, mais maintenant que dois-je dire à mon client? Le programme fonctionne parfaitement bien (avec quelques fuites de mémoire), mais ils s'en moquent? Je ne peux pas leur dire Oh, je prends 2-3 semaines de plus parce que je veux refaire quelque chose. Je vais cependant brancher le code et réécrire /jouer avec lui dans mon gratuit heure.

Juste mes 2 cents ok !?

4
gideon

Il y a la plaisanterie classique à propos de "si j'allais à X, je ne partirais pas d'ici".

J'ai pris un emploi une fois, où la principale motivation de l'employeur était d'amener des talents à bord pour lancer une réécriture attendue depuis longtemps d'une application critique pour l'entreprise. La question que je n'ai pas posée était, pourquoi vous êtes-vous retrouvé dans cette situation en premier lieu? Cela aurait dû être un drapeau rouge, que la cause soit

  • trop de pression pour ajouter des fonctionnalités pour maintenir et refactoriser progressivement la bête,

  • trop peu de capacité dans le département,

  • trop peu d'adhésion des clients ou de la direction pour un travail supplémentaire,

ou quoi que ce soit, et cette cause disparaît jusqu'à ce que le problème atteigne un niveau intolérable.

Je vais donc être d'accord avec Joel en ce sens qu'une réécriture massive est probablement une très mauvaise idée - à moins que vous n'ayez des preuves solides que toutes les raisons sous-jacentes pour lesquelles une réécriture majeure semble si nécessaire ont été traitées , vous allez probablement répéter le problème en temps voulu.

2
Julia Hayward

C'est la réponse lorsque la réécriture permet à l'organisation de poursuivre une stratégie qui offre un avantage concurrentiel ou lui permet de mieux servir ses clients d'une manière que l'architecture actuelle ne peut pas accueillir.

Au lieu de cela, les réécritures se produisent souvent pour atténuer les soucis de gestion:

  • tout devrait être en .NET,
  • nos développeurs disent que notre code est nul,
  • nous sommes en retard techniquement,
  • nous ne serons pas en mesure de trouver des ressources pour soutenir notre système ou, très souvent,
  • ça fait dix ans donc il est temps.

La plupart de ces inquiétudes ne se matérialiseront pas et, si elles le faisaient, elles pourraient être traitées. Ce dernier, cependant, est le pire. C'est essentiellement: nous n'avons pas de raison.

Oui, comme la voiture, un système commencera à montrer des signes d'usure. Cela peut être atténué par un entretien de routine. Vous savez ce qu'ils disent sur la façon dont un petit entretien préventif fait du chemin. En tant qu'investissement, l'entretien courant (c'est-à-dire le refactoring et la standardisation) coûtera presque toujours moins cher qu'une réécriture.

Cependant, nous devons prévoir qu'une réécriture sera éventuellement nécessaire. Fixez des dates et planifiez-les provisoirement, mais à mesure que la date approche, retardez en faveur de la réalisation d'autres objectifs stratégiques jusqu'à ce que vous ayez une raison impérieuse comme ...

Ces dernières années, nous avons perdu l'opportunité de gagner de grands comptes parce que nous ne pouvions pas répondre à leurs besoins en temps opportun ou coûteux. Notre système sera réécrit en utilisant une architecture extensible qui permet de brancher des personnalisations (et non de coder en dur comme nous le faisons actuellement). Cela réduira considérablement le temps et les coûts d'hébergement des clients ayant des besoins spéciaux. Nous gagnerons plus de comptes et répondrons mieux aux besoins de nos clients actuels.

2
Mario T. Lanza

Je pense que la principale raison qui justifie les réécritures est pour les changements de plate-forme. Par exemple, si vous avez une application graphique de bureau Windows et que le propriétaire de l'entreprise décide qu'il souhaite que la prochaine version soit une application Web. Bien que ce ne soit pas toujours le cas, d'après mon expérience, la plupart du temps, cela nécessitera une réécriture, à moins que les développeurs originaux n'aient écrit du code très modulaire et réutilisable (cela arrive rarement).

2
Craig

Selon Joel, les grosses réécritures sont la pire erreur stratégique qu'une entreprise peut commettre:

Choses que vous ne devriez jamais faire, partie I

... Il est important de se rappeler que lorsque vous partez de zéro, il n'y a absolument aucune raison de croire que vous allez faire un meilleur travail que vous ne l'avez fait la première fois. Tout d'abord, vous n'avez probablement même pas la même équipe de programmation qui a travaillé sur la première version, vous n'avez donc pas "plus d'expérience". Vous allez simplement refaire la plupart des anciennes erreurs et introduire de nouveaux problèmes qui n'étaient pas dans la version originale.

L'ancien mantra construisez-en un à jeter est dangereux lorsqu'il est appliqué à des applications commerciales à grande échelle. Si vous écrivez du code expérimentalement, vous voudrez peut-être déchirer la fonction que vous avez écrite la semaine dernière lorsque vous pensez à un meilleur algorithme. C'est très bien. Vous souhaiterez peut-être refactoriser une classe pour la rendre plus facile à utiliser. C'est bien aussi. Mais jeter tout le programme est une folie dangereuse, et si Netscape avait en fait une supervision adulte avec une expérience dans l'industrie du logiciel, ils ne se seraient peut-être pas tiré une balle dans le pied si mal.

2
user3287

Jamais, toujours refactoriser - la vérité est que si le code a été écrit par vous - vous ne pourrez pas faire mieux.

Sauf si vous voulez changer de technologie, le code manque de structure (je l'ai vu il y a très longtemps dans certains PHP, l'auteur vient de copier/coller des spahgetti au lieu d'inclure/classe/fonction) ou vous avez repris quelque chose d'une autre personne qui est très mal écrit.

Tout devrait être conçu comme une boîte noire. Modular, Simple API, ce qu'il y a à l'intérieur ... c'est moins important :) Si vous avez des spaghettis, vous pouvez peut-être les fermer à l'intérieur d'une boîte noire, afin qu'ils ne contaminent pas le bon code.

2
Slawek

Lors du passage à une toute nouvelle technologie est nécessaire pour fournir les fonctionnalités souhaitées.

"Complètement nouveau": si vous prévoyez de réécrire mais que vous utilisez la même plate-forme, le refactoring et une restructuration judicieuse sont presque certainement la meilleure solution. La "plate-forme", telle qu'elle est utilisée ici, est quelque peu vague - considérez-la comme incluant le langage, et peut-être le système d'exploitation (s'étendant de Linux à Windows ou vice versa), mais probablement pas le cadre (par exemple, en remplaçant Struts par Spring).

"Nécessaire pour fournir les fonctionnalités souhaitées": aux alentours de 2000, j'ai lancé un projet de réécriture d'un composant serveur majeur en Java à partir de C++ pour permettre le threading prêt à l'emploi, un cache d'objets, et les transactions contrôlées par le client. À l'époque, il y avait plusieurs bibliothèques de threads pour C++ que nous aurions dû prendre en charge, et l'activation de threads une grande partie de notre code de base de données aurait nécessité une réécriture presque totale. Comme pour les transactions contrôlées par le client. .. ne se produira pas avec l'ancienne architecture.

Même alors, je ne suis pas sûr que j'aurais fait la réécriture, sauf que j'avais une connaissance détaillée du comportement du système actuel, et c'était un code relativement propre qui n'avait pas développé beaucoup de verrues au cours de ses 11 années de vie.

1
Anon

Eh bien, je peux imaginer des scénarios hypothétiques où je pourrais simplement jeter la base de code existante (situations hypothétiques où les boules de bucky ont un poids et un volume nul, où personne ne se soucie si nous perdons des semaines ou des mois de productivité alors que nous nous battons pour ajouter des fonctionnalités et des bogues négligés corrige dans le système, et où le système est si trivial et détesté par une organisation que je peux remplacer la chose entière et l'armée de serveurs avec notepad ++ et un netbook en dix minutes et augmenter la productivité et la morale de tout le monde à tous les niveaux.)

Pour presque tous les scénarios du monde réel, je recommanderais simplement une refactorisation en place. ^ _ ^. Il y a généralement trop de coûts cachés et imprévus pour les réécritures lorsque des exigences légales et commerciales non documentées commencent à apparaître et que la dernière minute de pirater les choses ensemble à la dernière minute commence à s'ensuivre.

== Refactoring en place pour plus de bien, et des trucs ==

Refactorisation du code hérité avec l'ancienne approche incrémentielle régulière,

  1. Si vous avez la chance de convertir en UML et de documenter le peu d'architecture narqueuse qui existe.
  2. Si vous êtes sur le contrôle de version, essayez de générer des rapports de désabonnement de code et de déterminer quels fichiers et sections de fichiers ont été modifiés le plus fréquemment. Notez-les, car ce seront probablement les domaines que vous voudrez aborder en premier.
  3. Avant de modifier un code, essayez toujours d'ajouter une couverture de test (même des tests fonctionnels de pile complète laids feront l'affaire). Si vous traitez avec une grande logique d'extraction de code procédural désordonné, vous avez l'intention de passer à une méthode ou une fonction raisonnablement nommée et, si possible, ajoutez des cas de test qui vérifient votre nouvelle méthode. faites n'importe quel dieu que vous devez pirater et si possible paramétrez le changement s'il s'agit de quelque chose de communément modifié comme la largeur de la marge ou le titre, il sera donc un peu plus simple de mettre à jour la prochaine fois.
  4. Utilisez le modèle d'adaptateur et évitez de cacher les petits morceaux de code hérité sous un tapis de classes et de méthodes logiquement nommées de sorte que pour les tâches les plus courantes que vous et les autres développeurs exécutez, vous n'aurez pas à vous soucier des bits effrayants qui se passent derrière votre dos derrière ces jolies petites méthodes et classes propres, vous avez caché ce code hérité derrière - comme ces familles de Nice qui gardent les anciens membres de la famille des zombies meurtriers déformés dans les granges afin qu'ils ne gâchent pas les activités quotidiennes de la ferme. . . normalement.
  5. Alors que vous continuez à réduire et à nettoyer les sections du code, vous continuez à augmenter la couverture de votre test. Maintenant, vous pouvez creuser encore plus profondément et "réécrire" encore plus de code si nécessaire/souhaité avec une confiance sans cesse croissante.
  6. Répétez ou appliquez des approches de refactorisation supplémentaires pour continuer à améliorer votre base de code.

Ramification par abstraction

  1. Définissez le problème dans le code que vous souhaitez supprimer (la couche de persistance, le générateur de pdf, le mécanisme de décompte des factures, le générateur de widget, etc.).
  2. exécuter (écrire si nécessaire) certains cas de test fonctionnels (automatisés ou manuels mais vous savez automatisés) contre la base de code qui cible cette fonctionnalité ainsi que le comportement général.
  3. Extraire la logique liée à ce composant de la base source existante dans une classe avec une interface raisonnable.
  4. Vérifiez que tout le code utilise désormais la nouvelle interface pour effectuer l'activité X qui était auparavant dispersée de manière aléatoire dans le code (Grep la base de code, ajoutez une trace à la nouvelle classe et vérifiez que les pages qui devraient l'appeler le sont, etc.), et que vous pouvez contrôler quelle implémentation sera utilisée en modifiant un seul fichier. (registre d'objets, classe d'usine, quel que soit IActivityXClass = Settings.AcitivtyXImplementer ();)
  5. réexécutez les cas de test fonctionnels qui vérifient que tout fonctionne toujours avec tous les ajouts de l'Activité X dans votre nouvelle classe.
  6. Écrivez des tests unitaires lorsque cela est possible autour de la nouvelle classe wrapper d'activité X.
  7. implémentez une nouvelle classe avec une logique de spaghetti moins folle que l'implémentation héritée qui adhère à la même interface que la classe héritée.
  8. vérifiez que la nouvelle classe réussit les tests unitaires que vous avez écrits pour la classe héritée.
  9. mettez à jour votre code en changeant le registre/méthode d'usine/quoi que ce soit pour utiliser la nouvelle classe au lieu de l'ancienne classe.
  10. vérifiez que vos tests fonctionnels réussissent toujours.

Open Closed Principle et Common Business Logic/Persistence Layer

Dans une certaine mesure, vous pourriez être en mesure de vous séparer de votre couche de présentation, d'entreprise et de persistance et d'écrire une nouvelle application entièrement rétrocompatible avec la solution héritée, ou au minimum peut toujours gérer les données entrées par la solution héritée. Je ne recommanderais probablement pas cette approche mais parfois c'est un compromis raisonnable de temps/calendrier/ressources/nouvelles fonctionnalités requises.

  • Séparez au minimum la couche de présentation des couches métier et persistance.
  • implémenter une nouvelle interface utilisateur et une meilleure couche de présentation qui utilise la même couche commerciale et de persistance commune.
  • Vérifiez que les données créées avec la nouvelle interface utilisateur ne cassent pas l'ancienne interface utilisateur. (vous allez être dans l'eau chaude si les utilisateurs du nouvel outil interrompent les utilisateurs de l'ancien outil). Si vous recherchez une compatibilité ascendante totale, vous devez tout enregistrer dans les mêmes couches de persistance. Si vous souhaitez simplement une compatibilité directe avec le nouvel outil, utilisez une nouvelle base de données et de nouvelles tables ou tables d'extension pour suivre les données qui ne sont pas dans le système hérité.
  • Pour de nouvelles fonctionnalités et besoins de couche de persistance, ajoutez de nouvelles tables et méthodes ne modifiez pas la logique héritée existante, ou ajoutez des colonnes, des contraintes aux tables existantes. par exemple. si vous devez commencer à suivre les contacts d'urgence des employeurs et que certains autres champs ne modifient pas la table des employés existante (nous n'avons aucune idée des hypothèses que les données héritées émettent à propos de cette table) ajoutez une table d'extension employ_ext id, employee_id, emergency_contact_id, etc_id.
  • Migrez lentement les utilisateurs vers un nouveau système. si possible, mettez le système hérité en mode lecture seule, ou ajoutez simplement un avertissement indiquant aux utilisateurs qu'il ne sera plus disponible après la date X.
  • implémenter toutes les fonctionnalités manquées ou les exigences commerciales prioritaires dans la nouvelle interface utilisateur
  • roll over base d'utilisateurs.
  • continuer à nettoyer la logique métier et les utilisateurs de la couche de persistance d'autres méthodologies de refactoring.
0
Keith Brings

Je dirais qu'il y a une troisième catégorie dans l'espace Refactor vs Rewrite ... Et c'est la mise à jour de vos versions linguistiques, compilateurs et bibliothèques ... Parfois, simplement adopter des techniques de codage modernes a un grand avantage.

Prenez C # par exemple, le code v7 écrit beaucoup plus propre, plus sûr et plus concis que v2 .. Des choses comme Elvis et l'opérateur de coalescence nulle aident une tonne.

Changer de compilateur pourrait également donner un nouveau souffle à un code plus ancien. De même pour les nouvelles bibliothèques qui pourraient rendre les choses plus faciles à travailler et à implémenter ... La mise en réseau est un excellent exemple d'un éventail de difficultés d'implémentation.

Aussi - systèmes Linux embarqués ... Pensez à installer de nouveaux outils - passez à git depuis svn. ou ajoutez Vi à votre système, etc.

Cela ne doit pas toujours être un refactoreur vs une réécriture .. Votre architecture a probablement besoin d'être améliorée, mais cela fonctionne ... peut-être que vous avez juste besoin de penser à la façon dont votre code est écrit, etc.

0
visc

Pour décider du moment auquel vous devez recommencer, vous devez déterminer où la valeur de la poursuite de votre projet actuel est inférieure à la valeur de recommencer.

La raison pour laquelle cela est si difficile est que vous faites une estimation précise de la vitesse de développement de l'équipe sur le nouveau projet jusqu'à ce que vous le lanciez réellement. Cela dit, si, en utilisant une estimation TRÈS conservatrice de votre vitesse de développement sur le nouveau projet, le projet est estimé donner un retour sur investissement intéressant, alors vous avez une analyse de rentabilisation pour recommencer à zéro.

0
Nobody

Avec ma métrique, vous devez remplir deux conditions pour justifier une réécriture:

  1. Après la réécriture, les nouvelles fonctionnalités seront plus faciles/plus rapides/moins buggées à écrire
  2. La réécriture prendra moins ou un temps égal à l'ajout de la nouvelle fonctionnalité actuelle.

Même alors, vous souhaitez limiter la portée de votre réécriture. Par exemple, nous avions un logiciel hérité dans une entreprise qui était écrit en C++ avec la mentalité d'un programmeur C qui ne connaissait pas la modularité. Le résultat final a été un code speghetti sous la forme d'une machine à états finis couvrant plusieurs classes et DLL. Nous avions une nouvelle exigence très différente des hypothèses intégrées dans le code et qui allait faire partie de la valeur ajoutée brevetée de l'entreprise pour ses clients.

Après avoir passé du temps avec le code à implémenter d'autres fonctionnalités, j'ai eu une très bonne idée du temps qu'il faudrait pour déterminer laquelle des plusieurs instructions de commutation je devrais changer, etc. Ma proposition était de réécrire la section de code qui était l'énorme machine à états finis - cela devrait me prendre moins de temps que d'étendre le code existant. J'ai pu consolider en un DLL ce qui était auparavant de trois, et fournir une structure beaucoup plus orientée objet qui rendrait beaucoup plus facile la nouvelle fonctionnalité critique et la rendrait plus facile à ajouter de nouvelles fonctionnalités.

Il y avait trois autres applications utilisant les bibliothèques qui avaient besoin de la réécriture, donc je ne voulais pas avoir à réécrire complètement ces programmes. La portée était limitée à la bibliothèque et à ce qui était nécessaire pour lier la bibliothèque au logiciel existant. Mes estimations n'étaient pas loin de loin, et le travail était rentable. Peu de temps après la refonte, j'ai été chargé d'ajouter une nouvelle fonctionnalité. Ce qui m'aurait pris une semaine avec l'ancienne structure ne m'a pris qu'une journée avec la nouvelle structure.

0
Berin Loritsch

L'OP n'indique pas la portée du projet, mais l'indice principal que j'ai pris était "écrit en ancien [langue/dialecte] en utilisant de vieilles [libs]" qui pour moi sont les principaux moteurs d'une réécriture. En fait, la plupart des projets sur lesquels j'ai travaillé sur une longévité significative du marché finissent par se rendre compte que les mises à jour des compilateurs/interprètes/systèmes d'exploitation sont une tâche importante pour maintenir la base de code.

En bref, je planifierais la réécriture par phases, en priorisant d'abord la mise à jour dans les bibliothèques. Il se peut que, en cours de route, vous puissiez vous faufiler dans d'autres optimisations, mais le fait que vous envisagez de reporter certains changements à une phase ultérieure peut être un excellent moyen de respecter le calendrier et d'éviter d'être "bloqué".

0
MarkHu