web-dev-qa-db-fra.com

Comment faciliter la compréhension d'une grande base de code

Supposons que je développe un projet relativement important. J'ai déjà documenté toutes mes classes et fonctions avec Doxygen, cependant, j'ai eu l'idée de mettre des "notes de programmeur" sur chaque fichier de code source.

L'idée derrière cela est d'expliquer en termes simples le profane comment une classe spécifique fonctionne (et pas seulement pourquoi comme le font la plupart des commentaires). En d'autres termes, pour donner aux autres programmeurs une autre vision du fonctionnement d'une classe.

Par exemple:

/*
 * PROGRAMMER'S NOTES:
 *
 * As stated in the documentation, the GamepadManager class 
 * reads joystick joystick input using SDL and 'parses' SDL events to
 * Qt signals.
 *
 * Most of the code here is about goofing around the joystick mappings.
 * We want to avoid having different joystick behaviours between
 * operating systems to have a more integrated user experience, since
 * we don't want team members to have a bad surprise while
 * driving their robots with different laptops.
 *
 * Unfortunately, we cannot use SDL's GamepadAPI because the robots
 * are interested in getting the button/axes numbers, not the "A" or
 * "X" button.
 *
 * To get around this issue, we created a INI file for the most common 
 * controllers that maps each joystick button/axis to the "standard" 
 * buttons and axes used by most teams. 
 *
 * We choose to use INI files because we can safely use QSettings
 * to read its values and we don't have to worry about having to use
 * third-party tools to read other formats.
 */

Serait-ce un bon moyen de rendre un grand projet plus facile à comprendre pour les nouveaux programmeurs/contributeurs? Outre le maintien d'un style de codage cohérent et d'une organisation d'annuaire "standard", existe-t-il des "normes" ou recommandations pour ces cas?

105
Alex Spataru

C'est génial. Je souhaite que plus de développeurs de logiciels prennent le temps et les efforts pour le faire. Il:

  • Déclare en anglais simple ce que fait la classe (c'est-à-dire sa responsabilité),
  • Fournit des informations supplémentaires utiles sur le code sans répéter textuellement ce que le code dit déjà,
  • Décrit certaines des décisions de conception et pourquoi elles ont été prises, et
  • Met en évidence certains des pièges qui pourraient survenir à la prochaine personne lisant votre code.

Hélas, de nombreux programmeurs tombent dans le camp du "si le code est écrit correctement, il ne devrait pas être documenté". Pas vrai. Il existe de nombreuses relations implicites entre les classes de code, les méthodes, les modules et d'autres artefacts qui ne sont pas évidents à la simple lecture du code lui-même.

Un codeur expérimenté peut soigneusement élaborer une conception ayant une architecture claire et facilement compréhensible, évidente sans documentation. Mais combien de programmes comme celui-là avez-vous vu?

141
Robert Harvey

La clé pour travailler avec une grande base de code n'est pas d'avoir à lire la base de code entière pour effectuer un changement. Pour permettre à un programmeur de trouver rapidement le code qu'il recherche, le code doit être organisé et l'organisation apparente. Autrement dit, chaque unité logique dans le code, depuis l'exécutable, la bibliothèque, l'espace de noms, jusqu'à la classe individuelle devrait avoir une responsabilité clairement apparente. Je ne documenterais donc pas seulement les fichiers sources, mais aussi les répertoires dans lesquels ils se trouvent.

Les notes de votre programmeur donnent également des informations sur les décisions de conception. Bien que cela puisse être une information précieuse, je la séparerais de la déclaration de responsabilité (pour permettre au lecteur de choisir s'il veut lire sur la responsabilité de la classe ou sa logique de conception), et la déplacer aussi près de la source qu'elle décrit que possible, pour maximiser les chances que la documentation soit mise à jour lorsque le code est (la documentation n'est utile que si nous pouvons avoir confiance en sa précision - une documentation obsolète peut être pire que rien!).

Cela dit, la documentation doit rester SECHE, c'est-à-dire ne pas répéter des informations qui auraient pu être exprimées en code ou qui ont déjà été décrites ailleurs (des phrases comme "comme l'indique la documentation" sont un signe d'avertissement). En particulier, les futurs mainteneurs seront simplement compétents dans le langage de programmation du projet car ils sont en anglais; paraphraser l'implémentation dans les commentaires (que je vois trop souvent lorsque les gens sont fiers de leur documentation) n'a aucun avantage et risque de diverger de l'implémentation, en particulier si la documentation n'est pas proche du code qu'elle décrit.

Enfin, la structure de la documentation devrait être standardisée à travers le projet afin que tout le monde puisse la trouver (c'est un désordre royal de documents Peter dans le bug tracker, Sue dans le wiki, Alan dans le readme, et John dans le code source ...) .

36
meriton

Je ne suis pas d'accord pour dire que c'est une très bonne approche, principalement en raison de

  1. Lorsque vous refactorisez votre projet, déplacez des méthodes, la documentation se casse.

  2. Si la documentation n'est pas correctement mise à jour, il en résultera plus de confusion que la compréhension du code.

Si vous avez des tests unitaires pour chaque méthode/tests d'intégration pour chaque module, ce serait une auto-documentation plus facile à gérer et à comprendre par rapport aux commentaires de code.

Oui, avoir une structure de répertoire appropriée va certainement aider.

13
Low Flying Pelican

Je suis personnellement fan d'un document de conception de haut niveau - de préférence écrit AVANT tout code - qui donne un aperçu de la conception et une liste des classes et des ressources. Une conception descendante simplifie considérablement les choses - le vôtre pourrait être "moteur de jeu -> matériel -> contrôleurs -> joystick"; ainsi, un nouveau programmeur a dit que "corriger le bouton" a "sur le" contrôleur xyz "saurait au moins par où commencer.

Trop de langages modernes ont tendance à diviser le code en centaines de minuscules fichiers, donc trouver le bon fichier peut être un défi, même pour un projet modéré.

7
DWalker

Si la base de code est grande - j'essaie de fournir une conception document qui cartographie les éléments clés de sa conception et de la mise en œuvre. L'intention ici n'est pas de détailler les classes utilisées, mais de fournir une clé pour le code et la pensée qui est entrée dans la conception. Il donne un contexte global au système, à ses composants et à leur application.

Les éléments à inclure dans le document de conception sont:

  • Architecture d'application
  • Structure de code logique
  • Flux de données
  • Motifs clés utilisés et motivation de leur utilisation
  • Structure de la source du code
  • Comment le construire (cela offre un aperçu des dépendances implicites et de la structure du code source physique)

Suite à cela, la documentation des classes et des fonctions/méthodes doit être complétée selon les besoins. En particulier l'API publique; il doit être clair quels sont les éléments suivants dans chaque cas;

  • Conditions préalables
  • Effets
  • Invariants
  • Conditions d'exception (lancers)
6
Niall

La règle la plus importante que j'ai trouvée pour faciliter la compréhension d'une base de code pour les nouveaux développeurs est n accord parfait coûte cher.

Si les nouveaux développeurs doivent parfaitement comprendre le système sur lequel ils travaillent, cela empêche toutes les opportunités d'apprentissage en cours d'emploi. Je pense que les notes du programmeur sont un excellent début, mais j'irais plus loin. Essayez d'écrire du code qui, s'il était abordé à nouveau, permettrait à un développeur de comprendre ce qu'il fait à la volée, plutôt que de lui demander d'apprendre avant de le faire. De petites choses comme des assertions pour des cas que vous connaissez ne peuvent jamais se produire, ainsi que des commentaires expliquant pourquoi l'assertion est valide, vont un long chemin. Il en va de même pour l'écriture de code qui échoue gracieusement plutôt que pour segfault si vous faites quelque chose de mal.

4
Cort Ammon

J'ai vu de grandes classes avec de la documentation, et après avoir lu la documentation, je n'ai aucune idée de ce que cette classe est censée être bonne et pourquoi quelqu'un l'utiliserait! Et en même temps, j'avais besoin de fonctionnalités et j'étais absolument sûr qu'il devait y avoir une classe pour le gérer, et je ne pouvais le trouver nulle part - car il n'y avait aucune documentation qui me conduisait de ce dont j'avais besoin à la classe je le fais.

Donc la première chose que je voudrais dans la documentation est juste quelques phrases ce qu'une classe fait, et pourquoi je voudrais l'utiliser. Les commentaires de la question initiale se portent plutôt bien à cet égard. Après avoir lu ces commentaires, si j'avais un joystick qui ne fonctionne pas bien parce que je ne peux pas interpréter les valeurs qu'il délivre, je saurais quel code vérifier.

3
gnasher729

Semblable à ce que @meriton a dit, décomposez le code en composants séparés. Encore mieux, décomposez la base de code en packages séparés (JAR, gemmes, œufs, etc.) pour rendre encore plus clair la façon dont les composants sont séparés. S'il y a un bogue, un développeur n'a qu'à trouver le paquet où se trouve le bogue, et (espérons-le) ne le corrige que là. Sans oublier, il est plus facile de faire des tests unitaires et vous bénéficiez de la gestion des dépendances.

Autre solution: réduire la base de code. Moins il y a de code, plus il est facile à comprendre. Remaniez le code inutilisé ou dupliqué. Utilisez techniques de programmation déclarative . Cela demande des efforts, bien sûr, et n'est souvent ni possible ni pratique. Mais c'est un objectif louable. Comme Jeff Atwood l'a écrit: Le meilleur code n'est pas du tout un code

0
Sam Jones