web-dev-qa-db-fra.com

Comprendre la base de code complexe déjà existante

Duplicata possible:
Quel est le moyen le plus efficace d'ajouter des fonctionnalités à un code inconnu et structurellement défectueux?

Jusqu'à présent, tout ce que j'ai travaillé est avec Java projets que je construis à partir de zéro (principalement des projets de cours et des trucs de passe-temps). Mais maintenant, je suis tombé sur une énorme base de code d'environ 46000 lignes réparties sur environ 200 classes. En outre, il existe environ 10 bibliothèques dépendantes.

Le problème n'est pas seulement que je n'ai jamais travaillé avec le code de quelqu'un d'autre auparavant, mais je n'ai jamais travaillé avec une base de code aussi énorme auparavant.

On me demande de bien comprendre la base de code et de suggérer des améliorations à la conception existante. Maintenant, je suis un peu coincé. Je commence par une partie du code, puis au moment où j'atteins une autre partie du code, j'ai perdu les détails de travail de la partie précédente.

Je pourrais vraiment utiliser vos suggestions et vos expériences pour résoudre ce problème. Comment procéder/documenter les détails des classes pour mieux comprendre le code?

Edit: Il s'agit d'un projet de recherche de niveau universitaire. Les étudiants l'ont développé sur quelques années et la mauvaise partie: les étudiants qui ont écrit cela ont déjà obtenu leur diplôme. La documentation existante (uniquement sous forme de Javadocs, pas de trucs UML) est beaucoup mais pas utile en termes de compréhension de la conception de l'application.

37
Ankit

Travailler avec le code est le meilleur moyen de l'apprendre. Il n'y a pas de moyen "express" d'apprendre une énorme base de code, mais il y a quelques choses que vous pouvez faire.

Vous pouvez essayer de modifier le code pour ajouter de petites fonctionnalités et refactoriser et apprendre la base de code de cette manière. Essayez de vous concentrer sur de petites sections localisées de la base de code, en essayant de l'apprendre en petits morceaux.

S'il y a des tests unitaires, vous pouvez essayer de les étudier pour mieux comprendre comment le code est censé fonctionner. S'il n'y a pas de tests, les écrire peut être un excellent moyen de comprendre des parties du code. Par définition, les tests unitaires sont censés ne tester qu'une seule unité, vous pouvez donc vous concentrer uniquement sur cette unité, en vous moquant de toutes les autres dépendances. Cela vous permettra de vous concentrer et d'apprendre une unité de code à la fois, jusqu'à ce que vous en sachiez de plus en plus sur la base de code.

Une autre excellente technique consiste à exécuter le code dans un débogueur et à parcourir l'exécution complète de certains cas d'utilisation. Cela vous donnera une bonne vue de la façon dont le système répond et exécute certaines fonctionnalités.

Ne vous attendez pas à ce que cela se fasse du jour au lendemain. Il faudra un certain temps pour comprendre les subtilités de la base de code, mais l'écriture/compréhension des tests unitaires est un moyen fantastique de les apprendre.

25
Oleksi

Je dois faire beaucoup de révisions de code et cela inclut une base de code large et complexe.

J'essaie de construire un mind map du composant quand c'est possible.

Si je dois travailler ou contribuer au projet, je fais quelque chose de très efficace en ajoutant (ou en changeant) des commentaires dans un domaine qui n'était pas clair au départ.

Enfin, un simple aperçu "architectural" du projet doit être construit pour les futurs réviseurs de code. La carte mentale sera très utile pour cette étape.

18
user2567
  • J'étais dans une position similaire après avoir terminé la première année à l'université. Sur la base de cette expérience, je pense que vous mordez plus que vous ne pouvez mâcher.

Les éléments suivants pourraient vous faciliter la vie, mais vous devrez y consacrer beaucoup de travail.

  • Acquérir une compréhension complète de votre domaine problématique. Parlez aux fonctionnalités de l'application métier et du modèle avec des diagrammes de cas d'utilisation ou quelque chose de similaire. Je suppose que vous avez un temps et des ressources illimités pour le faire.

  • Vous devez décomposer votre problème en tâches plus petites. Fixez-vous un objectif et travaillez vers l'objectif. Par exemple. Je veux comprendre le processus d'authentification. Trouvez le code qui, selon vous, fait cela et commencez à travailler dessus. Si vous raccrochez sur l'ensemble du système, il est très peu probable que vous arriviez à quelque chose à mon avis.

  • Obtenez des contacts de personnes qui ont déjà travaillé sur ce sujet. S'ils sont toujours dans la même entreprise, travaillez avec eux après vous être familiarisé avec le système.

  • En parcourant le code, en documentant ce qu'il fait, cela vous prendra très longtemps. Je doute que vous puissiez vous le permettre.

  • Déployez le système dans un nouvel environnement. J'espère que ça va casser et que vous devrez déboguer beaucoup de code pour voir ce qui se passe.

  • En supposant que vous disposez des cas d'utilisation, commencez à déboguer via la base de code.

  • Assurez-vous de bien comprendre pourquoi les entreprises souhaitent que vous examiniez la base de code. Ce n'est certainement pas seulement un exercice coûteux et inutile, ils doivent donc avoir une bonne raison. Cela devrait vous donner une bonne idée où chercher.

  • Il existe des outils qui analysent la base de code et vous indiquent si elle est étroitement couplée et combien de code en double existe. Cela peut être utile, mais pas au début de votre projet.

  • Vérifiez s'il y a des tests unitaires. Commencez à les exécuter pour voir ce que le système est capable de faire.

Choses à garder à l'esprit:

  • Ce n'est pas une tâche facile, alors ne vous battez pas.

  • Il y aura beaucoup de choses que vous ne comprendrez pas, alors ne raccrochez pas à ces choses et continuez d'avancer.

  • C'est normalement assez démotivant, il est donc important que vous preniez note de vos progrès. Je l'ai normalement sur un tableau blanc devant moi.

  • Ne raccrochez pas aux gros chiffres. Oui, vous pouvez l'utiliser en auto-défense et 200 classes équivaut probablement à pas mal de responsabilités, mais cela ne vous facilite pas la vie, alors cherchons des solutions :)

10
CodeART

Bienvenue dans le monde du développement logiciel. La plupart du temps, vous allez:

  • Travaillez avec une grande base de code préexistante.
  • La documentation sera limitée.
  • Les créateurs originaux ont disparu depuis longtemps.
  • Personne ne connaîtra vraiment le système de bout en bout.

La plupart du temps, vous allez être projeté et vous devez le découvrir. Bien sûr, il y aura des gens le long du chemin et une certaine quantité de documentation pour vous aider, mais à la fin, c'est à vous de donner un sens aux choses. Je pense que cela donner un sens aux choses est différent pour chaque personne et est une compétence qui fait vraiment une différence.

D'après mes expériences/observations sur la façon dont les autres le font, voici ce que je vois qui fonctionne:

  • En l'abordant de manière à trouver d'abord le squelette du système, puis à commencer à remplir les détails.
  • Écrire des arborescences d'appels qui montrent comment se rendre d'un endroit à l'autre dans le code. Souvent, ce n'est qu'un domaine particulier et non l'ensemble du système.
  • Utilisation d'outils qui vous aident à comprendre le code. J'utilise la fonction de recherche et la fonction de références de Slickedit. Je pense également qu'Eclipse a des outils comme celui-ci.
  • Expérimentation sur le fonctionnement du système. Souvent, j'utilise un niveau élevé de traçage/printfs avec des tests de différentes choses pour m'aider à comprendre le flux.

En fin de compte, la chose qui aide le plus est Répétition! Plus vous passez par les choses, plus il est facile de savoir quoi. Dans l'industrie, nous disons souvent qu'il faudra quelques mois avant que vous puissiez considérer quelqu'un comme ayant les connaissances nécessaires pour être efficace. Cela est dû à la courbe d'apprentissage.

Enfin, d'après ma propre expérience, j'ai l'impression qu'il y a quelques étapes pour comprendre une nouvelle base de code importante:

  • Étape 1: Prenez vos repères. À ce stade, il s'agit d'apprendre où se trouvent les choses et de se familiariser. Je dirais que vous devez vous attendre à pouvoir apporter de petits changements avec succès.
  • Étape 2: Vous savez où en sont les choses et êtes capable de faire des changements de taille moyenne avec un peu de chance. Je dirais qu'à ce stade, vous auriez besoin d'une bonne quantité d'aide pour bien faire les choses mais vous pouvez faire avancer les choses.
  • Étape 3: Vous avez une très bonne compréhension du code et êtes capable de faire de grandes modifications compliquées. Le problème le plus courant à ce niveau est qu'une compréhension incomplète du niveau système vous amène à introduire des bogues. Vous êtes toujours très efficace.
  • Étape 4: Vous avez une compréhension complète et pouvez plier le système à votre guise. Je dirais que très peu de personnes arrivent jamais ici.
6
barrem23

À moins que quelque chose comme cela n'existe dans la documentation, j'aime dessiner des diagrammes de classes et de séquences UML pour avoir une idée de la structure statique et du comportement dynamique du code. Ces diagrammes ne doivent pas nécessairement être formellement corrects, mais donnez-moi quelque chose à regarder lorsque j'ai un "qu'est-ce que cela fait à nouveau ??" moment.

S'ils sont déjà là, j'aime aussi regarder les tests unitaires pour voir comment tout cela se combine. S'il n'y en a pas, les écrire est aussi un bon moyen d'accéder à la base de code.

EDIT: Je ne dessine pas les diagrammes pour tout le code, seulement la partie sur laquelle je travaille actuellement et qui me déroute (hiérarchies d'héritage complexes, etc.).

5
ftr

Concentrez-vous sur structures de données - c'est là que le caoutchouc frappe la route.

La définition des données (par exemple, le schéma de base de données, les formats de fichier) prend beaucoup moins de lignes (de code) que la logique d'application, mais elle est cruciale pour vraiment comprendre ce que fait l'application. Apprenez les structures et les relations des données. Après cela, il est beaucoup plus facile d'enrouler la tête autour du reste du programme.

Connaître la disposition des données vous donne sens de l'orientation lors de la lecture du code. C'est comme avoir une carte et une boussole en naviguant en forêt.

"Montrez-moi votre organigramme et cachez vos tableaux, et je continuerai à être mystifié. Montrez-moi vos tableaux, et je n'aurai généralement pas besoin de votre organigramme; ce sera évident." - Fred Brooks, Le mois-homme mythique

PS. Les données vivent pour toujours. Les programmes (et les ordinateurs) sont transitoires.

3
Maglob

Je travaille sur une base de code complexe depuis plus d'un an maintenant. Voyez si mes idées peuvent vous aider:

Vos idées sont exactes, au moment où vous atteignez une partie différente du code, vous oubliez la partie précédente. Ce peut être un cycle sans fin. La leçon importante à retenir ici est que le produit ne peut pas fonctionner sans que toutes les pièces fonctionnent correctement. Même si une partie échoue, le produit ne fonctionne pas. Voyez-le sous un autre angle: si vous améliorez une pièce de façon spectaculaire, cela NE POURRAIT PAS encore entraîner un meilleur fonctionnement du produit, ce qui est votre objectif principal ici.

Donc, au début: ne soyez pas développeur. Soyez testeur.

N'essayez pas de comprendre partie par partie. Comprendre l'ensemble du produit et son fonctionnement lorsque toutes les pièces sont réunies. Dans un environnement de production (c'est-à-dire un environnement sans développement - pas de points de débogage), testez le produit. Ensuite, comme tous les testeurs, enregistrez les problèmes que vous rencontrez dans un outil de suivi des bogues. Attribuez-lui la gravité et la priorité. Comme ce logiciel existe depuis un certain temps, voyez s'il y a déjà un tracker de bug créé. S'il y en a déjà un, vous avez de la chance. Ajoutez à ceux-ci et prenez le temps et vérifiez chacun des existants. À la fin de ce cycle, vous comprenez le produit d'un point de vue utilisateur (vous ne devriez certainement pas le manquer) et également d'un point de vue QA. En temps voulu, vous pourriez même vous rendre compte qu'une ligne de code corrigera le bogue, et ceux qui l'ont codé ne l'ont pas fait car il n'y avait pas vraiment de besoin à l'époque.

Deuxième étape: portez votre cape de créateur

Divisez le produit en plusieurs parties (pas littéralement ou selon votre convenance, mais selon la façon dont elles fonctionnent ensemble). Peut être votre travail jusqu'à maintenant ou les connaissances existantes pourraient entrer en jeu. Ensuite, essayez de comprendre comment ils fonctionnent les uns avec les autres ainsi qu'avec les 10 bibliothèques dépendantes. Ensuite, pour chaque bug suivi, écrivez vos notes identifiant les entités de code (par exemple: ce changement implique de modifier les classes X, Y, Z, etc.). Probablement, à la fin de cette étape, vous aurez QUELQUES conseils sur les problèmes de l'architecture actuelle et ce qui peut être amélioré.

Ensuite, vous pouvez décider si l'architecture/la conception actuelle est suffisante et vous pouvez continuer à améliorer le logiciel OR si le produit a besoin d'une meilleure conception ou de modifications dans la conception existante.

Château de cartes

De plus, comme les produits complexes sont livrés avec beaucoup de code, nous pourrions ne pas être en mesure de ramasser quelques éléments et de les modifier ou de les améliorer. C'est parce que tout le système peut être entrelacé de telle manière que le changement dans l'une des classes équivaut à changer la position d'une carte dans un château de cartes, vous ne savez jamais quelle extrémité pourrait casser. D'après mon expérience, cela a été vrai. J'ai choisi une partie, amélioré son code, ignorant les contrats qu'elle avait avec d'autres parties du code et j'ai fini par abandonner le code et réaliser mon erreur. Donc, au lieu d'essayer de comprendre les parties, essayez de comprendre que c'est un tout.

Priorisez vos préoccupations

Vous devez garder à l'esprit ce que vous essayez d'améliorer:

Voulez-vous que le produit soit plus rapide?

Bien sûr, vous le faites. Mais est-ce le premier des soucis? Est-ce lent? Si oui, créez des critères de performance, identifiez les goulots d'étranglement et améliorez ces pièces. Testez à nouveau.

Voulez-vous améliorer la convivialité?

Ensuite, c'est à peu près le côté API/UI.

Voulez-vous améliorer la sécurité?

Ensuite, ce sont les limites que vous devriez explorer.

Je n'ai fourni que 3 exemples, mais il y en a beaucoup plus à rechercher.

Dernière et meilleure documentation

J'ai lu ici dans l'un des articles que la documentation la plus récente et la meilleure est le code lui-même. Même si vous créez une bonne quantité de documentation aujourd'hui, c'est de l'histoire après un certain temps. Le code est donc votre dernière documentation. Donc, chaque fois que vous parcourez du code, écrivez votre compréhension dans les commentaires. Lors du passage de la base de code, avertissez-les de ne pas dépendre UNIQUEMENT des commentaires!

3
Sundeep

Lié à this . Mais avec l'ajout d'un composant Lignes de code. Et en passant, 46000 lignes de code est une application de taille moyenne d'après mon expérience.

1
NWS

Quelques stratégies:

  • Créez un diagramme d'héritage. Il y a outils qui le feront pour vous, mais même le dessiner à la main pourrait être utile.

  • Sur les 200 classes, vous constaterez probablement qu'une douzaine sont vraiment importantes. Ce seront les classes proches de la racine de l'arbre d'héritage. Les autres seront des variations sur un thème, et une fois que vous saurez ce que font leurs superclasses, vous aurez une assez bonne idée du fonctionnement de toutes ces classes de feuilles.

  • Prendre des notes. L'utilisation d'un wiki peut être utile ici. Finalement, vous pourriez transformer certaines de vos notes en une meilleure documentation que celle qui existe actuellement.

  • Dessinez des diagrammes des objets qui sont créés et comment ils sont liés les uns aux autres.

  • Utilisez un débogueur pour parcourir les sections que vous ne comprenez pas.

  • Utilisez un outil de profilage pour trouver des problèmes de performances sans trop vous soucier de ce qui se passe exactement dans le code. Mettez simplement l'application à l'épreuve pendant que vous enregistrez des mesures de performances. Savoir où l'application passe la plupart de son temps peut a) vous donner un aperçu de son fonctionnement et b) suggérer des domaines à améliorer sans que vous ayez besoin de comprendre chaque détail.

1
Caleb

tl; dr: Écrire des documents, écrire des tests. Transformez la compréhension en création.

Version complète:

Il n'y a pas si longtemps, j'ai moi aussi commencé à travailler sur des projets existants pour la première fois dans une entreprise et j'ai dû me mettre rapidement au courant.

J'ai trouvé que tous les projets souffrent invariablement du problème très grave: documentation et tests insuffisants. C'est très mauvais du point de vue de la réussite du projet.

  • Élevé facteur de bus . Peu de gens comprennent vraiment comment les choses fonctionnent, à l'exception peut-être d'un développeur principal qui est affecté à un projet.

  • La communication est difficile car il n'y a pas d'image d'architecture commune à laquelle on puisse se référer. Il est difficile de prendre des décisions éclairées d'amélioration de l'architecture.

  • C'est dur pour les gens. Les nouveaux arrivants ont du mal à comprendre un programme.

Donc, ce qui a fonctionné pour moi, c'est de transformer la compréhension en la fabrication .

  • S'il y a une tâche particulière que je dois faire dans un nouveau projet, je m'y prendrais de la manière qui me permettrait de recueillir le plus d'informations sur le système.

  • S'il n'y a pas de tâche, mais "juste" une compréhension globale est requise (ce qui semble être votre cas), alors j'écrirais de la documentation.

Rédaction de documentation pour acquérir une compréhension générale

J'ai trouvé qu'il était difficile de faire comprendre au cerveau des systèmes abstraits complexes. Cependant, la même compréhension vient facilement si vous faites quelque chose (cela est probablement en quelque sorte lié au concept de "flux").

C'est une sorte de hack. Je pense que la plupart des gens aiment faire des produits de qualité et sont fiers de leur travail, vous pouvez donc faire de la documentation le produit final. Vous apprendrez de nouveaux outils (système de documentation comme Sphinx, par exemple) et résolvez des problèmes difficiles sur la façon de transmettre votre compréhension, au fur et à mesure qu'elle émerge, au public cible. Vous aurez un produit final à montrer à vous-même et aux autres, et les gens vous remercieront plus tard, ce qui est une grande motivation.

N'oubliez pas la méta-documentation: c'est frustrant quand vos documents deviennent obsolètes car les autres ne prennent pas la peine de les mettre à jour. Documentez brièvement le flux de travail de développement: versionnage, test, documentation et guide de style de codage, etc.

Tests d'écriture

Si j'avais une tâche particulière à portée de main - nouvelle fonctionnalité ou correction de bogue - j'écrirais d'abord un test pour cela.

Pour écrire un test, je dois comprendre comment fonctionne la suite de tests et la mettre en place. Ce n'est généralement pas évident, alors je le documente brièvement. La suite de tests a souvent beaucoup de ses propres problèmes comme les tests unitaires et les tests d'intégration tous mélangés, donc je note également les idées sur la façon de le résoudre plus tard. Parfois, la suite de tests ne fonctionne pas ou tous les tests échouent, alors je le corrige. Il y a des cas où la suite de tests est totalement absente, ce qui est une chance d'apprendre à en configurer une.

J'écris ensuite un test. Si c'est une tâche importante, j'écris d'abord un test "d'intégration" de haut niveau. Lors de l'écriture de tests unitaires, la première tâche consiste à déterminer quelle (s) unité (s) devrait implémenter les fonctionnalités nécessaires. Cela vous donnera une bonne compréhension de l'architecture. Après cela, il est facile d'écrire le code implémentant la fonctionnalité.

L'écriture d'un test peut devenir une tâche plus importante que la mise en œuvre d'une fonctionnalité ou la correction d'un mais. Cependant, c'est gratifiant plus tard. Une fois qu'il existe une suite de tests solide, vous (ou d'autres développeurs) pouvez en apprendre beaucoup en essayant d'améliorer les choses au hasard et de voir si les tests réussissent.

1
Anton Strogonoff