Dans une base de code héritée, comment savoir rapidement ce qui est utilisé et ce qui ne l'est pas?

21

On m'a demandé d'évaluer ce qui semble être une base de code héritée substantielle, en tant que précurseur d'un contrat de maintenance de cette base de code.

Ce n'est pas la première fois que je suis dans cette situation. Dans le cas présent, le code est destiné à un site de jeu multijoueur à profil assez élevé et assez chargé, prenant en charge au moins plusieurs milliers de joueurs en ligne à la fois. Comme beaucoup de ces sites sont, celui-ci est un mélange de technologies frontales et principales.

La structure du site, vue de l'intérieur, est un gâchis. Il y a des dossiers suffixés "_OLD" et "_DELETE" qui se trouvent partout. La plupart des dossiers semblent inutiles ou portent des noms très cryptés. Il pourrait y avoir un certain nombre d'anciens scripts inutilisés qui traînent même dans des dossiers d'apparence légitime. Non seulement cela, mais il y a sans aucun doute de nombreuses sections de code disparues, même dans des scripts par ailleurs opérationnels (une préoccupation beaucoup moins urgente).

Il s'agit d'un transfert des mainteneurs en place, aux développeurs / mainteneurs originaux du site. Comme il est compréhensible de manière typique dans ce genre de scénarios, le titulaire ne veut rien avoir à faire avec le transfert autre que ce qui est contractuellement et légalement exigé d'eux pour le repousser au responsable nouvellement élu. Il est donc tout simplement hors de question d'extraire des informations sur la structure du site existant.

La seule approche qui vient à l'esprit pour entrer dans la base de code est de commencer à la racine du site et de parcourir lentement mais sûrement les scripts liés ... et il y en a probablement des centaines en cours d'utilisation, et des centaines d'autres qui ne le sont pas. Étant donné qu'une partie substantielle du site est en Flash, cela est encore moins simple car, en particulier dans les anciennes applications Flash, les liens vers d'autres scripts peuvent être intégrés dans des fichiers binaires (.FLA) plutôt que dans des fichiers texte (.AS / ActionScript).

Je me demande donc si quelqu'un a de meilleures suggestions sur la façon d'aborder l'évaluation de la base de code dans son ensemble pour la maintenabilité. Ce serait merveilleux s'il y avait un moyen de regarder un graphique de la fréquence d'accès aux fichiers sur le système d'exploitation du serveur Web (auquel j'ai accès), car cela pourrait donner un aperçu des fichiers les plus critiques, même s'il ne le ferait pas être en mesure d'éliminer les fichiers qui ne sont jamais utilisés (car certains fichiers ne peuvent être utilisés qu'une seule fois par an).

Ingénieur
la source
7
Je ne connais pas assez le flash mais si vous obtenez des erreurs de compilation lorsque le code n'est pas là, vous devriez pouvoir renommer les dossiers pour voir s'ils sont référencés.
Oded
Solution maléfique: supprimez-les et attendez les rapports d'erreurs / bogues. (Assurez-vous simplement qu'il est récupérable!)
Izkata
1
@Nick Pourriez-vous préciser si vous êtes payé pour l'évaluation dans le cadre de la prochaine phase du contrat que vous devez encore soumissionner ou obtenir autrement? Votre réponse ne changera pas la question "existe-t-il un outil", mais certains d'entre nous pourraient élaborer des réponses concernant un processus qui serait mieux adapté à votre situation (par exemple, vous empêcher de vous faire foutre, etc.).
jcmeloni
@jcmeloni Non, je ne suis pas payé pour l'évaluation. Mais d'après mon expérience , et à partir de petites choses que j'ai ramassées au cours des deux derniers jours, ils n'ont personne d'autre à la table pour le moment. Mon niveau de compétence est assez inhabituel, donc je suis encore plus à l'aise qu'ils n'aient personne d'autre en compétition, d'après la citation. Le devis en question est celui de mon futur client à son client, qui prévoit de lui attribuer à nouveau le contrat. Vraiment de mon côté, je suis censé les aider à fournir cette citation. HTH.
Ingénieur
@Oded Rename est définitivement plus facile que la suppression par essais et erreurs! Bonne pensée là-bas. C'est un outil de plus dans la boîte.
Ingénieur

Réponses:

32

Étant donné que ce qu'on vous demande de faire est de fournir une entrée pour que votre client écrive une proposition appropriée à l' autre client (code propriétaire du cauchemar) pour tout travail sur ce code, je vais un membre et dire que vous n'allez pas faire de test approfondi ou de refactorisation ou quoi que ce soit dans ce sens à ce stade. Vous avez probablement très peu de temps pour obtenir une estimation approximative. Ma réponse est basée sur mon expérience dans la même situation, et donc si mon interprétation est incorrecte, ignorez tout ce qui suit.

  • Utilisez un outil d'araignée pour avoir une idée des pages qui s'y trouvent et de ce qui est entrant. Même un outil de contrôle de liens de base - pas un outil spécifique "d'araignée à des fins d'audit" - sera utile à cet égard.
  • Créez une feuille de calcul d'audit / d'inventaire de base. Cela peut être aussi simple qu'une liste de fichiers et leur date de dernière modification, organisés par répertoire. Cela vous aidera à avoir une idée de la portée, et lorsque vous accédez à des répertoires comme _OLD et _DELETE, vous pouvez noter que a) votre évaluation est basée sur des éléments qui ne se trouvent pas dans ces répertoires b) la présence de ces répertoires et le potentiel de les cauchemars crus / cachés témoignent de problèmes plus profonds qui devraient être pris en compte dans l'offre de votre client , d'une manière ou d'une autre. Vous n'avez pas à passer un milliard d'années à énumérer les problèmes possibles dans _OLD ou _DELETE; les informations alimenteront l'éventuelle offre.
  • Étant donné que vous examinez ce qui ressemble à une application entièrement basée sur le Web, même les outils standard d'analyseur de journaux vont être votre ami. Vous pourrez ajouter à la feuille de calcul un sens de «c'est dans le top 10 des scripts consultés» ou quelque chose du genre. Même si les scripts sont intégrés dans des fichiers Flash et ne sont donc pas spiderables, il y a une forte probabilité qu'ils soient accessibles via POST ou GET, et apparaîtront dans les journaux du serveur. Si vous savez que vous disposez de 10 scripts hautement accessibles, et non 100 (ou vice versa), cela vous donnera une bonne idée de la façon dont les travaux de maintenance se dérouleront probablement.

Même dans un site compliqué, ce que j'ai décrit ci-dessus est quelque chose que vous pourriez faire en une journée ou une journée et demie. Étant donné que la réponse que vous allez donner à votre client est quelque chose comme "cela va être une douleur énorme dans le cul, et voici quelques raisons pour lesquelles vous allez simplement mettre du rouge à lèvres sur un porc, vous devez donc enchérir en conséquence "ou" toute personne raisonnable ferait une offre non pas pour maintenir mais pour recommencer, vous devriez donc enchérir en conséquence "ou même" ce n'est pas si mal, mais ce sera un flux de travail cohérent sur une période donnée, alors enchérissez en conséquence " , le fait est qu'ils vont faire l'offre et que vous n'avez donc pas besoin d'être aussi précis que si vous étiez embauché directement pour effectuer un audit complet du contenu et de l'architecture.

jcmeloni
la source
2
+1 C'est une réponse fantastique. Où est passé ce bouton +5 ...
Ingénieur
1
TL; DR: ne vous envoyez pas dans un terrier de lapin avant d'y être obligé. :)
jcmeloni
4

Je recommande fortement de refactoriser le code source existant (par opposition à une réécriture) en utilisant les modèles trouvés dans le livre " Working Effectively With Legacy Code ".

Le livre détaille plusieurs mécanismes pour couvrir efficacement le code hérité dans les tests unitaires, afin que vous puissiez ensuite commencer à refactoriser le code en toute sécurité. Le livre est divisé en plusieurs parties, l'une décrivant la philosophie derrière l'approche, puis plusieurs chapitres qui résolvent des problèmes particuliers, tels que "Il faut une éternité pour faire un changement", "Je n'ai pas beaucoup de temps et j'ai besoin de le changer" et "Je ne peux pas intégrer cette classe à un harnais de test". Chacun de ces chapitres présente des techniques détaillées et éprouvées qui vous aident à apprendre comment appliquer les meilleures pratiques de test à des problèmes réels.

La lecture du livre m'a donné un sentiment très réel que "nous ne sommes pas seuls" ... beaucoup d'entre nous, ou peut-être tous, travaillons avec des bases de code complexes qui sont devenues difficiles à gérer. Les techniques énumérées dans le livre m'ont donné beaucoup d'espoir et j'ai personnellement pu les appliquer presque immédiatement.

Le billet de blog de Joel Spolsky fait un excellent travail pour expliquer pourquoi il est préférable de conserver une base de code existante et fonctionnelle plutôt que de partir de zéro. J'ai choisi une citation de l'article qui le résume, mais c'est une lecture fantastique.

"Il y a une raison subtile pour laquelle les programmeurs veulent toujours jeter le code et recommencer. La raison en est qu'ils pensent que l'ancien code est un gâchis. Et voici l'observation intéressante: ils ont probablement tort. La raison pour laquelle ils pensent que l'ancien le code est un gâchis à cause d'une loi fondamentale et fondamentale de la programmation:

Il est plus difficile de lire du code que de l'écrire. ". - http://www.joelonsoftware.com/articles/fog0000000069.html

Kyle Hodgson
la source
4
+1. En réponse au commentaire de Joel, "ça ne devrait pas être sanglant." Parce que je ne vois pas le problème comme inhérent. Je vois cela comme étant en partie le fait que beaucoup de gens écrivent du code de mauvaise qualité et ne s'en soucient pas, tandis que beaucoup d'autres écrivent du code raisonnablement bon mais vivent selon le concept de "code auto-documenté" ... qui est tout simplement BS: On peut flatter son propre style de codage tout ce que l'on souhaite dans la vie privée, mais quand il s'agit de bases de code publiques, il suffit de générer des commentaires comme s'il n'y avait pas de lendemain. Ça ne fait pas mal. Et enfin, il y a des gens qui doivent faire fonctionner les choses dans des bases de code héritées, avec un budget temps serré.
Ingénieur
2

Dans une base de code Java typique, j'envisagerai d'utiliser des outils tels que PMD, FindBugs ou Sonar, puis j'essaierai de comprendre les rapports d'outils (code mort, code non documenté, code dupliqué, etc.)

Sur la base des rapports, je vais essayer de trouver les différentes couches de l'application / du site (couche métier, DB, SQL, etc.)

Si les couches sont couplées (html dans le servlet, sql dans le code java), je commencerai par découpler chacune de ces étapes doit être considérée comme isolée et vous pouvez vous engager à la fin de chacune (en démarrant une branche puis en faisant fusion) .

Abderrazak BOUADMA
la source
1
Merci. Bien que votre réponse soit quelque peu spécifique à Java, il est intéressant de voir votre approche en couches ... éplucher l'oignon, pour ainsi dire. Quelque chose à quoi penser.
Ingénieur
1

D'après votre description, il semble que ce code ait atteint l'état impossible à maintenir, ce qui signifie que la meilleure approche est probablement une réécriture complète. Les développeurs auraient des chèques de paie beaucoup plus petits s'il y avait des outils de qualité qui fonctionnaient pour maintenir une base de code en désordre maintenable. Il est possible de parcourir et de nettoyer l'ancien code inutile des dossiers, mais c'est une tâche manuelle et vous n'obtiendrez probablement pas tout de toute façon sans un temps déraisonnable. Je suis juste en train de deviner ici, mais je parie que le code de travail lui-même est tout autant un gâchis que la structure du fichier, ce qui signifie que même lorsque vous parvenez à couper la base de code en code actif, cela restera un cauchemar. pour mettre à jour ou réparer quoi que ce soit.

Je voudrais souligner que l'effort requis pour obtenir le code existant dans un état maintenable serait égal ou supérieur à l'effort de recommencer sur une réécriture. une partie du maintien de quoi que ce soit consiste à savoir quand «le prendre derrière le hangar et le tirer».

Ryathal
la source
Habituellement, je serais à 100% avec vous dans l'approche du lancer et de la réécriture. Mais dans ce cas (et au moins pour l'instant), je suis payé uniquement pour les travaux d'entretien du site, plutôt que pour une révision plus approfondie qui prendrait plusieurs semaines. De plus, même si je le voulais en ce moment, je ne pouvais pas continuer à le faire et à maintenir les autres contrats que j'ai en cours, car ma disponibilité hebdomadaire pour cela est explicitement limitée - mon contrat principal doit être respecté à son Minimum hebdomadaire de 40 heures.
Ingénieur
1
Pas d'accord avec le lancer et la réécriture! De joelonsoftware.com/articles/fog0000000069.html ... "Il y a une raison subtile que les programmeurs veulent toujours jeter le code et recommencer. La raison en est qu'ils pensent que l'ancien code est un gâchis. Et voici l'observation intéressante : ils ont probablement tort. La raison pour laquelle ils pensent que l'ancien code est un gâchis est à cause d'une loi cardinale et fondamentale de la programmation: il est plus difficile de lire du code que de l'écrire. " Au lieu de cela, je recommande fortement la refactorisation: amazon.ca/Working-Effectively-Legacy-Michael-Feathers/dp/…
Kyle Hodgson
1
@KyleHodgson parfois le code est en fait un gâchis, et quand vous êtes au point que c'est un gâchis de trouver le code avant de le lire, il est temps de recommencer.
Ryathal
Ouais, je ne pense pas que ce soit aussi clair que ça, bien que ce livre ait l'air d'être lu. Cela dépend beaucoup de la taille / complexité de la base de code et des corps chaleureux disponibles pour faire le travail.
Ingénieur
1

Un robot d'indexation Web peut vous aider à déterminer quelles URL sont accessibles. Surtout s'il est assez intelligent pour extraire des liens de Flash ou JavaScript. Une fois que vous avez une liste de pages Web, parcourez-les et répertoriez les fichiers auxquels elles se réfèrent. Tout ce qui reste après ce processus doit être considéré comme du code mort.

Mike Baranczak
la source
1
Je suis fortement en désaccord avec votre dernière phrase. Le robot d'exploration ne peut découvrir que les pages liées entre elles sous forme de graphique dirigé avec un ou plusieurs points de départ. Mais lorsque nous parlons d'un site Web, il existe également des «pages de destination» qui renvoient vers d'autres pages, mais il n'y a aucun lien pointant vers elles. De plus, il peut y avoir d'anciennes parties de l'interface d'administration qui sont également déconnectées des autres pages. J'ai actuellement un projet de ce type.
scriptin
0

Remarque: J'ai mis un accent sur l'utilisation de la base de données, pendant que vous posiez des questions sur l'utilisation du code lui-même. La réponse s'applique toujours aux deux cas sur tous les points que j'ai mentionnés.

Vous avez déjà répondu en partie à votre propre question dans le dernier paragraphe: voir à quoi on accède pendant que l'application est en cours d'exécution.

  1. Vous pouvez souhaiter profiler la base de données et demander au profileur d'enregistrer toutes les requêtes pendant une journée. Il vous donnera un aperçu des objets de base de données les plus utilisés, mais ne dira pas lesquels ne sont jamais utilisés. En outre, vous devez toujours être prudent avec les résultats: par exemple, une table peut être utilisée exclusivement via des procédures stockées, mais lorsque vous examinerez les requêtes du profileur, il semblerait que la table ne soit pas utilisée du tout.

  2. L'examen du code source, la recherche de requêtes est plus utile, et après avoir collecté toutes les requêtes, vous pouvez avoir une bonne compréhension de l'utilisation de la base de données, non pas en termes de fréquence (c'est là qu'un profileur est pratique), mais en termes d'utilisation / non tables utilisées. Malheureusement, pour une base de code mal écrite / non maintenue pendant des années, elle peut être extrêmement difficile et sujette aux erreurs , surtout si les requêtes sont construites dynamiquement (imaginez une méthode qui, dans a select, utilise un paramètre comme nom de la table; comment pouvez-vous savoir éventuellement quelles sont les valeurs possibles du paramètre en regardant simplement le code source?).

  3. L'analyse statique et certains compilateurs peuvent également révéler du code mort, mais ne vous donnent toujours pas la réponse que vous souhaitez.

  4. L'analyse des données elles-mêmes ou des métadonnées de la base de données peut révéler des informations intéressantes. Par exemple, il serait facile d'affirmer que la table LogonAudit(uniqueidentifier LogonAuditId, datetime LogonEvent, ...)n'est pas utilisé plus longtemps si elle contient 10 000 enregistrements par jour pour les années 2006 à 2009, et aucun enregistrement de Septembre, 18 e , 2009. La même chose est pas vrai pour un table qui contient les données en retrait pour être principalement en lecture seule.

Ces quatre points ensemble vous donneront la liste des tableaux utilisés. Les autres sont utilisés ou non. Vous pouvez faire des affirmations et les tester, mais sans une bonne couverture des tests unitaires, ce ne serait pas facile. Tout moyen "facile" échouerait également. Par exemple, si vous avez une products_delme_not_usedtable, vous pouvez affirmer que la table n'est pas utilisée du tout et rechercher "products_delme_not_used" dans votre code. C'est optimiste: il n'est pas rare de trouver le candidat DailyWTF comme celui-ci dans une ancienne base de code:

// Warning: WTF code below. Read with caution, never reuse it, and don't trust
// the comments.

private IEnumerable<Product> GetProducts()
{
    // Get all the products.
    return this.GetEntities<Product>("PRODUCT");
}

private IEnumerable<T> GetEntities<T>(string tableName)
{
    // Everyone knows that SQL is case sensitive.
    tableName = tableName.ToLower();

    if (tableName == "user" || tableName == "product")
    {
        // Those tables were renamed recently in the database. Don't have time
        // to refactor the code to change the names everywhere.
        // TODO: refactor the code and remove this `if` block.
        tableName += "s";
    }

    if (this.IsDelme(tableName))
    {
        // We have some tables which are marked for deletion but are still
        // used, so we adjust their name.
        tableName = this.Delme(tableName);
    }

    return this.DoSelectQuery<T>("select top 200 * from " + tableName);
}

private bool IsDelme(string name)
{
    // Find if the table is among candidates for removal.
    List<string> names = this.Query<string>("select Names from DelmeTables");
    return names.Contains(name);
}

private string Delme(string name)
{
    // Return the new name for a table renamed for deletion.
    return string.Join("_", new [] { name, "delme", "not", "used" });
}

Pouvez-vous comprendre que ce code utilise réellement une products_delme_not_usedtable?

Si j'étais toi, je:

  1. Gardez tous les objets de la base de données en place,
  2. Refactorisez l'ensemble de l'application (si cela en vaut la peine),
  3. Documenter (tout en refactorisant) l'application et en particulier l'utilisation de la base de données.

Lorsque vous aurez terminé les deux dernières étapes, vous aurez probablement une meilleure compréhension de l'utilisation de la base de données, ce qui aidera à déterminer les noms des tables qui ne sont plus utilisées et peut les supprimer plus ou moins en toute sécurité.

Arseni Mourzenko
la source
0

Il me semble que vous devez obtenir suffisamment d'informations pour créer un devis, je vais donc me concentrer sur cet effort.

J'essaierais de déterminer le nombre de cas d'utilisation impliqués dans ce site. Cela vous donne généralement une idée de la taille et de la complexité du site et du temps qu'il faudra pour recréer ou maintenir le site / l'application.

Oui, il est vrai que parfois le code n'est plus utilisé et cela rendra l'application un peu plus grande qu'elle ne l'est vraiment, mais je ne pense pas que cela affectera les nombres de plus de 20% au maximum , donc je ne m'inquiéterais pas pour cette partie.

La lecture du code source, des pages Web et des tables de base de données devrait vous aider à le découvrir.

Vous pouvez également envisager de limiter le nombre d'heures par mois que vous consacrerez à ce projet pour les frais prédéterminés pour vous protéger.

En ce qui concerne la découverte de ce qui est utilisé et non utilisé, il n'y a vraiment pas de moyen facile. Les outils d'analyse de code peuvent aider, mais comme vous faites face à un problème aussi mitigé, je ne pense pas qu'il existe un seul outil qui puisse vous aider. Pour chaque domaine spécifique, vous pouvez probablement trouver un outil d'analyse de code qui peut vous aider.

Sarel Botha
la source