Comment rendre une grande base de code plus facile à comprendre

104

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 une "note du programmeur" sur chaque fichier de code source.

L'idée derrière ceci est d'expliquer en termes simples comment une classe spécifique fonctionne (et pas seulement pourquoi, comme le font la plupart des commentaires). En d'autres termes, 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 de répertoires «standard», existe-t-il des «normes» ou des recommandations pour ces cas?

Alex Spataru
la source
32
Sûrement pas. Si votre code est illisible, la documentation ne vous aidera pas.
Telastyn
35
@ jeffo - le problème est que prendre le temps de faire cela peut arriver une fois. Le temps nécessaire pour garder le code lisible se produit avec le temps. Je suis allé dans des endroits avec ce type de documentation, réalisée lorsque le projet était jeune ou lorsque Joe le perfectionniste faisait encore partie de l'équipe. Il a ensuite été abandonné et les commentaires ont traîné, pas plus précis.
Telastyn
25
À un niveau plus élevé au moins, une description en prose non codée de ce que fait un projet, de son fonctionnement et des compromis qui ont été faits dans l’architecture est inestimable. Ce type de document est une lecture incontournable pour tout nouveau venu avant de faire un tour de code. Il y a beaucoup de conneries sur le net que ma méthodologie est trop radicales pour docs-mec, et s'il est vrai qu'un doc original et un doc évolutif ne seront pas alignés, une description en prose est nécessaire. pour quiconque de saisir rapidement une base de code volumineuse et non triviale. Voici un exemple (pauvre): zxq9.com/erlmud/html/001-002_architecture.html
zxq9
11
@Telastyn: Cela n'a rien à voir avec le fait que le code soit lisible ou non (et j'espère que c'est le cas). La documentation de la conception est absolument importante.
Courses de légèreté en orbite
7
@Telastyn: Ouais, peut-être. Personnellement, je l'écrirais dans un doc autonome. Mais les blocs de commentaires en haut des fichiers sources ne sont pas si mauvais.
Courses de légèreté en orbite

Réponses:

140

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

  • Exprime en anglais clair ce que la classe fait (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 les raisons pour lesquelles elles ont été prises.
  • Met en évidence certains des pièges qui pourraient arriver à la prochaine personne lisant votre code.

Hélas, beaucoup de programmeurs tombent dans le camp de "si le code est écrit correctement, il ne devrait pas être nécessaire de le documenter". 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 évidentes à la lecture du code lui-même.

Un codeur expérimenté peut concevoir avec soin une conception ayant une architecture claire, facilement compréhensible et évidente sans documentation. Mais combien de programmes de ce genre avez-vous réellement vus?

Robert Harvey
la source
15
Et pourquoi le "Mois de l'homme mythique" devient une prophétie auto-réalisatrice, personne n'a pris le temps d'écrire tout cela pour le nouveau dev quand cela lui revenait à l'esprit et que le projet ne prenait pas de retard.
JeffO
3
Je suis d'accord avec chaque point que vous faites ici. Je n'aime pas le terme OP utilisé dans son message how a class works. Cela change avec le temps et la maintenance. Bien que mon équipe ne mette pas ce qui précède dans la source. Nous maintenons un wiki avec les décisions et copions la discussion brute sur les décisions de conception brutes dans un document (nous fournissons un lien entre le résumé de la décision et la conclusion vers les notes brutes afin de ne pas avoir à modifier les anciennes décisions). Tout se fait parfaitement dans github (donc tout est au même endroit).
Martin York
1
Mon seul problème est d’appliquer cela globalement. Cette classe est assez complexe, avec certains pièges disponibles, il est clair que c'est vraiment utile (même si vous finissez toujours par avoir affaire à Comment Rot). Quand une classe est plus évidente, le commentaire peut être un peu superflu.
deworde
1
"Un codeur expérimenté peut concevoir avec soin une architecture claire, facile à comprendre et évidente sans documentation. Mais combien de programmes de ce type avez-vous réellement vu" Bien que cela soit vrai, la qualité de la documentation n'est jamais meilleure que celle de le code. Le code bien architecturé a tendance à avoir une bonne, voire inutile, documentation. Le code mal architecturé a des commentaires comme "increment x by 1"
deworde
3
Je suis tout à fait d'accord avec cette réponse et si je trouvais quelque chose comme l'exemple du code OP dans le code, je serais tellement heureux. Un simple ajout: envisagez d’ajouter une date à votre commentaire, pour donner un indice aux lecteurs éventuels quant à la fraîcheur de la description et la mettre à jour à chaque fois que vous mettez à jour le texte.
Svalorzen
36

La clé pour travailler avec une base de code volumineuse n’est pas obligée de lire la totalité de la base de code pour apporter une modification. Pour permettre au programmeur de trouver rapidement le code qu'il recherche, le code doit être organisé et l'organisation apparente. C'est-à-dire que chaque unité logique dans le code, de l'exécutable à la classe, en passant par la bibliothèque, l'espace de noms, doit avoir une responsabilité clairement apparente. Je voudrais donc non seulement documenter les fichiers source, mais aussi les répertoires dans lesquels ils se trouvent.

Les notes de votre programmeur donnent également un aperçu des 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 souhaite lire la question de la responsabilité de la classe ou de sa logique de conception), et de la déplacer aussi près que possible de la source décrite. dans la mesure du possible, pour maximiser les chances de mise à jour de la documentation lorsque le code l’est (la documentation n’est utile que si nous pouvons nous fier à son exactitude - une documentation obsolète peut être pire que rien!).

Cela dit, la documentation doit rester sèche, c'est-à-dire ne pas répéter les informations qui auraient pu être exprimées en code ou déjà décrites ailleurs (des expressions telles que "comme l'indique la documentation" sont un signe d'avertissement). En particulier, les futurs responsables seront simplement compétents dans le langage de programmation du projet, car ils le sont en anglais; Paraphraser l'implémentation dans les commentaires (ce que je vois trop souvent quand 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 doit être normalisée dans tout le projet pour que tout le monde puisse la trouver (c'est un fouillis royal de documents de Peter dans le suivi des bogues, de Sue dans le wiki, d'Alan dans le readme et de John dans le code source ...). .

meriton - en grève
la source
Votre première phrase est exactement comment je vois cela. Les grandes bases de code doivent être composées d'un certain nombre de composants plus petits dans lesquels un nouveau programmeur peut changer de manière fiable sans mettre en danger les autres.
Jon Chesterfield
1
déplacez-la aussi près que possible de la source décrite, afin de maximiser les chances que la documentation soit mise à jour lorsque le code le sera . C'est une expérience précieuse.
laike9m
DRY comme guide pour la documentation est un très bon point! Cela règle automatiquement le focus correctement et interdit les commentaires odieux "// incrémente x de 1".
Hans-Peter Störr
13

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 rompt.

  2. Si la documentation n'est pas correctement mise à jour, la confusion sera plus grande 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épertoires appropriée va certainement aider.

Pélican volant à basse altitude
la source
+1 pour les tests étant le meilleur moyen de comprendre une base de code. Les tests unitaires, les tests d'intégration, les tests d'acceptation racontent tous l'histoire de la manière dont l'application est censée fonctionner et de la manière dont elle est censée être utilisée.
BZink
7

Je suis personnellement fan d'un document de conception de haut niveau - de préférence écrit AVANT n'importe quel code - qui donne une vue d'ensemble de la conception et une liste de classes et de ressources. Une conception descendante simplifie énormément les choses - le vôtre pourrait être "moteur de jeu -> matériel -> contrôleurs -> joystick"; ainsi, un nouveau programmeur a déclaré "le bouton" Fixer le bouton "a" sur le "contrôleur xyz" permettrait au moins de savoir par où commencer.

Trop de langues modernes ont tendance à diviser le code en des centaines de petits fichiers. Il peut donc être difficile de trouver le bon fichier, même pour un projet modéré.

DWalker
la source
16
Il y a 20 ans, tout mon code était dans un fichier énorme. Maintenant, il se trouve dans des milliers de petits fichiers et de fichiers de test. Il y a une bonne raison à cela et cela reflète 20 ans de développement logiciel (l'écosystème général, pas ma connaissance). Waaay trop long pour un commentaire cependant.
Michael Durrant
4
ah, l'ancienne méthode d'écriture en cascade d'une vérité, même avant de commencer à coder, ne peut même pas être déviée de la vérité avant qu'elle ne commence à coder.
Jwenting
2
@jwenting: Vous n'avez pas à aller aussi loin. Mais il est toujours bon d’avoir une idée de ce que vous construisez.
Robert Harvey
1
Certes, sans la mise en garde sur la manière de décomposer correctement ces informations et de déterminer les règles à respecter, vous obtiendrez très rapidement un document périmé ou obsolète. "J'ai besoin d'ajouter une nouvelle classe; à Documanto, le Béhémoth qui mange du temps!"
deworde
2
@deworde: J'ai lu cela comme "trop ​​paresseux pour maintenir la documentation".
Robert Harvey
6

Si la base de code est volumineuse, j'essaie de fournir un document de conception qui présente les éléments clés de sa conception et de sa 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 a été prise en compte dans la conception. Il donne un contexte global au système, à ses composants et à ses applications.

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

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

Suite à cela, la documentation pour les classes, ainsi que les fonctions / méthodes doivent être complétées le cas échéant . En particulier l'API publique; les éléments suivants doivent être clairement définis dans chaque cas;

  • Les conditions
  • Effets
  • Invariants
  • Conditions d'exception (lancers)
Niall
la source
+1 Mieux que de décrire chaque classe, car cela va devenir obsolète plus rapidement qu’une conception globale.
Lode
4

La règle la plus importante que j'ai trouvée pour aider les nouveaux développeurs à comprendre une base de code est qu'un accord parfait coûte cher.

Si les nouveaux développeurs doivent parfaitement comprendre le système sur lequel ils travaillent, cela empêche toute possibilité d'apprentissage sur le tas. 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é de nouveau, permettrait au développeur de comprendre ce qu'il fait à la volée, plutôt que de le demander à apprendre avant de le faire. De petites choses comme des assertions pour des cas que vous savez ne peuvent jamais se produire, ainsi que des commentaires expliquant pourquoi l'assertion est valide, vont très loin. Il en va de même pour l'écriture de code qui échoue gracieusement plutôt que de commettre une erreur de segmentation si vous faites quelque chose de mal.

Cort Ammon
la source
Ma règle est que les commentaires devraient être sur POURQUOI , pas COMMENT . Le code décrit COMMENT.
user11393
3

J'ai vu de grandes classes avec de la documentation et après avoir lu la documentation, je n'ai pas la moindre 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 certaines fonctionnalités et j'étais absolument sûr qu'il devait y avoir une classe pour la gérer, et je ne la trouvais nulle part - car aucune documentation ne m'emmenait de ce dont j'avais besoin à la classe. je le fais.

La première chose que je voudrais dans la documentation, ce sont juste quelques phrases de ce que fait une classe et de la raison pour laquelle 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 fonctionnait pas bien car je ne pouvais pas interpréter les valeurs qu’il fournit, je saurais quel code vérifier.

gnasher729
la source
0

Semblable à ce que @meriton a dit, divisez le code en composants distincts. Mieux encore, divisez la base de code en packages distincts (JAR, gemmes, œufs, etc.) pour que la distinction entre les composants soit encore plus claire. S'il y a un bogue, un développeur doit seulement trouver le paquet contenant le bogue et le corriger (espérons-le) uniquement. Sans oublier qu'il est plus facile de faire des tests unitaires et de tirer parti de la gestion des dépendances.

Une autre solution: réduire la base de code. Moins il y a de code, plus il est facile à comprendre. Refactoriser le code inutilisé ou dupliqué. Utiliser des techniques de programmation déclaratives . Cela demande des efforts, bien sûr, et souvent, cela n’est ni possible ni pratique. Mais c'est un objectif louable. Comme l'a écrit Jeff Atwood: Le meilleur code est aucun code

Sam Jones
la source
-1

Pour les systèmes complexes, il peut être intéressant de ne pas documenter chaque fichier, mais également leurs interactions et leur hiérarchie, ainsi que la structure et les raisons du programme.

Par exemple, un moteur de jeu est généralement assez complexe et il est difficile de décider ce qui appelle quoi après cent couches d'abstraction. Il peut être intéressant de créer un fichier tel que "Architecture.txt" pour expliquer comment et pourquoi le code est structuré de la sorte, et pourquoi il existe une couche d'abstraction inutile.

Akaltar
la source
-7

Cela peut être en partie dû au fait qu’il est difficile pour un seul programmeur de l’écrire, car chaque individu ne comprend que sa partie du projet.

Parfois, vous pouvez obtenir ces informations à partir des notes du chef de projet, mais c’est tout ce que vous obtiendrez, car elles réécriront rarement leurs notes dans ce format.

Ilqar Rasulov
la source
7
Si vous regardez github, vous trouverez beaucoup de projets qui ont ce genre de note dans un fichier README.md. Cela fait tellement partie de la culture de git en général et les projets javascript en particulier pour la plupart des gens n'utiliseront pas une bibliothèque qui ne possède pas ce type de documentation de haut niveau. Il est donc faux qu’aucun programmeur n’écrive cela car il suffit de regarder quelque chose comme jQuery ou socket.io et de trouver des programmeurs qui écrivent de telles choses. Il est également devenu une culture selon laquelle les fichiers README qui ne sont pas précis génèrent des rapports de bogues.
Slebetman
1
Cela ne semble pas répondre à la question qui consistait à rechercher les raisons pour lesquelles le style de documentation proposé fonctionnerait ou non, ainsi que les normes de documentation.
user52889
5
Si vous avez une équipe de programmeurs travaillant sur un produit et que chaque programmeur ne comprend que le code spécifique sur lequel ils ont travaillé, votre équipe est non seulement incroyablement dysfonctionnelle avec un facteur de bus absurde, mais elle met en doute la qualité du code. Comment intégrer du code dans un produit sans comprendre le reste du code dans le même système ??!?
Courses de légèreté en orbite