IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)

Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Commenter son code :
Pourquoi, quand et comment, un excellent tutoriel par benbout

Le , par Benbout

0PARTAGES


Le développeur a tendance à sous-estimer les bienfaits du commentaire. La raison qui se cacherait derrière cet apparent désamour serait bien souvent la même que celui face aux tests unitaires. “C’est chiant”. Oui, peut être, mais d’autres situations sont à prendre en compte. Parfois, c’est la culture de l’entreprise qui tend à laisser de côté le commentaire. On doit assumer la surcharge de travail, respecter les délais, alors on priorise, et on en oublie le bon sens. Nous pourrions passer des heures à théoriser sur la faible utilisation du commentaire. Tout le monde irait de sa petite anecdote croustillante basée sur son expérience en entreprise ou sur ses projets personnels collaboratifs, mais la n’est pas le sujet de ce court article. Mon but est avant tout de rappeler aux développeurs, occasionnels comme professionnels, ce qu’est un commentaire et ce qu’il n’est pas, lui démontrer l’importance de son utilisation, et peut être raviver la flamme entre eux.

Commenter != documenter

Séparons une fois pour toute l’expression documenter de commenter.

Documenter, c’est fournir la description de son application, de tous ses points d’accès publics et de ses dépendances.
Exemples:

  • Tel objet est utilisé pour faire ceci ou cela, telle méthode est utilisée avec N paramètres et retournera ou non tel type de valeur.

  • La bibliothèque X dépend des bibliothèques Y et Z. Il est nécessaire d’utiliser au minimum la version 4.10 de la bibliothèque Y.

  • L’application ne prend pas en charge, dans la version 0.7RC-2, les échanges avec le service X.



La documentation est générée et utilisée aussi bien par le(s) développeur(s) de l’application qu’un éventuel client de l’application. La plupart du temps, on consulte la documentation soit à partir d’outils propre à l’IDE utilisé, soit directement sur un terminal ou sur une application tierce (un browser par exemple).

Commenter, c’est décrire l’implémentation d’une classe, d’une méthode, d’une propriété, ou de toute variable spéciale (et de leurs relations parfois), quand la nécessité ou le besoin de confort l’exigent.
Exemples de commentaires:

  • La méthode Toto fonctionne de telle sorte, elle appelle la méthode Nono et modifie la propriété X qui sera multiplié par 3 si la valeur de X n’excède pas 10.

  • Cette collection peut être vide, et si c’est le cas, la variable Y est réinitialisée.

  • Si cette méthode est utilisée dans tel contexte, alors l’objet assigné à la variable X sera déréférencé et l'événement Z sera levé.

  • Cette méthode implémente le contrat de postcondition X car elle doit respecter la norme Y citée dans la documentation de l’application (cf: link). Contacter X_Z avant toute modification du contrat.

  • Un opérateur implicite est utilisé ici pour telle raison.


Quand doit on commenter

La question qui revient souvent est “quand doit on commenter ?”. J’y ai déjà répondu en partie lors de la description du commentaire. Quand la nécessité ou le besoin de confort l’exigent, tout simplement. Je vous vois venir avec vos haussements d’épaules … et je les comprends. Il est vrai qu’il n’est pas toujours aisé de savoir si le comportement de telle portion de notre code doit être commenté ou non. D’autant que lorsqu’on a pas l’habitude de commenter, on est moins à l’aise pour le faire. Tout comme le vélo, cela s’apprend, et l'intérêt du commentaire, c’est qu’il ne faut pas assimiler le dernier framework à la mode pour apprendre à en faire.

Puisque les exemples sont toujours plus parlant, rien de mieux qu’un code source pour prendre quelques notes. Si vous ne connaissez ni le framework .NET, ni le langage C#, peu importe, cela n’aura aucune incidence pour la compréhension de cet article, j'ai justement choisis ce langage car sa syntaxe c-like est compréhensible de tous. Prenons la classe de la List, l’une des plus célèbres collections d’objets utilisées en .NET.
>> Voir le code source sur le site de Microsoft

La nécessité

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
// Implements a variable-size List that uses an array of objects to store the 
// elements. A List has a capacity, which is the allocated length 
// of the internal array. As elements are added to a List, the capacity 
// of the List is automatically increased as required by reallocating the 
// internal array. 
//  
[DebuggerTypeProxy(typeof(Mscorlib_CollectionDebugView<>))] 
[DebuggerDisplay("Count = {Count}")] 
[Serializable] 
public class List<T> : IList<T>, System.Collections.IList, IReadOnlyList<T> 
{


Pour ceux qui seraient en froid avec la langue de Shakespeare:

“Implémente une liste de taille variable qui utilise un tableau d’objets pour stocker ses éléments. Une liste a une capacité, qui est la taille du tableau interne. Quand un élément est ajouté à la liste, la capacité de la liste est automatiquement augmentée si nécessaire par réallocation du tableau interne.”

Ce commentaire est un commentaire résultant d’un besoin de confort, mais dans ce cas précis, devient une nécessité. En effet, toute classe doit être commentée pour en décrire brièvement le fonctionnement interne. Dans le cas de cette liste, elle utilise un tableau pour son stockage interne et la méthode employée pour assurer sa “dynamicité” se base le plus simplement du monde sur une réallocation. L’information est utile, voire nécessaire pour appréhender la lecture de la classe. Voyez la différence avec la documentation de notre List :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
// Résumé : 
// Représente une liste fortement typée d'objets accessibles par index. // Fournit 
// des méthodes de recherche, de tri et de manipulation de listes. Pour 
// parcourir le code source .NET Framework pour ce type, consultez la 
// Référence Source. 
// 
// Paramètres de type : 
//   T: 
//     Type d'éléments de la liste.


La documentation s’occupe uniquement de décrire l’objet tel qu’il est utilisable par l’utilisateur.

Pour les besoins de cet article, je switch brièvement sur l’un des constructeurs de la classe ArrayList avant de revenir à notre List :

Code c# : Sélectionner tout
1
2
3
4
5
// Note: this constructor is a bogus constructor that does nothing 
// and is for use only with SyncArrayList. 
internal ArrayList( bool trash ) 
{ 
}

Si vous n'êtes pas un habitué du framework .NET, le mot clé internal est un modificateur d’accès. En l'occurrence, cela signifie que notre constructeur ne peut être utilisé que dans cette assembly.
Remarquez le commentaire, sa présence est une nécessité. En effet, SyncArrayList est une classe dérivée de ArrayList. Sans ce commentaire, vous penseriez qu’il s’agit d’un constructeur sans utilité pour notre ArrayList, ce qui est le cas, mais vous ne sauriez pas qu’il est utilisé pour une classe fille qui elle en aura besoin. Vous seriez à même de penser qu’il serait peut être envisageable de le supprimer. Vous décideriez, peut être, par pragmatisme, de vérifier s’il n’y a aucunes références dans le code d’autres classes, car après tout, cela semble étrange à première vue et vous finiriez par tomber sur une référence dans la classe SyncArrayList. Cette réflexion, puis sa recherche associée, serait une perte de temps inutile qui peut être prévenue par un simple commentaire de deux lignes...
Revenons en à notre List.

Le besoin de confort

Code c# : Sélectionner tout
1
2
3
4
5
6
7
8
9
// Adds the given object to the end of this list. The size of the list // is 
// increased by one. If required, the capacity of the list is doubled 
// before adding the new element. 
// 
public void Add(T item) { 
    if (_size == _items.Length) EnsureCapacity(_size + 1); 
    _items[_size++] = item; 
    _version++; 
}

Remarquez qu’ici, l’implémentation de la méthode est brève. Ce code ne nécessite pas à proprement parler d’un commentaire pour en décrire son fonctionnement. Le commentaire* répond ici à un besoin de confort. D’abord, ce commentaire nous rappelle ce que nous savions déjà par la lecture du commentaire de la classe, mais, comme la méthode fait principalement appel à une autre méthode privé dans la classe ( .EnsureCapacity() ), un bref résumé du comportement des deux méthodes est énoncé. Cela nous évite d’aller nous renseigner dans le commentaire de la méthode appelée.

*si le commentaire semble bizarrement mis en page, il s’agit du formatage de google docs, n’y prêtez pas attention.


Parlons taille

Il est déconseillé d’écrire de longs commentaires. Plus les commentaires sont longs, plus ces derniers risquent de distraire le programmeur et de réduire la lisibilité d’un fichier. Il est donc plus ou moins convenu qu’un commentaire ne devrait pas excéder 5 lignes. Cependant, il y a des cas ou il est utile de générer un commentaire long. Ces cas pourraient être les suivants :

  • La méthode / propriété (des accessors) utilise un algorithme complexe qu’il est nécessaire de détailler pour rendre rapidement abordable sa compréhension.
  • La méthode utilise une méthode d’une autre classe, il est alors plus confortable pour le programmeur de comprendre le fonctionnement de l’autre méthode et de son incidence dans la première sans avoir à aller jusqu’à la source de cette méthode et de revenir sur sa feuille de travail pour en tirer un bilan.
  • La méthode a beaucoup de surcharges (au moins 3) et certaines appellent l’une d’entre elles, voire plusieurs. Il est alors plus lisible d’écrire un long commentaire au dessus de la première méthode que de diviser les commentaires pour chaque méthodes surchargées.


Les commentaires spéciaux

De nos jours, la plupart des IDE proposent quelques snippets pour insérer des commentaires spéciaux. Les plus connus sont les TODO et les FIXME. En quoi sont ils spéciaux ?
Les TODO, comme les FIXME, sont des commentaires qui présentent le code non pas tel qu’il est mais tel qu’il devrait, ou devra être. La nuance est subtile mais notable. Ainsi, mélanger des commentaires décrivant l’objet informatique tel qu’il est implémenté, et d’autres, tel qu'il le devrait ou le sera, peut créer des confusions.

Cependant, il faut reconnaître que ces types de commentaires ont le mérite d’exister car peuvent se révéler très utile dans certaines situations. Le programmeur veillera à les utiliser avec parcimonie, et, essaiera de les isoler du reste des commentaires.

Gravé dans le code

Le principal défaut du commentaire, c’est qu’il affirme la vérité, un fait qui ne peut être remis en cause. Le commentaire est une transcription du langage informatique vers le langage naturel, et un code informatique est par essence toujours vrai, sa lecture ne peut pas être soumise à interprétation, seulement à compréhension. De ce fait, cette transcription n'est qu'unidirectionnelle, le langage humain étant lui interprétable.
Le problème étant que, quand le commentaire est faux, il est toujours considéré comme vrai par ses lecteurs, et de la, peut induire un certain nombre d'erreurs en cascade.

Restons toujours sur notre List, car il y a justement un exemple parfait pour illustrer ce que je suis en train de vous énoncer :

Code c# : Sélectionner tout
1
2
3
4
5
6
7
// Constructs a List. The list is initially empty and has a capacity 
// of zero. Upon adding the first element to the list the capacity is 
// increased to 16, and then increased in multiples of two as required 
public List()  
{ 
     _items = _emptyArray; 
}

Dans ce code (qui n'est pas un exemple, et qui a du être corrigé depuis), le commentaire nous informe qu’une liste instanciée avec ce constructeur aura une capacité de 0, et que, lors de l’ajout du premier élément, la capacité sera augmenté à 16, et qu’en suite, elle sera multipliée par deux à chaque fois que le tableau interne sera plein. Pour notre plus grand bonheur, ce commentaire est faux et le code lui dit toujours la vérité :

Code c# : Sélectionner tout
private const int _defaultCapacity = 4;

La capacité de la liste sera en effet de 0, mais lors de l'insertion du premier élément, la capacité sera fixée à 4 et non à 16 :

Code : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
private void EnsureCapacity(int min)  
{ 
	if (_items.Length < min) { 
		int newCapacity = _items.Length == 0? _defaultCapacity : _items.Length * 2; 
		// Allow the list to grow to maximum possible capacity (~2G elements) before encountering overflow. 
		// Note that this check works even when _items.Length overflowed thanks to the (uint) cast 
		if ((uint)newCapacity > Array.MaxArrayLength) newCapacity = Array.MaxArrayLength; 
		if (newCapacity < min) newCapacity = min; 
		Capacity = newCapacity; 
	} 
}

Nous supposons que le programmeur a du écrire le commentaire avant d’oublier de modifier la propriété _defaultCapacity.
Le danger, comme j’ai tenté de le souligner plus haut, est que le commentaire lui sera toujours considéré comme vrai. Il ne peut être remis en question. On peut aussi noter que le code ne semble pas être couvert par les tests, ou que ceux-ci sont eux aussi dépréciés et confirment au programmeur que tout fonctionne pour le mieux dans le meilleur des mondes alors que ce n’est pas le cas. Dans ce cas précis, cela n'entraîne pas d’erreurs en cascade, mais vous savez très bien ce que cela peut induire dans un cadre différent.

Conclusion

Les commentaires sont nécessaires au développement d’une application, et on ne peut pas parler de maintenabilité du code sans y inclure l’importance du commentaire. Que vous utilisiez des tests unitaires et/ou des contrats conditionnels pour vos membres de classe, rien ne peut être plus important que les commentaires dans la prévention de comportements non souhaités dans votre application. Ces derniers renseignent, avertissent, annotent. Ils évitent au programmeur d’aller chercher l’information utile ailleurs, limitent la distraction de l’Homme derrière la machine, focalisent ce dernier sur la feuille de travail et l’accompagne dans l’écriture, l’édition et la factorisation du code. Les commentaires vulgarisent les comportements et les algorithmes. Aucun programmeur ne devrait s’en priver ou en priver ses confrères. Il faut tout de même les utiliser avec parcimonie et veiller à ce qu'ils soient fidèles au code commenté, sinon, cet outils peut devenir plus dangereux qu'utile à son propriétaire.

N’est il pas temps de vous réconcilier avec le commentaire ? Jusqu'où devra-t-il aller pour vous séduire ?

Une erreur dans cette actualité ? Signalez-nous-la !