Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

syntaxe et norme de codage

16 réponses
Avatar
3dsman
Salut a tous!
Je suis entrain de cleanner un code que j'ai fait pour qu'il soit
reprenable par d'autres.

j'ai recupéré deux docs sur des regles de notation regulierement utilise
(exemple le p devant le nom d'une variable de type pointeur)
Sauf que sur certains trucs elles sont pas d'accord :-)

les noms des arguments des methodes:
soit premier charactere en minuscule puis chaque debut de mot en
majuscule (ex: methode(int maVariable);)
soit la meme chose mais avec un _ au debut (ex: methode(int _maVariable);)

laquelle de ces deux notation vous semble la plus propre?


dans une de ces docs il y a pour les attributs des classes un "m" en prefixe
(ex: int mVarAbc;
string* mpName;)

l'idee est d'eviter les conflits de nom avec les methodes de la classe
mais pourquoi un "m" ?



Si vous avez des sites ou des ressources (pdf par ex) sur la mise en
forme d'un projet opensource en c++ (syntaxe, regles de nommage ou
d'arborescence, fichiers standards,...) je suis preneur

merci!

10 réponses

1 2
Avatar
Marc Boyer
Le 28-02-2006, 3dsman a écrit :
Salut a tous!
Je suis entrain de cleanner un code que j'ai fait pour qu'il soit
reprenable par d'autres.


Bon courrage.

j'ai recupéré deux docs sur des regles de notation regulierement utilise
(exemple le p devant le nom d'une variable de type pointeur)


Qui est une norme qui ne fait pas l'unanimité (cf Notation Hongroise
sur les archives de ce forum).

Sauf que sur certains trucs elles sont pas d'accord :-)


Et oui ;-)

les noms des arguments des methodes:
soit premier charactere en minuscule puis chaque debut de mot en
majuscule (ex: methode(int maVariable);)


Oui.

soit la meme chose mais avec un _ au debut (ex: methode(int _maVariable);)


Il y a des identifiants commençant par _ qui sont réservés à
l'implémentation. Comme je ne me souviens jamais de la règle,
je n'utilise pas ce _.

laquelle de ces deux notation vous semble la plus propre?


La première, mais c'est un jugement purement personnel.

dans une de ces docs il y a pour les attributs des classes un "m" en prefixe
(ex: int mVarAbc;
string* mpName;)

l'idee est d'eviter les conflits de nom avec les methodes de la classe
mais pourquoi un "m" ?


m = member
Ceci dit, je trouve ça ridicule. Mais là encore, ça n'engage que moi.

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exiter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)

Avatar
Vincent Jacques
Salut a tous!
Je suis entrain de cleanner un code que j'ai fait pour qu'il soit
reprenable par d'autres.

j'ai recupéré deux docs sur des regles de notation regulierement utilise
(exemple le p devant le nom d'une variable de type pointeur)


Si je ne m'abuse, mais faut vraiment confirmer, cette habitude s'appelle
la "Notation Hongroise" et était appliquée par les programmeurs de
Microsoft qui est en train de l'abandonner comme tout le monde.

Mettre un "p" devant les noms de pointeurs, pourquoi pas, mais préfixer
par "n" les entiers, par "sz" les chaines "à la C", par... c'est
rapidement agaçant, et si un jour tu changes le type d'une variable, tu
dois corriger tout ton code, alors que justement, la surcharge des
fonctions et des opérateurs pertmet de ne pas tout ré-écrire si tu n'a
pas préfixé tes variables.

Sauf que sur certains trucs elles sont pas d'accord :-)

les noms des arguments des methodes:
soit premier charactere en minuscule puis chaque debut de mot en
majuscule (ex: methode(int maVariable);)
soit la meme chose mais avec un _ au debut (ex: methode(int _maVariable);)

laquelle de ces deux notation vous semble la plus propre?


Il a été dit ici il y a quelques jours de ne pas utiliser de nom
commançant par "_", parce que le compilateur et les headers en utilisent
et que ça peut donc générer des conflits.

dans une de ces docs il y a pour les attributs des classes un "m" en
prefixe
(ex: int mVarAbc;
string* mpName;)

l'idee est d'eviter les conflits de nom avec les methodes de la classe
mais pourquoi un "m" ?


"member" ? Un bouquin que j'ai lu il y a bien longtemps (plus de ref en
tete) disait :
char MaBelleVariable, *pMaBelleVariable;
class truc
{
char m_MaBelleVariable;
}

Je pense que ce qui compte vraiment pour qu'un code soit lisible est
qu'il soit cohérent. Les programmeurs prendront 10 minutes pour
comprendre la convention de nomage et roulez jeunenesse !

Bonne journée,
--
Vincent Jacques

"S'il n'y a pas de solution, c'est qu'il n'y a pas de problème."
Devise Shadok

Avatar
Fabien LE LEZ
On Wed, 01 Mar 2006 07:55:25 +0100, Vincent Jacques
:

Si je ne m'abuse, mais faut vraiment confirmer, cette habitude s'appelle
la "Notation Hongroise"


Pas tout à fait. L'idée de la notation hongroise est de mettre un
préfixe significatif sur les noms de variables.
Ça a été détourné pour donner un truc assez infect.

http://www.joelonsoftware.com/articles/Wrong.html

Avatar
Herode

m = member
Ceci dit, je trouve ça ridicule. Mais là encore, ça n'engage que moi.

Pas tant que ça. Dans les méthodes dépassant la vingtaine de lignes,

ça permet facilement de savoir qui est une variable membre et qui ne
l'est pas. La question semble en tracasser plus d'un, d'ailleurs, si
j'en juge par le nombre de fois où je vois du code du type :

void MaClasse::tagada() {
[...]
this->maVariable = 654654654;
[...]
}

Avatar
Marc Boyer
Le 01-03-2006, Herode a écrit :

m = member
Ceci dit, je trouve ça ridicule. Mais là encore, ça n'engage que moi.

Pas tant que ça. Dans les méthodes dépassant la vingtaine de lignes,

ça permet facilement de savoir qui est une variable membre et qui ne
l'est pas.


J'avais tendance à croire qu'un bon choix de noms de variables
rendait ce genre d'ambiguité inutile, mais face aux faits,
je m'incline.

La question semble en tracasser plus d'un, d'ailleurs, si
j'en juge par le nombre de fois où je vois du code du type :

void MaClasse::tagada() {
[...]
this->maVariable = 654654654;
[...]
}


Oui, entre this->maVar est m_maVar, je n'ai pas de
préférence nette.
Bon, hormis que this-> est parfois nécessaire dans
certains contextes template si j'ai bien suivit certaines
discussions ici.

Je viens de faire un grep sur mes sources: en effet,
j'utilise parfois this, mais c'est quand un paramètre
à le même nom qu'une variable membre.

Foo::Foo(int size, ...){
if (this->size > size) {...
}
}

Marc Boyer
--
Si tu peux supporter d'entendre tes paroles
Travesties par des gueux pour exiter des sots
IF -- Rudyard Kipling (Trad. Paul Éluard)


Avatar
Loïc Joly
On Wed, 01 Mar 2006 07:55:25 +0100, Vincent Jacques
:


Si je ne m'abuse, mais faut vraiment confirmer, cette habitude s'appelle
la "Notation Hongroise"



Pas tout à fait. L'idée de la notation hongroise est de mettre un
préfixe significatif sur les noms de variables.
Ça a été détourné pour donner un truc assez infect.

http://www.joelonsoftware.com/articles/Wrong.html



Un bémol sur cet article : Si je n'ai rien à dire sur la partie
historique, la partie conseils de programmation me laisse bien plus
dubitatif, voire opposé si on cherche à l'appliquer à un langage où
l'utilisateur peut définir ses propres types.

--
Loïc


Avatar
Fabien LE LEZ
On 1 Mar 2006 08:52:04 -0800, "Herode" :

méthodes dépassant la vingtaine de lignes,


Ça existe, ça ?

Avatar
Fabien LE LEZ
On Wed, 01 Mar 2006 21:20:19 +0100, Loïc Joly
:

http://www.joelonsoftware.com/articles/Wrong.html


Un bémol sur cet article : [...]la partie conseils
de programmation me laisse bien plus dubitatif,


J'avoue que je n'ai jamais envisagé sérieusement de suivre ces
conseils.

voire opposé si on cherche à l'appliquer à un langage où
l'utilisateur peut définir ses propres types.


Reprenons l'exemple de l'article : il faudrait un type "chaîne fiable"
et un type "chaîne non fiable".
En l'absence d'un "typedef" un peu plus souple qu'un #define (i.e. un
machin qui permettrait de définir deux types au même comportement mais
tout de même différentiables[*]), comment proposes-tu d'implémenter
ces deux types ?


[*] J'aimerais bien un système où, étant donné un type A, je pourrais
définir un type B, avec les mêmes membres, une conversion implicite de
A vers B, de B vers A, de A* vers B*, et de B* vers A*, mais tout de
même distincts.

Exemple :

class A { ... };
MonTypeDef A B;

void f (A); // 1
void f (B); // 2
void g (A);
void h (B);

int main()
{
A a;
B b (a);
f (a); // OK, appelle 1
f (b); // OK, appelle 2
g (b);
h (a);
}

En fait, on pourrait presque dire "B hérite de A _et_ A hérite de B".
Mais je digresse, sur un sujet qu'on a je crois déjà abordé ici...


Avatar
Patrick 'Zener' Brunet
Bonjour.

Je réponds à 3dsman
Salut a tous!
Je suis entrain de cleanner un code que j'ai fait pour qu'il soit
reprenable par d'autres.

j'ai recupéré deux docs sur des regles de notation regulierement
utilise (exemple le p devant le nom d'une variable de type pointeur)
Sauf que sur certains trucs elles sont pas d'accord :-)

les noms des arguments des methodes:
soit premier charactere en minuscule puis chaque debut de mot en
majuscule (ex: methode(int maVariable);)
soit la meme chose mais avec un _ au debut (ex: methode(int
_maVariable);)

laquelle de ces deux notation vous semble la plus propre?


dans une de ces docs il y a pour les attributs des classes un "m" en
prefixe (ex: int mVarAbc;
string* mpName;)

l'idee est d'eviter les conflits de nom avec les methodes de la classe
mais pourquoi un "m" ?



C'est un sujet récurrent et pour lequel il n'y a pas de règle absolue, tout
est une question de contexte.
Donc je vous répond pour partager mon expérience, mais vous allez voir qu'il
y aura de toute manière des pour et des contres.

I) Le code indéfiniment manipulable par des générations de développeurs
=============
C'est une utopie. Le code est homogène lorsqu'il y a **une** personne qui
met ses pattes dedans, sinon il se dégrade forcément.

J'ai fait des projets où on était (seulement ) 5 sur un jeu de codes. On a
dû (qualité oblige) rédiger une norme de codage. Ca a pompé beaucoup de
temps et personne n'a été capable de s'y tenir à la lettre tellement c'était
anti-naturel (2 SSII différentes + la boîte donneur d'ordre).

J'ai aussi eu à adapter du code "patrimonial" et je connais le coût de ce
type d'opération. Elle se justifie toujours par les deux mêmes raisons:
- documentation obsolète imposant de repartir du code,
- code non modulaire transformant ce qui aurait pu être une substitution de
module en chirurgie à coeur ouvert sur un ensemble.

D'où les règles raisonnables suivantes:

1) On découpe en modules fonctionnels et chacun est responsable des siens.

2) On se met d'accord sur les interfaces (headers communs et interfaces type
COM), c'est déjà assez contraignant.

3) Si on doit exceptionnellement intervenir sur le code d'un autre, on se
force à respecter au mieux son standard et ses paramètres (format de
tabulations notamment), et on repère la section pour qu'il puisse repasser
dessus ensuite si ça le gêne. Histoire de limiter l'entropie.

4) On travaille de préférence par modules fonctionnels avec un état livrable
a priori définitif. Le code éternellement en chantier AMHA traduit une
tendance au bricolage. Je ne sais pas pour vous, mais moi je préfère refaire
un module neuf à partir de ses specs que chercher à comprendre et rafistoler
pour la nième fois une vieille tripe. C'est plus long, plus pénible et
souvent plein de surprises.

II) Les normes universelles de codage
===========
Beau sujet d'étude pour un psychologue :-)

Ce qui paraîtra bien pratique à l'un sera insupportable pour un autre et
inversement.

Certains préfèrent économiser sur la frappe et s'entraîner à décoder au vol
les déclarations de variables. D'autres (c'est mon cas) préfèrent que le nom
soit totalement explicite.

Certains préfèrent écrire du code très condensé et le commenter à outrance.
D'autres (c'est mon cas) préfèrent utiliser des tydedefs en cascade et même
des macros définies localement pour que ça se laisse comprendre sans aucun
commentaire superflu.

Certains préfèrent atomiser leur code dans une pléthore de fonctions pour
que leur corps ne dépasse pas 5 lignes. D'autres (c'est mon cas) préfèrent
que les fonctions matérialisent des sections d'algorithmes, même si elles
sont plus longues (mais pas forcément plus complexes).

Certains préfèrent se limiter à la typologie élementaire de C et C++.
D'autres (c'est mon cas) pensent que typedef a une raison d'être et
n'hésitent pas à se doter de toute une panoplie sur mesure de types
génériques ou dédiés à un module.

Certains préfèrent nommer en Français (mais sans les accents). D'autres
(c'est mon cas) le font toujours en Anglais US pour éviter cette forme de
barbarisme imposé (et aussi parce que cette langue est plus performante pour
cette application).

Etc.

AMHA si déjà le bonhomme qui fait le travail est capable d'être à la fois
productif et cohérent, dans la mesure où il va être capable de livrer un
module opérationnel conforme à **un** standard, il est plus intéressant de
lui demander de documenter l'interface externe que de lui imposer de
développer le tout moins efficacement selon un compromis des préférences de
chacun.

Je crois qd'ailleurs ue l'on peut dire que des standards tels que COM
incluent dans leurs objectifs la possibilité d'interconnecter ainsi des
modules en se préoccupant seulement de leur interface externe, laissant donc
un maximum de liberté pour réaliser l'intérieur. Ca marche plutôt bien.

Bien sûr dans une structure durable, on peut avantageusement demander aux
gens qui sont ainsi productifs de révéler leur savoir-faire pour permettre à
ceux qui en ont envie de s'en inspirer, et ainsi arriver par émulation à une
norme maison. A l'échelle mondiale (projets online), ça me paraît illusoire.

On peut aussi imposer une norme stricte, mais il faut alors accepter que son
application se fasse au détriment de l'efficacité. C'est le codage
"administratif".

III) La mise en forme du code
========
Il existe plusieurs standards pour l'indentation, les espacements, le
placement des { } et autres aspects syntaxiques.
Il existe des outils reformateurs qui font ça très bien, pour intégrer un
code "offert" dans un projet, c'est pas mal.
Mais ça ne touche pas aux identifiants, typages, tailles de fonctions et
commentaires, donc à la sémantique.

IV) La sémantique
======
Sans porter atteinte à la fonctionnalité, la seule partie pouvant faire
l'objet d'une norme est le choix des identifiants. On entre dans le
subjectif, mais on peut toujours argumenter objectivement en faveur de
certains choix:

L'Anglais est efficace pour l'informatique, n'utilise pas de caractères
interdits, et sa connaissance est a priori universelle dans ce métier.

Un nom de variable ou de fonction explicite permet normalement d'économiser
un commentaire, or rien ne garantit que les commentaires seront maintenus à
jour, alors que pour le code le compilo fait la police.

On peut raffiner en donnant à ces identifiants des structures nominales,
adjectivales ou verbales conformes à leur sémantique:
CountOfItems, IndexOfItem, etc.
Initial, Final, Maximum, etc.
IsWindowVisible, ComputeDate, etc.

Et c'est là qu'on s'aperçoit qu'il y a des lourdeurs récurrentes qui
pourraient faire l'objet d'un encodage dans les standards de chacun.
Qui par exemple n'a jamais (failli) confondre:
- NbItems (cardinal) avec NoItem (ordinal)
- NoItem (ordinal basé en 1) avec IndexOfItem (indice basé en 0)
... qui sont pourtant 3 honorables entiers liés au même tableau ?

De même, on peut s'interroger sur la sémantique d'un entier "le plus grand
possible" sans plus de précision, ou au contraire "standard et je suppose
que ma mantisse tiendra dedans".
AMHA les trois suivants sont sémantiquement parfaitement distincts:
- int, container requis par exemple par un printf()
- signed int
- unsigned int

De même, si j'ai besoin d'une mantisse 32bits non signée, je veux savoir si
je peux compter dessus ou pas.
Si c'est non pour une plate-forme, alors une fonctionnalité requise n'existe
pas.
Et si on me force à accepter à la place un 64bits, ça peut me gêner aussi en
faisant déborder des structures, donc je veux le savoir aussi.
C'et pourquoi je réclamerai volontiers un U32 plutôt qu'un "unsigned long"
... J'imagine que pour avoir 128 bits il me faudra demander un "unsigned
long long long" ? Navré mais j'ai un petit faible pour U128 :-D

Pour ce qui est du polymorphisme permettant ensuite de changer globalement
le typage d'une telle donnée, et donc justifiant de ne pas faire de telles
considérations, AMHA ça s'applique surtout aux objets (type "class") et aux
paramètres de templates d'objets, mais même en C++, les autres types ont
encore un rôle essentiel à jouer. On ne peut quand même pas mouliner du heap
sans jamais se poser de questions.

Ben voilà, on pinaille et on se rend compte que s'ils sont bien choisis, les
préfixes devant un identifiant capitalisé peuvent pas mal éclairer à la
relecture du code (quand vous accédez à un champ d'une structure par
exemple).

Mais je comprends très bien que d'autres personnes fassent d'autres choix
selon leur mode de travail...

Donc 3dsman, vous dites que vous voulez "cleaner votre code pour qu'il soit
reprenable par d'autres".

Ca veut déjà dire que vous l'avez fait fonctionner par bricolages successifs
sans impératif initial de propreté ?
Dans ce cas c'était une maquette pour valider un principe, maintenant vous
êtes bon pour développer proprement la version définitive à partir du
principe validé, pas du code d'essai :-)

Repris par d'autres ? Si j'en crois mon expérience, vous avez trois
possibilités à envisager:

1) S'il constitue un module fonctionnel (et pas une tranche d'un truc
monolithique) et s'il est documenté extérieurement, alors il pourra être
réutilisé sans aucune modification interne => pas de reprise de code.

2) S'il contient des techniques de codage innovantes ou astucieuses,
certains pourront vouloir s'en inspirer pour d'autres développements. Donc
ils vont le lire pour trouver la partie en question. => pas de reprise non
plus.

3) Sinon votre code va se rajouter à la montagne de grand bazar que l'on
peut trouver dans beaucoup de structures et aussi sur le Web, dans le genre
"j'ai ça dans un coin, si ça peut te servir", et il y a peu de chance que
quelqu'un ait le courage de fouiller dans un tel volume pour voir s'il y a
quelque chose qu'il pourrait reprendre directement. Tout au plus il va
procéder comme en 2) puis poubelle.

Et vous-même d'ici un an ou deux vous allez vous retrouver exactement dans
la même situation devant votre propre code. J'ai chez moi des dizaines de Mo
de code source validé, et je peux vous le dire: les choses que je réutilise
hors contexte sont de type 1). Pour le type 2) c'est seulement du
"savoir-faire temporairement mis de côté".

Mais donc tout ceci ne représente qu'un partage d'expérience.

Cordialement,

--
/***************************************
* Patrick BRUNET
* E-mail: lien sur http://zener131.free.fr/ContactMe
***************************************/

Avatar
3dsman
en fait mon soft est plus une base d'interface graphique donc les
eventuels codeurs exterieurs n'auraient pas ou peu a retoucher le code
existant.
J'ai commente tout ca et je genere une doc avec doxygen.*
J'ai developpe ce soft en decouvrant au fur et a mesure des normes de
codage et de mise en page.
Mon code est relativement propre (enfin je crois) mais on m'as fait la
remarque qu'on dirait qu'il a ete ecrit par plusieurs personnes :-)
J'essaye donc d'homogeneïser tout ca.
Au niveau des noms de variables, des noms de methodes, de classes,...

Si ca ne vous derange pas quand il sera un peu plus propre je vous
mettrais une copie sur mon site pour que vous me donniez votre avis.
1 2