vendredi 14 octobre 2005, 18:11
Vous avez dit « Coding Style » ?
Pourquoi est-ce utile ?
D'abord, quel est l'interet de mettre en forme son code ? La lisibilité ! Un code bien mis en forme est plus facile à lire, à comprendre, et donc à maintenir.
Ensuite, quel est l'interet d'avoir une même convention pour tout un projet ? Encore la lisibilité ! Si chaque développeur présente son code comme il l'entend, l'intégration risque de se faire dans la douleur. Les différents morceaux seront difficiles à lire, les noms des variables seront surement incohérents (avec risque de doublons), etc.
Enfin, quel est l'interet de rédiger un document ? Pouvoir entrer dans les détails. En effet, si on peut se mettre d'accord sur les grandes lignes (indentation notamment) par oral, cela devient plus difficile dès qu'on décide d'entrer dans les détails ; et croyez moi, certains Coding style sont tellement détaillés qu'ils vous imposeraient presque la couleur du caleçon...
Voyons maintenant les points essentiels de toute bonne convention de codage qui se respecte.
Conventions de nommage
La façon de nommer les variables et les fonctions (identifiers en anglais) est sans aucun doute le point le plus important d'un projet - et pourtant pas le plus médiatique. En effet, de bonnes règles de nommage permettront la plupart du temps de connaitre en un seul coup d'oeil certaines caractéristiques (au choix : type, portée (globale, locale, publique, privée, ...), appartenance, dépendance, etc.) et de savoir à coup sûr comment nommer une variable selon le contexte. A l'inverse, aucune règle amenera immenquablement à des noms de variables sans aucune logique (toto
, tata
et compagnie), et provoquera à coup sûr des erreurs parfois difficiles à detecter (exemple : Ah merde, je suis en train de détruire une variable globale là !
).
Sur la mise en forme seule, il existe un grand nombre de possibilités, revelant plus du goût qu'autre chose :
- Jouer sur la casse (Case en anglais) :
miniscules
,MAJUSCULES
,MixedCase
oumixedCase
; et quid des abrévations, faut-il écriretrainSNCF
outrainSncf
? (désolé pour la SNCF, c'est le seul exemple qui m'est venu à l'esprit :) - Utiliser le caractère underscore « _ » :
liste_double
- Retirer les voyelles, ou les espaces :
lst
(liste) - Plus généralement, utiliser des variables courtes,
cptList
, oudes_variables_explicites
?
Là où ça devient interressant, c'est d'associer une mise en forme à un contexte. Par exemple, voici les conventions que j'utilise pour un projet de C++ :
- Les variables globales et les macros en
MAJUSCULES
. - Les variables locales en
minuscules_avec_des_underscores
et un nom explicite. - Les variables internes à une classe finissent par un
underscore_
. - Les variables statiques dans une classe commencent par un
_underscore
. - Les fonctions membre d'une classe sont
enMixedCase
avec une minuscule au départ. Les abréviations sont également en minuscule (sauf la première lettre si besoin). - Les fonctions non-membres sont précédée du nom du modules si aucun namespace, et en mixed case, comme ça :
module_mixedCase
ounamespace::mixedCase
. - Les classes sont en
MixedCase
avec une majuscule au départ.
Quelques styles célèbres
A vrai dire, le seul style que je connaisse qui porte un nom est le style hongrois (Hungarian notation) qui consiste à préfixer les variables par des lettres indentifiant leur type. Par exemple : ulToto
est une variable de type unsigned long (int)
. Même si la démarche peut sembler interessante, elle s'avère à l'usage peut pratique et peut lisible. Personnellement je la déconseille.
Quelques liens :
- Une page présentant différents style de nommage.
- La page wikipedia sur les conventions de nommage.
Indentation
- Indentation
- Disposition particulière du texte d'un programme faisant apparaître des décalages de la marge dans l'écriture des divers blocs d'instructions.(source : Le Petit Robert)
L'indentation concerne non seulement la manière de décaler les blocs d'instructions, mais aussi le placement des accolades (ou autre élément délimiteur de bloc). Autant pour le nommage des variables il est facile de faire un peu ce qu'on veut et d'être spécifique à chaque type de programme, autant là, il vaut mieux se rallier à un camp existant ; d'une part parceque tout a déjà été inventé, et d'autre part parceque ça demande moins de temps d'adaption aux nouveaux développeurs.
Attention, l'indentation est un sujet extrêmement trollifère, et il est difficile d'en parler déclancher une guerre de religion. D'ailleurs, je ne vais pas m'en priver !
Quelques styles célèbres
Le K&R, est le style de Brian Kernighan et Dennis Ritchie, les inventeurs du langage C. C'est de loin le plus utilisé et le plus connus (et généralement celui qu'un débutant adopte naturellement). Il est notamment utilisé (avec quelques petites améliorations) pour le kernel Linux. Je ne vais pas y aller par 4 chemins : c'est mon style préféré.
void truc()
{
if (x > y) {
faire_un_truc();
}
fin();
}
Le Linux Kernel Coding Style est disponible dans les sources du noyau linux (dans Documentation/CodingStyle
). Vous pouvez consulter la version disponible dans les sources du kernel 2.6.12.2
Le style GNU, est utilisé (de gré ou de force) pour tous les projets GNU. Dans mon environnement, c'est le deuxième et le seul autre style que je côtoie souvent.
void
truc()
{
if (x > y)
{
faire_un_truc ();
}
fin();
}
Voir le Gnu Coding Style, section Formatting.
Pour plus d'informations sur les différents styles d'indentation, ainsi que les arguments pour et contre chacun, je vous conseille la page Wikipedia.
Trollons un peu : pourquoi utiliser des tabs ?
Pour mettre en retrait du texte, il y a deux écoles : les pro-espaces qui prônent l'utilisation de séquences d'espaces et les pro-tabs qui militent pour l'utisation du caractère « tabulation ». Et la guerre entre les deux fait rage depuis des années. Par exemple, taper les deux mots « indentation tabs » dans Google renvoie plus de 360 000 réponses, avec en des titres comme Tabs versus Spaces, Why I prefer no tabs in source code, Indentation wars end here, Space indentation is morally wrong, etc. Bref, tout un programme ! En ce qui me concerne, j'ai choisi mon camp, celui des tabulations, et je vais vous expliquer pourquoi.
A l'origine (c'est-à-dire au temps des machines à écrire), le caractère tabulation permet de déplacer le curseur jusqu'à un point d'arret marqué sur une réglette (tabstop en anglais). Cela évitait à l'opérateur d'avoir à taper une série d'espace pour aligner des éléments. Tiens donc, « aligner des éléments » ça ne vous rappelle rien ? Aujourd'hui, on retrouve le principe des réglettes et des tabstop dans les logiciels de traitement de texte tels que Microsoft Word ou OpenOffice Writer. La tab (parceque c'est une tabulation) permet par exemple de faire un retrait au début d'un paragraphe.
De manière plus générale, dans tout éditeur de texte moderne, il est possible de choisir la taille des tabs. Concrètement, vous pouvez définir qu'une tab fera 2 caractères ou 4 ou 8 ou autant que vous voulez ! Un seul caractère ASCII permet donc non seulement de remplacer efficacement une série d'espaces (et ainsi d'avoir un fichier plus petit), mais aussi de laisser celui qui consulte le fichier la possibilité de modifier son apparence visuelle par simple réglagle de son éditeur ! Exemple : vous avez un grand écran avec une grande résolution et vous préferez les tabs de 8 caractères ? Pas de problème. Vous passez le fichier à un ami qui a un tout petit écran et préfére des tabs de 2 caractères ? Pas besoin de toucher la moindre ligne du fichier, un simple réglage suffit.
Pour en savoir plus, voici quelques liens très utiles :
- Tabs versus Spaces: An Eternal Holy War : L'auteur est pro-espaces, mais le rappel historique du caractère tabulation est très pertinent.
- La page wikipedia sur le caractère tab.
- Use Tabs in Source Code, ou pourquoi les tabs c'est mieux.
- Tab-size independent source code formatting : Technique ultime d'indentation à base de tab permettant d'être complètement indépendant de la taille paramétrée.
Trollons un peu plus : pourquoi le GNU Coding Style est-il une erreur de la nature ?
Je n'aime pas Richard M. Stallman (RMS). Certes, il a fait énormement pour le libre (c'est l'inventeur de gcc, de la GPL, etc.), mais c'est un intégriste borné qui ne voit malheureusement pas plus loin que le bout de son clavier et qui se permet de donner son avis sur tout et n'importe quoi (oui, comme RAGE2000, cqp). A chaque fois que j'en entend parler, il a encore sorti une connerie plus grosse que lui. Tiens par exemple, la dernière fois il ordonnait à ses fidèles de ne pas acheter les livres Harry Potter (à quand une intifada ?). Et la fois d'avant, il se permettait de juger le projet de Constitution Européenne et d'affirmer que c'était une bonne chose d'avoir voter « non » (c'est un américain, qu'est-ce qu'il y connait ?). Et parmi toute les idioties de RMS, celle qui me pourri le plus la vie au quotidien est son GNU Coding Style...
Première chose : déclarer les fonctions sur deux lignes (ou plus !). Les ayatollah affirment que ça permet de retrouver facilement l'implémentation d'une fonction parmis des centaines de milliers de lignes de code. Explication : il leur suffit de rechercher la ligne commençant directement par le nom de la fonction recherchée. En effet, si on cherche le nom de la fonction simplement, on va tomber, non seulement sur la déclaration, mais également sur tous les appels à ladite fonction. Cet argument est valable, certes, mais on peut tout à fait trouver une astuce similaire pour un autre style, par exemple avec le K&R il suffit de rechercher une ligne contenant le nom de la fonction et aucun caractère « ; », ou bien une ligne contenant le nom de la fonction directement suivie d'une ligne débutant par une accolade... Une autre solution est d'utiliser un IDE moderne, qui permet de se rendre directement à l'implémentation par simple clic. Ah oui, mais ça, contraire à la religion des GNUistes, qui doivent utiliser GNU emacs.
Deuxième chose : les « demi-niveaux » d'indentation ; c'est-à-dire le placement des accolades à mi-chemin entre les deux blocs, comme ceci :
if (x > y)
{
faire_un_truc ();
}
Ce que j'en pense, c'est qu'en plus d'être illisible, ça n'a pas grand interet. Mais bon, je veux bien admettre qu'il s'agit là d'une notion tout à fait subjective ; comme dirait ma grand-mère : Les goûts et les couleurs...
. Alors discutons sur des choses objectives.
Premièrement, est-ce bien moral de « couper » l'indentation en deux, et de créer ainsi ces « demi-niveaux » ? Je ne crois pas. Ca casse l'imbrication et ça perturbe la lecture : la notion de « demi » n'est pas naturelle et on a l'impression que le bloc est en fait 2 niveaux en dessous.
Deuxièmement, la façon d'indenter. Pour créer ces « demi-niveaux », il faut impérativement utiliser des espaces au lieu des tabulations (voir ci-dessus). Cela à 2 inconvenients majeurs :
- Il faut plusieurs caractères « espace » pour imiter un seul caractère « tabulation » ; ça prend plus de place pour le stockage (essayez avec un fichier de quelques centaines de lignes pour voir, la perte peut très vite se compter en kilo-octets), et donc rend la compilation un poil plus longue (parceque fichier plus gros à parser), ainsi que les commits et autre manipulation.
- Les développeurs ne peuvent pas modifier la valeur de l'indentation selon leur goûts (2, 4, 8, ...)
Pour conclure ce petit troll, je vais citer Linus Torvalds (le papa du noyau Linux) : First off, I'd suggest printing out a copy of the GNU coding standards, and NOT read it. Burn them, it's a great symbolic gesture.
(« Avant tout, je vous suggère d'imprimer une copie du GNU Coding style, et de NE PAS le lire. Brulez-le, c'est un grand geste symbolique. »).
Encore plus loin...
Même si ces deux notions (nommage et indentation) sont les plus importantes (et les plus celèbres), il y a bien d'autres point à préciser si on veut rédiger un coding style complet. Parmi celles-ci :
- Les espacements. Faut-il écrire :
m = moyenne(a,b);
oum=moyenne(a,b);
ou encorem = moyenne(a, b);
? - Les noms de fichiers, et l'arborescence du projet. Les noms de fichiers doivent-ils être en miniscules uniquement ? Faut-il faire une classe par fichier ?
- On peut aller encore plus loin, en imposant par exemple un nombre de lignes limite pour les fonctions, un nombre de variable maximum, ou, comme je le disais en introduction, la couleur du caleçon à porter pour coder !
Bref, comme vous avez pu le constater, les standards de codage forment un sujet très vaste et particulièrement... délicat. Les guerres sont nombreuses, très nombreuses, à tel point qu'il est difficile d'en parler sans que ça dégénère (essayer de poser une question sur un forum de geek en postant un morceau de code : à tous les coups quelqu'un va venir vous dire que votre coding style n'est pas bon !). Et encore, là je n'ai survolé que les points les plus connus...
Note : Saviez-vous que, lorsqu'on parle de typographie, on dit une espace ?
Par cgo2, dans Programmation
Commentaires
C'est très joli, haut en couleurs, y'a de l'idée, mais de toute façon, le plus important, c'est d'utiliser un bon éditeur, vim donc.
Salut,
bon j'ai lu assez vite fait l'article (oui j'avoue avoir vu peu d'intérêt à cet article pour des non-programmeurs qui s'en foutent. Quant aux programmeurs, ils connaissent en général tous ces questions). Par contre, je me suis un peu attardé sur ton avis de Stallman.
Et si, je suis assez d'accord sur le fait que parfois il est trop intégriste... ton avis n'est vraiment pas très argumenté pour autant. Car quand je dis trop intégriste, il n'empêche qu'en général, ça ne m'empêche pas d'être tout à fait d'accord avec lui dans le fond. Pour l'affaire HP par ex. Ben j'étais philosophiquement absolument d'accord avec lui. Ca ne m'a pas empêché de lire HP toutefois, car je n'ai toutefois pas la force d'esprit de résister à la suite des ces aventures qui me plaisent. L'erreur de Stallman a été sûrement de mélanger le plaisir d'une oeuvre appréciée, et l'auteur. C'est un point qui a de tous temps fait couler beaucoup d'encre: jusqu'à quel point relier l'auteur et ses oeuvres? Pour ma part par ex, malgré tout le bien que je pense de ces bouquins, je ne peux m'empêcher de penser que Rowling a fait une grosse erreur de "vendre son âme au diable", en se vendant à la Warner (financièrement elle n'en avait même pas besoin, elle était déjà sacrément riche). C'est un sentiment que je ressens d'autant plus qu'elle n'a absolument pas l'air de le regretter. En fait je n'en sais rien de ce genre de choses (elle est peut-être très sympa, ça se trouve, je la connais pas personnellement), mais ce sont les affaires de ce style (l'histoire des livres interdits de lire, ou bien les procédures judiciaires contre les sites de fans, etc.) où non seulement elle n'intervient pas contre la Warner, mais parfois en renfort même, qui me font penser qu'elle se complaît dans cette situation. Enfin voilà, je pense que ce sont des questions aux réponses difficiles à avoir. Et je pense qu'il est évident plus facile de réagir négativement à ce genre d'affaire quand on n'aime pas l'oeuvre comme Stallman, que quand on l'apprécie, comme moi, c'est certain. Cependant il n'empêche que je le comprends tout à fait, et qu'au fond, je pense qu'il n'a pas tort.
Par contre, cracher sur Stallman comme on le voit ici, sans aucune argumentation poussée sinon juste une divergence d'opinion, ça je trouve ça un peu nul. La vie n'est pas si simple pour se limiter au fait d'avoir des avis différents, et je pense que pour en arriver à ainsi dénigrer quelqu'un, il faudrait de profondes raisons. C'est trop facile sinon. Je pense qu'il est plus intéressé de comparer les opinions, et moi je trouve ça bien de donner la sienne comme il le fait.
Au passage, en quoi le fait qu'il soit américain fait qu'il n'a pas droit de donner son avis sur des sujets qui l'intéressent? Notamment des sujets assez proches de ses autres intérêts?
Notamment moi j'étais contre la constitution aussi, suis-je également un gros con? Comme ça, on se connaît pas, mais bon on a pas le même avis, donc c'est comme ça? Je trouve que c'est des visions bien simplistes.
Et même parfois je lis qques articles sur des trucs qui se passent dans d'autres pays que le mien, et j'essaie d'avoir une opinion sur les choses. Ca ne m'empêche pas de pouvoir la faire évoluer, mais on se fait toujours des opinions, qu'on le veuille ou non. Mais comme c'est pas mon pays, j'ai pas le droit de m'y intéresser?
Et pis bon on fait pas tous pareil, moi je trouve ça cool un peu de diversité. Par exemple, non tout le monde n'utilise pas des "IDE modernes" (ce qui implique que tu considères un éditeur comme emacs comme une antiquité?!), désolé. Y en a qu'aiment pas ça, et alors? Ca fait quoi qu'on fasse pas comme toi? Et sinon il n'existe pas qu'emacs comme autre éditeur "pas moderne", y a aussi vim, que j'utilise aussi (comme MsK juste au dessus), et que je préfère à tout ce que j'ai jamais testé! Ben oui, shuis peut-être un homme préhistorique pour toi, shais pas. C'est comme ça, désolé. Et ça m'empêche pas d'aimer beaucoup la philo GNU aussi en plus (comme quoi on n'est pas tous sous emacs! oooh?!) Mais moi au moins je dis "chacun ses choix, chacun ses préférences", et je fais pas chier les autres qui préfèrent autre chose, ni ne crache sur eux.
En voila un long commentaire ! Je vais essayer de répondre à tout...
- Comme je l'ai dis dans l'article "Je *n'aime pas*" RMS, c'est effectivement totalement subjectif, et je ne pense pas avoir besoin de me justifier plus que ça dans un article qui concerne le coding style. Tant pis si tu "trouves ça nul", je pense avoir encore le droit d'exprimer mon avis librement sur mon site web !
- Pour les questions politiques, comment peux-tu juger quoi que ce soit alors que tu n'es pas dans le même pays ni dans la même culture ? L'avis que tu peux avoir est, au mieux, totalement partial, et, au pire, complètement faux. Je trouve anormal qu'un type comme RMS (qui plus est qui ne fait du tout de politique) se permette de donner des consignes de vote.
- Dans l'expression "IDE moderne", moderne signifie : "Qui est, a été réalisé depuis peu de temps et souvent d'une manière différente de ce qui avait été fait précédemment; qui est représentatif du goût dominant de l'époque" ; c'est à dire dans le cas de l'informatique : le mode graphique. Et oui un soft informatique dont la première date de 1976 est une antiquité pour moi, pas seulement en terme de code (je pense qu'il a du être réécrit une bonne demi-douzaine de fois), mais surtout en terme d'ergonomie, puisqu'en 30 ans les choses ont bien évoluées !
En conclusion, je trouve tes commentaires interressants, mais malheureusement un peu hors sujet (le coding style). Si tu souhaites continuer à en discuter, pourquoi ne pas aller sur le forum ?
Salut,
c'était juste pour préciser que j'aime bien le coding style GNU et les espaces pour les tabulations. Afin d'être un peu constructif, voilà quelques points en faveur de ces choix:
Pour les espaces:
- utiliser des espaces permet à un contributeur lambda de visualiser le fichier avec l'identation souhaitée par le programmeur initial (c'est je crois l'argument principal en faveur de cette pratique)
- sur certains outils les tabs se comportent bizarrement. Je sais, on peut tous utiliser une usine à gaz comme visual Studio, mais bon ça ne devrait pas être obligatoire, surtout pour un projet qui diffuse ses sources...
- Au niveau de la navigation dans les sources, les outils GNU comme VIM permettent de se déplacer facilement dans les sources utilisant des espaces au lieu des tabs, on a donc le "meilleur" des deux mondes
Pour le style GNU:
- je le trouve très lisible
- il différencie les fonctions des autres blocs, ce qui facilite (à mon avis) la navigation
- je trouve qu'il sort très bien à l'impression en noir et banc. L'air de rien ça a son importance quand on a des imprimantes laser au bureau. Evidemment Visual Studio et compagine colorisent les sources, mais avoir une version papier ça peut toujours servir
- il est bien intégré aux outils GNU, et on trouve des guides pour le paramétrer facilement. Ca evite de se prendre la tête à paramétrer son outil de ttravail.
Voilà évidemment tout ça n'engage que moi, mais il ne faut pas diaboliser le code GNU non plus. Linus Torvald est bien gentil, mais Linux ne serait pas ce qu'il est sans les outils GNU. En plus il recommande des tabs de 8 caractères, ce que je trouve vraiment laid...
ushu
"- utiliser des espaces permet à un contributeur lambda de visualiser le fichier avec l'identation souhaitée par le programmeur initial (c'est je crois l'argument principal en faveur de cette pratique)"
C'est aussi le principal argument *contre* les espaces. En effet, l'indentation doit être logique (niveau 1, niveau 2, etc.) mais pas "gravée dans le marbre". Si je trouve plus clair d'avoir 8 caractères entre chaque niveau d'identation (parceque j'ai une énorme résolution par exempe), mais que le programmeur, qui lui préfère avoir seulement 2 caractères, a identé avec des espaces, je suis niqué.
Avec les tabulations, chacun règle son éditeur comme il le souhaite, sans que ça change quoi que ce soit à la logique de l'indentation.
"- sur certains outils les tabs se comportent bizarrement. Je sais, on peut tous utiliser une usine à gaz comme visual Studio, mais bon ça ne devrait pas être obligatoire, surtout pour un projet qui diffuse ses sources..."
Faut pas utiliser des éditeurs qui datent de la préhistoire :)
SciTE se comporte très bien avec les tabs.
"- je trouve qu'il sort très bien à l'impression en noir et banc. L'air de rien ça a son importance quand on a des imprimantes laser au bureau. Evidemment Visual Studio et compagine colorisent les sources, mais avoir une version papier ça peut toujours servir"
SciTE est capable d'imprimer très lisiblement en noir & blanc (en utilisant des niveaux de gris, des effets de polices -gras, italique, ...- etc.)
Quant à Linux, on pourrait dire aussi que les outils GNU ne seraient pas ce qu'ils sont sans lui (parceque bon, le Hurd il est gentil, mais il avance pas vite).
Bon déjà, je vois pas pourquoi on pourrait pas avoir une opinion sur ce qui se passe dans un pays qui n'est pas le nôtre. Donc je pense que ce que RMS a dit concernant le TECE était approprié et pas blâmable. Ensuite, le GNU Coding Style n'utilise pas de "demi" niveaux d'indentation. quand on a une instruction à indenter, on indente (par convention, de 2 espaces). Quand il s'agit d'un bloc c'est pareil, on indente (toujours de 2 espaces). Mais quand on a une accollade ouvrante, ben c'est pareil, on indente (toujours de 2 espaces). Et grâce à ça, on voit très bien ce qui va entraîner l'exécution du bloc (première indentation), ainsi que le début et la fin du bloc (deuxième indentation). Et ça pour un développeur, c'est optimal. Et pour finir, utiliser une citation de Linus, ça n'a vraiment aucune valeur. Je rappelle quand même que Linus a dit que changer les interfaces du noyau très souvent c'est une bonne chose, même si ça casse la compatibilité avec tout un tas de programmes utilisant ces interfaces, et que du coup ça force un tas de développeurs à réagir très vite, et pas forcément bien, qu'il a également dit que les micronoyaux c'est nul, alors que des OS comme QNX basés sur des micronoyaux fonctionnent très bien et apportent des avantages non négligeables sur les noyaux monolithiques (je vais pas m'étendre là dessus, c'est pas le sujet), et oui, le Hurd n'avance pas vite, mais bon, si on avait autant de développeur que pour Linux, ça serait très différent hein :-p.
bah on a quand meme le doit de pas aimer stallman, nan!! moi je peux pas blairer non plus torvald (pour un peu les memes raisons que l'auteur cite concernant stallmaniaque, la grosse tete en plus) et ca fait pas de moi quelqu'un de pas fréquentable (quoique, ca, c'est subjectif)... ca me fait trop marrer quand des armées de merdeux te regardent de haut et argumentent "leurs" en te balancant des "bah oui, mais torvald y fait comme ca, lui"
lol avec des branques pareil on à pas finit
et puis on est dans un pays libre, alors on critique qui on veut quand on veut, nan mais, on put encore dire ses opinions sur les gens sans que ca fasse monter les branleurs du coin sur leus grand chevaux que je sâche!
merde après "leurs" j'ai oublié "choix"
Et si chacun écrivait son code comme il veut, passait son source dans "astyle" (voir "man astyle") et s'occupait du vrai problème : coder correctement ?