Un grand nombre de code C ++ utilise des conventions syntaxiques pour le balisage des variables membres. Les exemples courants incluent
- m_ memberName pour les membres publics (où les membres publics sont utilisés du tout)
- _ memberName pour les membres privés ou tous les membres
D'autres essaient de forcer en utilisant this-> member chaque fois qu'une variable membre est utilisée.
D'après mon expérience, la plupart des bases de code plus volumineuses ne parviennent pas à appliquer ces règles de manière cohérente.
Dans d'autres langues, ces conventions sont beaucoup moins répandues. Je ne le vois qu'occasionnellement en code Java ou C #. Je pense que je ne l'ai jamais vu en code Ruby ou Python. Ainsi, il semble y avoir une tendance avec les langages plus modernes à ne pas utiliser de balisage spécial pour les variables membres.
Cette convention est-elle encore utile aujourd'hui en C ++ ou est-ce juste un anachronisme. D'autant plus qu'il est utilisé de manière incohérente dans les bibliothèques. Les autres langues n'ont-elles pas montré que l'on peut se passer de préfixes de membre?
la source
self._something = 1
.this->member
dans le code Python. En Python, ce serait généralement le casself.member
et ce n'est pas seulement une convention, cela est requis par le langage.Réponses:
Vous devez faire attention à l'utilisation d'un trait de soulignement en tête. Un trait de soulignement avant une majuscule dans un mot est réservé. Par exemple:
_Foo
_L
sont tous des mots réservés tandis que
_foo
_l
ne sont pas. Il existe d'autres situations dans lesquelles les traits de soulignement avant les lettres minuscules ne sont pas autorisés. Dans mon cas spécifique, j'ai trouvé que le _L était réservé par Visual C ++ 2005 et que le conflit a créé des résultats inattendus.
Je ne sais pas à quel point il est utile de baliser les variables locales.
Voici un lien sur les identifiants réservés: Quelles sont les règles d'utilisation d'un trait de soulignement dans un identifiant C ++?
la source
Je suis tout à fait en faveur des préfixes bien faits .
Je pense que la notation hongroise (système) est responsable de la plupart des "bad rap" que les préfixes reçoivent.
Cette notation est largement inutile dans les langages fortement typés, par exemple en C ++ "lpsz" pour vous dire que votre chaîne est un long pointeur vers une chaîne terminée par nul, quand: l'architecture segmentée est une histoire ancienne, les chaînes C ++ sont par convention commune des pointeurs vers une terminaison nulle char, et ce n'est pas vraiment difficile de savoir que "customerName" est une chaîne!
Cependant, j'utilise des préfixes pour spécifier l' utilisation d'une variable (essentiellement "Apps hongrois", bien que je préfère éviter le terme hongrois car il a une association mauvaise et injuste avec le système hongrois), et c'est un gain de temps très pratique et approche de réduction des bogues .
J'utilise:
Là où je souhaite rendre le type clair, j'utilise des suffixes standard (par exemple, Liste, ComboBox, etc.).
Cela rend le programmeur conscient de l' utilisation de la variable chaque fois qu'il la voit / l'utilise. Le cas le plus important est sans doute "p" pour pointeur (car l'utilisation change de var. À var-> et vous devez être beaucoup plus prudent avec les pointeurs - NULL, l'arithmétique du pointeur, etc.), mais tous les autres sont très pratiques.
Par exemple, vous pouvez utiliser le même nom de variable de plusieurs manières dans une seule fonction: (ici un exemple C ++, mais il s'applique également à de nombreux langages)
Vous pouvez voir ici:
Un autre grand avantage des itérateurs "iName" est que je n'indexe jamais un tableau avec le mauvais index, et si je copie une boucle dans une autre boucle, je n'ai pas à refactoriser l'une des variables d'index de boucle.
Comparez cet exemple d'une simplicité irréaliste:
(qui est difficile à lire et conduit souvent à utiliser "i" là où "j" était destiné)
avec:
(ce qui est beaucoup plus lisible et supprime toute confusion sur l'indexation. Avec la saisie semi-automatique dans les IDE modernes, cette saisie est également rapide et facile)
L'avantage suivant est que les extraits de code ne nécessitent aucun contexte pour être compris. Je peux copier deux lignes de code dans un e-mail ou un document, et quiconque lit cet extrait de code peut faire la différence entre tous les membres, constantes, pointeurs, index, etc. Je n'ai pas besoin d'ajouter "oh, et soyez prudent car "data" est un pointeur vers un pointeur ", car il s'appelle" ppData ".
Et pour la même raison, je n'ai pas besoin de sortir les yeux d'une ligne de code pour la comprendre. Je n'ai pas besoin de rechercher dans le code pour trouver si «data» est un paramètre local, un membre ou une constante. Je n'ai pas besoin de déplacer ma main vers la souris pour pouvoir placer le pointeur sur «données», puis attendre qu'une info-bulle (qui n'apparaît parfois jamais) s'affiche. Ainsi, les programmeurs peuvent lire et comprendre le code beaucoup plus rapidement, car ils ne perdent pas de temps à chercher de haut en bas ou à attendre.
Le préfixe 'm' évite également la notation (IMHO) laide et verbeuse "this->", et l'incohérence qu'elle garantit (même si vous faites attention, vous vous retrouverez généralement avec un mélange de "this-> data" et 'data' dans la même classe, car rien n'impose une orthographe cohérente du nom).
«cette» notation est destinée à résoudre l' ambiguïté - mais pourquoi quelqu'un écrirait-il délibérément du code qui peut être ambigu? Ambiguïté va conduire à un bogue tôt ou tard. Et dans certains langages, «ceci» ne peut pas être utilisé pour les membres statiques, vous devez donc introduire des «cas spéciaux» dans votre style de codage. Je préfère avoir une seule règle de codage simple qui s'applique partout - explicite, sans ambiguïté et cohérente.
Le dernier avantage majeur est avec Intellisense et l'auto-complétion. Essayez d'utiliser Intellisense sur un formulaire Windows pour trouver un événement - vous devez faire défiler des centaines de méthodes de classe de base mystérieuses que vous n'aurez jamais besoin d'appeler pour trouver les événements. Mais si chaque événement avait un préfixe «e», ils seraient automatiquement répertoriés dans un groupe sous «e». Ainsi, le préfixage permet de regrouper les membres, les consts, les événements, etc. dans la liste intellisense, ce qui permet de trouver beaucoup plus rapidement et plus facilement les noms que vous voulez. (Habituellement, une méthode peut avoir environ 20 à 50 valeurs (locales, paramètres, membres, consts, événements) qui sont accessibles dans sa portée. Mais après avoir tapé le préfixe (je veux utiliser un index maintenant, donc je tape 'i. .. '), on ne me propose que 2 à 5 options de saisie semi-automatique.
Je suis un programmeur paresseux, et la convention ci-dessus me fait gagner beaucoup de travail. Je peux coder plus rapidement et je fais beaucoup moins d'erreurs car je sais comment chaque variable doit être utilisée.
Arguments contre
Alors, quels sont les inconvénients? Les arguments typiques contre les préfixes sont:
"Les schémas de préfixes sont mauvais / mauvais" . Je conviens que "m_lpsz" et ses semblables sont mal pensés et totalement inutiles. C'est pourquoi je vous conseillerais d'utiliser une notation bien conçue conçue pour prendre en charge vos besoins, plutôt que de copier quelque chose qui ne convient pas à votre contexte. (Utilisez le bon outil pour le travail).
"Si je change l'usage de quelque chose, je dois le renommer" . Oui, bien sûr que vous faites, c'est ce qu'est le refactoring, et pourquoi les IDE ont des outils de refactoring pour faire ce travail rapidement et sans douleur. Même sans préfixes, changer l'utilisation d'une variable signifie presque certainement que son nom doit être changé.
"Les préfixes me confondent" . Comme tout outil jusqu'à ce que vous appreniez à l'utiliser. Une fois que votre cerveau s'est habitué aux modèles de dénomination, il filtrera automatiquement les informations et cela ne vous dérangera pas vraiment que les préfixes soient plus là. Mais vous devez utiliser un schéma comme celui-ci solidement pendant une semaine ou deux avant de devenir vraiment "courant". Et c'est à ce moment-là que beaucoup de gens regardent l'ancien code et commencent à se demander comment ils ont pu réussir sans un bon schéma de préfixes.
"Je peux juste regarder le code pour résoudre ce problème" . Oui, mais vous n'avez pas besoin de perdre du temps à chercher ailleurs dans le code ou à vous souvenir de chaque petit détail de celui-ci lorsque la réponse est juste à l'endroit où votre œil est déjà concentré.
(Certaines de) ces informations peuvent être trouvées en attendant simplement qu'une info-bulle apparaisse sur ma variable . Oui. Là où cela est pris en charge, pour certains types de préfixes, lorsque votre code se compile proprement, après une attente, vous pouvez lire une description et trouver les informations que le préfixe aurait transmises instantanément. Je pense que le préfixe est une approche plus simple, plus fiable et plus efficace.
"C'est plus typant" . Vraiment? Un personnage entier de plus? Ou est-ce - avec les outils de saisie semi-automatique IDE, cela réduira souvent la saisie, car chaque caractère de préfixe réduit considérablement l'espace de recherche. Appuyez sur "e" et les trois événements de votre classe apparaissent dans Intellisense. Appuyez sur "c" et les cinq constantes sont répertoriées.
"Je peux utiliser à la
this->
place dem
" . Eh bien, oui, vous pouvez. Mais c'est juste un préfixe beaucoup plus laid et plus bavard! Seulement, il comporte un risque beaucoup plus grand (en particulier dans les équipes) car pour le compilateur, il est facultatif , et donc son utilisation est souvent incohérente.m
d'autre part, il est bref, clair, explicite et non facultatif, il est donc beaucoup plus difficile de faire des erreurs en l'utilisant.la source
z
soit très souvent utile dans un langage comme C ++ où ce genre de détail d'implémentation de bas niveau devrait être encapsulé dans une classe, mais en C (où la terminaison zéro est une distinction importante) je suis d'accord avec vous. IMO, tout schéma que nous utilisons doit être adapté selon les besoins pour mieux répondre à nos propres besoins - Donc, si la terminaison zéro affecte votre utilisation de la variable, il n'y a rien de mal à déclarer "z" un préfixe utile.The most important case is "p" for pointer (because the usage changes from var. to var-> and you have to be much more careful with pointers.
Je ne suis pas du tout d’accord. Si j'utilise un mauvais pointeur, il ne se compilera tout simplement pas (void*
peut être une exception pour les pointeurs doubles). Et l'ensemble->
plus.
est suffisant pour me dire qu'il est un pointeur. De plus, si vous utilisez la saisie semi-automatique, votre éditeur a probablement des info-bulles de déclaration, ce qui élimine le besoin de préfixer les informations de variable. Quoi qu'il en soit, bonne réponse.Je n'utilise généralement pas de préfixe pour les variables membres.
Je l' habitude d'utiliser un
m
préfixe, jusqu'à ce que quelqu'un a souligné que « C ++ a déjà un préfixe standard pour l' accès aux membres:this->
.C'est donc ce que j'utilise maintenant. C'est-à-dire qu'en cas d'ambiguïté , j'ajoute le
this->
préfixe, mais généralement, aucune ambiguïté n'existe et je peux simplement me référer directement au nom de la variable.Pour moi, c'est le meilleur des deux mondes. J'ai un préfixe que je peux utiliser quand j'en ai besoin, et je suis libre de le laisser de côté autant que possible.
Bien sûr, le contre-sens évident à cela est "oui, mais vous ne pouvez pas voir d'un coup d'œil si une variable est un membre de classe ou non".
À quoi je dis "et alors? Si vous avez besoin de savoir cela, votre classe a probablement trop d'état. Ou la fonction est trop grande et compliquée".
En pratique, j'ai trouvé que cela fonctionne extrêmement bien. En prime, cela me permet de promouvoir facilement une variable locale auprès d'un membre de la classe (ou l'inverse), sans avoir à la renommer.
Et le meilleur de tous, c'est cohérent! Je n'ai rien à faire de spécial ni à me souvenir des conventions pour maintenir la cohérence.
En passant, vous ne devriez pas utiliser de traits de soulignement pour les membres de votre classe. Vous vous approchez inconfortablement des noms réservés par l'implémentation.
La norme réserve tous les noms commençant par un double trait de soulignement ou un trait de soulignement suivi d'une majuscule. Il réserve également tous les noms commençant par un seul trait de soulignement dans l'espace de noms global .
Ainsi, un membre de classe avec un trait de soulignement avant suivi d'une lettre minuscule est légal, mais tôt ou tard, vous allez faire de même avec un identifiant commençant par une majuscule, ou autrement enfreindre l'une des règles ci-dessus.
Il est donc plus facile d'éviter les principaux traits de soulignement. Utilisez un trait de soulignement postfix, ou un préfixe
m_
ou simplementm
si vous souhaitez encoder la portée dans le nom de la variable.la source
this->
si vous devez spécifier que c'est une variable membre, ou non, c'est bien aussi.this->
signifie.Je préfère les traits de soulignement postfix, comme tels:
la source
vector<int> v_;
et l'écriturev_.push_back(5)
est assez moche aussiDernièrement, j'ai eu tendance à préférer le préfixe m_ au lieu de n'avoir aucun préfixe, les raisons ne sont pas tant qu'il est important de marquer les variables membres, mais cela évite toute ambiguïté, disons que vous avez du code comme:
void set_foo(int foo) { foo = foo; }
Celle de la cause ne fonctionne pas, une seule est
foo
autorisée. Vos options sont donc:this->foo = foo;
Je n'aime pas ça, car cela provoque l'observation des paramètres, vous ne pouvez plus utiliser d'
g++ -Wshadow
avertissements, il est également plus long à taper ensuitem_
. Vous rencontrez également toujours des conflits de dénomination entre les variables et les fonctions lorsque vous avez unint foo;
et unint foo();
.foo = foo_;
oufoo = arg_foo;
J'utilise cela depuis un moment, mais cela rend les listes d'arguments laides, la documentation ne devrait pas avoir trait à la désambiguïté des noms dans l'implémentation. Des conflits de noms entre les variables et les fonctions existent également ici.
m_foo = foo;
La documentation de l'API reste propre, vous n'obtenez pas d'ambiguïté entre les fonctions membres et les variables et son plus court à taper alors
this->
. Le seul inconvénient est que cela rend les structures POD laides, mais comme les structures POD ne souffrent pas de l'ambiguïté du nom en premier lieu, il n'est pas nécessaire de l'utiliser avec elles. Avoir un préfixe unique facilite également quelques opérations de recherche et de remplacement.foo_ = foo;
La plupart des avantages de
m_
s'appliquent, mais je le rejette pour des raisons esthétiques, un trait de soulignement à la fin ou au début donne simplement à la variable un aspect incomplet et déséquilibré.m_
semble juste mieux. L'utilisationm_
est également plus extensible, comme vous pouvez l'utiliserg_
pour les globaux ets_
pour la statique.PS: La raison pour laquelle vous ne voyez pas
m_
dans Python ou Ruby est que les deux langages appliquent leur propre préfixe, Ruby utilise@
pour les variables membres et Python requiertself.
.la source
foo
uniquement pour les membres et utiliser à la place des noms simples ou courts pour les paramètres ou d'autres sections locales / jetables, commeint f
; ou (b) préfixez les paramètres ou d'autres sections locales avec quelque chose. bon point rem_
et pods, cependant; Je suis indépendamment arrivé à une préférence pour suivre ces deux directives, pour la plupart.Lors de la lecture d'une fonction membre, savoir à qui «appartient» chaque variable est absolument essentiel pour comprendre la signification de la variable. Dans une fonction comme celle-ci:
... il est assez facile de voir d'où viennent les pommes et les bananes, mais qu'en est-il des raisins, des melons et des patates? Devrions-nous regarder dans l'espace de noms global? Dans la déclaration de classe? La variable est-elle membre de cet objet ou membre de la classe de cet objet? Sans connaître la réponse à ces questions, vous ne pouvez pas comprendre le code. Et dans une fonction plus longue, même les déclarations de variables locales comme les pommes et les bananes peuvent se perdre dans le shuffle.
La préparation d'une étiquette cohérente pour les globaux, les variables membres et les variables membres statiques (peut-être g_, m_ et s_ respectivement) clarifie instantanément la situation.
Il faudra peut-être un certain temps pour s'y habituer au début - mais ensuite, qu'est-ce qui ne fonctionne pas en programmation? Il y a eu un jour où même {and} vous avait l'air bizarre. Et une fois que vous vous y êtes habitué, ils vous aident à comprendre le code beaucoup plus rapidement.
(Utiliser "this->" à la place de m_ a du sens, mais est encore plus long et visuellement perturbateur. Je ne le vois pas comme une bonne alternative pour baliser toutes les utilisations des variables membres.)
Une objection possible à l'argument ci-dessus serait d'étendre l'argument aux types. Il peut également être vrai que la connaissance du type d'une variable «est absolument essentielle pour comprendre la signification de la variable». Si tel est le cas, pourquoi ne pas ajouter un préfixe à chaque nom de variable qui identifie son type? Avec cette logique, vous vous retrouvez avec la notation hongroise. Mais beaucoup de gens trouvent la notation hongroise laborieuse, laide et inutile.
hongrois faitdites-nous quelque chose de nouveau sur le code. Nous comprenons maintenant qu'il existe plusieurs transtypages implicites dans la fonction Foo :: bar (). Le problème avec le code maintenant est que la valeur des informations ajoutées par les préfixes hongrois est faible par rapport au coût visuel. Le système de type C ++ comprend de nombreuses fonctionnalités pour aider les types à bien fonctionner ensemble ou pour déclencher un avertissement ou une erreur du compilateur. Le compilateur nous aide à gérer les types - nous n'avons pas besoin de notation pour le faire. Nous pouvons déduire assez facilement que les variables de Foo :: bar () sont probablement numériques, et si c'est tout ce que nous savons, c'est assez bien pour avoir une compréhension générale de la fonction. Par conséquent, l'intérêt de connaître le type précis de chaque variable est relativement faible. Pourtant, la laideur d'une variable comme "s_dSpuds" (ou même simplement "dSpuds") est excellente. Alors,
la source
Je ne peux pas dire à quel point c'est large, mais personnellement, j'ai toujours (et j'ai toujours) préfixé mes variables membres avec «m». Par exemple:
C'est la seule forme de préfixe que j'utilise (je suis très contre la notation hongroise) mais cela m'a bien aidé au fil des ans. En passant, je déteste généralement l'utilisation de traits de soulignement dans les noms (ou n'importe où ailleurs d'ailleurs), mais fais une exception pour les noms de macro de préprocesseur, car ils sont généralement tous en majuscules.
la source
a
en majuscule dans ce scénario - vous ne le faites pas correctement autrement.mApData
(m
préfixe, alors le nom de la variable estapData
).La raison principale d'un préfixe de membre est de faire la distinction entre une fonction membre locale et une variable membre avec le même nom. Ceci est utile si vous utilisez des getters avec le nom de l'objet.
Considérer:
La variable membre n'a pas pu être appelée full_name dans ce cas. Vous devez renommer la fonction membre en get_full_name () ou décorer la variable membre d'une manière ou d'une autre.
la source
foo.name()
c'est beaucoup plus lisible qu'àfoo.get_name()
mon avis.Je ne pense pas qu'une syntaxe ait une valeur réelle par rapport à une autre. Tout se résume, comme vous l'avez mentionné, à l'uniformité entre les fichiers source.
Le seul point où je trouve ces règles intéressantes, c'est quand j'ai besoin de 2 choses nommées identiques, par exemple:
Je l'utilise pour différencier les deux. De plus, lorsque j'emballe des appels, comme à partir de Windows Dll, RecvPacket (...) de la Dll peut être enveloppé dans RecvPacket (...) dans mon code. Dans ces cas particuliers, l'utilisation d'un préfixe tel que "_" peut faire en sorte que les deux se ressemblent, il est facile d'identifier lequel est lequel, mais différent pour le compilateur
la source
Certaines réponses se concentrent sur la refactorisation, plutôt que sur les conventions de dénomination, comme moyen d'améliorer la lisibilité. Je ne pense pas que l'un puisse remplacer l'autre.
J'ai connu des programmeurs qui ne sont pas à l'aise avec les déclarations locales; ils préfèrent placer toutes les déclarations en haut d'un bloc (comme en C), afin de savoir où les trouver. J'ai constaté que, là où la portée le permet, déclarer les variables là où elles sont utilisées pour la première fois diminue le temps que je passe à regarder en arrière pour trouver les déclarations. (Cela est vrai pour moi même pour les petites fonctions.) Cela me permet de mieux comprendre le code que je regarde.
J'espère que le lien avec les conventions de dénomination des membres est suffisamment clair: lorsque les membres ont un préfixe uniforme, je n'ai jamais à regarder en arrière du tout; Je sais que la déclaration ne sera même pas trouvée dans le fichier source.
Je suis sûr que je n'ai pas commencé par préférer ces styles. Pourtant, au fil du temps, travaillant dans des environnements où ils étaient utilisés de manière cohérente, j'ai optimisé ma réflexion pour en tirer parti. Je pense qu'il est possible que de nombreuses personnes qui se sentent actuellement mal à l'aise avec eux en viennent également à les préférer, étant donné leur utilisation constante.
la source
Ces conventions ne sont que cela. La plupart des magasins utilisent des conventions de code pour faciliter la lisibilité du code afin que tout le monde puisse facilement consulter un morceau de code et déchiffrer rapidement entre des éléments tels que des membres publics et privés.
la source
class
tous les membres dont les membres sontprivate
/protected
, soit les PODstruct
dont toutes les variables sontpublic
(et souvent aussiconst
). Donc, je n'ai jamais besoin de m'interroger sur le niveau d'accès d'un membre donné.C'est généralement parce qu'il n'y a pas de préfixe . Le compilateur a besoin de suffisamment d'informations pour résoudre la variable en question, que ce soit un nom unique à cause du préfixe ou via le
this
mot - clé.Donc, oui, je pense que les préfixes sont toujours utiles. Pour ma part, je préférerais taper «_» pour accéder à un membre plutôt que «this->».
la source
struct Foo { int x; Foo(int x) : x(x) { ... } };
Foo(int x, bool blee) : x(x) { if (blee) x += bleecount; } // oops, forgot this->
préférez appeler mes variables membres quelque chose d'utile, puis donner des paramètres de constructeur qui leur correspondent des noms abrégés:Foo(int f) : foo(f) {...}
D'autres langages utiliseront des conventions de codage, ils tendent simplement à être différents. C #, par exemple, a probablement deux styles différents que les gens ont tendance à utiliser, soit l'une des méthodes C ++ (_variable, mVariable ou un autre préfixe tel que la notation hongroise), ou ce que j'appelle la méthode StyleCop.
En fin de compte, cela devient ce que les gens savent et ce qui semble le mieux. Personnellement, je pense que le code est plus lisible sans la notation hongroise, mais il peut devenir plus facile de trouver une variable avec intellisense par exemple si la notation hongroise est jointe.
Dans mon exemple ci-dessus, vous n'avez pas besoin d'un préfixe m pour les variables membres, car vous préfixez votre utilisation avec ceci. indique la même chose dans une méthode appliquée par le compilateur.
Cela ne signifie pas nécessairement que les autres méthodes sont mauvaises, les gens s'en tiennent à ce qui fonctionne.
la source
Lorsque vous avez une grande méthode ou des blocs de code, il est pratique de savoir immédiatement si vous utilisez une variable locale ou un membre. c'est pour éviter les erreurs et pour une meilleure clarté!
la source
-Wshadow
OMI, c'est personnel. Je ne mets aucun préfixe. Quoi qu'il en soit, si le code est censé être public, je pense qu'il devrait mieux avoir des préfixes, afin qu'il soit plus lisible.
Souvent, les grandes entreprises utilisent leurs propres «règles de développement».
Btw, le plus drôle mais le plus intelligent que j'ai vu était DRY KISS (Ne vous répétez pas. Keep It Simple, Stupid). :-)
la source
Comme d'autres l'ont déjà dit, il est important d'être familier (adapter les styles et les conventions de dénomination à la base de code dans laquelle vous écrivez) et d'être cohérent.
Pendant des années, j'ai travaillé sur une grande base de code qui utilise à la fois la convention "this->" et un suffixe notation de soulignement pour les variables membres. Au fil des années, j'ai également travaillé sur des projets plus petits, dont certains n'avaient aucune sorte de convention pour nommer les variables membres, et d'autres qui avaient des conventions différentes pour nommer les variables membres. De ces petits projets, j'ai toujours trouvé que ceux qui n'avaient aucune convention étaient les plus difficiles à aborder rapidement et à comprendre.
Je suis très réticent à la dénomination. Je m'inquiéterai du nom à attribuer à une classe ou à une variable au point que, si je ne parviens pas à trouver quelque chose que je trouve «bon», je choisirai de le nommer quelque chose de non-sens et de fournir un commentaire décrivant ce que c'est vraiment est. De cette façon, au moins le nom signifie exactement ce que je veux dire - ni plus ni moins. Et souvent, après l'avoir utilisé pendant un petit moment, je découvre ce que le nom devrait vraiment être et je peux revenir en arrière et modifier ou refactoriser de manière appropriée.
Un dernier point sur le sujet d'un IDE faisant le travail - c'est bien beau, mais les IDE ne sont souvent pas disponibles dans les environnements où j'ai effectué le travail le plus urgent. Parfois, la seule chose disponible à ce stade est une copie de «vi». En outre, j'ai vu de nombreux cas où l'achèvement du code IDE a propagé la stupidité telle que l'orthographe incorrecte des noms. Ainsi, je préfère ne pas avoir à compter sur une béquille IDE.
la source
L'idée originale des préfixes sur les variables membres C ++ était de stocker des informations de type supplémentaires que le compilateur ne connaissait pas. Ainsi, par exemple, vous pourriez avoir une chaîne qui a une longueur fixe de caractères, et une autre qui est variable et terminée par un '\ 0'. Pour le compilateur, ils sont tous les deux
char *
, mais si vous essayez de copier de l'un à l'autre, vous avez d'énormes problèmes. Alors, du haut de ma tête,char *aszFred = "Hi I'm a null-terminated string";
char *arrWilma = {'O', 'o', 'p', 's'};
où "asz" signifie que cette variable est "chaîne ascii (terminée par un zéro) et" arr "signifie que cette variable est un tableau de caractères.
Ensuite, la magie opère. Le compilateur sera parfaitement satisfait de cette déclaration:
strcpy(arrWilma, aszFred);
Mais vous, en tant qu'humain, pouvez le regarder et dire "hé, ces variables ne sont pas vraiment du même type, je ne peux pas faire ça".
Malheureusement, de nombreux endroits utilisent des standards tels que "m_" pour les variables membres, "i" pour les entiers peu importe comment ils sont utilisés, "cp" pour les pointeurs char. En d'autres termes, ils dupliquent ce que le compilateur sait et rendent le code difficile à lire en même temps. Je crois que cette pratique pernicieuse devrait être interdite par la loi et passible de sanctions sévères.
Enfin, il y a deux points que je devrais mentionner:
la source
Notre projet a toujours utilisé «son» comme préfixe pour les données des membres et «le» comme préfixe pour les paramètres, sans préfixe pour les locaux. C'est un peu moche, mais il a été adopté par les premiers développeurs de notre système car ils l'ont vu utilisé comme convention par certaines bibliothèques de sources commerciales que nous utilisions à l'époque (XVT ou RogueWave - peut-être les deux). Vous obtiendrez donc quelque chose comme ça:
La principale raison pour laquelle je vois les préfixes de portée (et pas d'autres - je déteste la notation hongroise) est que cela vous empêche d'avoir des problèmes en écrivant du code où vous pensez que vous faites référence à une variable, mais vous faites vraiment référence à une autre variable avec le même nom défini dans la portée locale. Cela évite également le problème de trouver un nom de variable pour représenter ce même concept, mais avec des portées différentes, comme dans l'exemple ci-dessus. Dans ce cas, vous devrez de toute façon trouver un préfixe ou un nom différent pour le paramètre "theName" - pourquoi ne pas créer une règle cohérente qui s'applique partout.
Le simple fait d'utiliser this-> n'est pas vraiment suffisant - nous ne sommes pas aussi intéressés par la réduction de l'ambiguïté que par la réduction des erreurs de codage, et masquer les noms avec des identifiants à portée locale peut être pénible. Certes, certains compilateurs peuvent avoir la possibilité de déclencher des avertissements pour les cas où vous avez masqué le nom dans une portée plus large, mais ces avertissements peuvent devenir une nuisance si vous travaillez avec un grand nombre de bibliothèques tierces qui ont choisi les noms de variables inutilisées qui entrent parfois en conflit avec les vôtres.
En ce qui concerne le son / le lui-même - honnêtement, je trouve qu'il est plus facile à taper que les traits de soulignement (en tant que dactylo tactile, j'évite autant que possible les traits de soulignement - trop d'étirement des lignes d'origine), et je le trouve plus lisible qu'un mystérieux soulignement.
la source
Je l'utilise parce que Intellisense de VC ++ ne peut pas dire quand afficher les membres privés lors de l'accès hors de la classe. La seule indication est un petit symbole de «verrouillage» sur l'icône de champ dans la liste Intellisense. Cela facilite simplement l'identification des membres privés (champs). Aussi une habitude de C # pour être honnête.
la source
Je pense que si vous avez besoin de préfixes pour distinguer les membres de la classe des paramètres de fonction membre et des variables locales, soit la fonction est trop grande, soit les variables sont mal nommées. S'il ne rentre pas sur l'écran pour que vous puissiez facilement voir ce qui est quoi, refactoriser.
Étant donné qu'ils sont souvent déclarés loin de l'endroit où ils sont utilisés, je trouve que les conventions de dénomination des constantes globales (et des variables globales, bien que l'OMI ait rarement besoin de les utiliser) ont du sens. Mais sinon, je ne vois pas grand besoin.
Cela dit, j'avais l'habitude de mettre un trait de soulignement à la fin de tous les membres de la classe privée. Étant donné que toutes mes données sont privées, cela implique que les membres ont un trait de soulignement à la fin. Je ne fais généralement plus cela dans de nouvelles bases de code, mais comme, en tant que programmeur, vous travaillez principalement avec de l'ancien code, je le fais toujours beaucoup. Je ne sais pas si ma tolérance pour cette habitude vient du fait que je le faisais toujours et que je le fais toujours régulièrement ou si cela a vraiment plus de sens que le marquage des variables membres.
la source
En python, les doubles traits de soulignement sont utilisés pour émuler les membres privés. Pour plus de détails, consultez cette réponse
la source
Il est utile de faire la différence entre les variables membres et les variables locales en raison de la gestion de la mémoire. De manière générale, les variables membres allouées au tas doivent être détruites dans le destructeur, tandis que les variables locales allouées au tas doivent être détruites dans cette portée. L'application d'une convention de dénomination aux variables membres facilite la gestion correcte de la mémoire.
la source
Code Complete recommande m_varname pour les variables membres.
Bien que je n'ai jamais pensé que la notation m_ était utile, je donnerais du poids à l'opinion de McConnell dans la construction d'une norme.
la source
Je n'utilise presque jamais de préfixes devant mes noms de variables. Si vous utilisez un IDE suffisamment décent, vous devriez pouvoir refactoriser et trouver facilement des références. J'utilise des noms très clairs et je n'ai pas peur d'avoir de longs noms de variables. Je n'ai jamais eu de problème avec la portée non plus avec cette philosophie.
La seule fois où j'utilise un préfixe serait sur la ligne de signature. Je préfixe les paramètres à une méthode avec _ afin que je puisse programmer de manière défensive autour d'eux.
la source
Vous ne devriez jamais avoir besoin d'un tel préfixe. Si un tel préfixe vous offre un avantage, votre style de codage en général doit être corrigé, et ce n'est pas le préfixe qui empêche votre code d'être clair. Les mauvais noms de variables typiques incluent "autre" ou "2". Vous ne corrigez pas cela en exigeant qu'il soit mOther, vous le corrigez en amenant le développeur à réfléchir à ce que cette variable fait là dans le contexte de cette fonction. Peut-être qu'il voulait dire remoteSide, ou newValue, ou secondTestListener ou quelque chose dans cette portée.
C'est un anachronisme efficace qui se propage encore trop loin. Arrêtez de préfixer vos variables et donnez-leur des noms propres dont la clarté reflète la durée de leur utilisation. Jusqu'à 5 lignes, vous pouvez l'appeler "i" sans confusion; au-delà de 50 lignes, vous avez besoin d'un nom assez long.
la source
J'aime que les noms de variables ne donnent qu'une signification aux valeurs qu'ils contiennent et ne tiennent pas compte de la manière dont ils sont déclarés / implémentés. Je veux savoir ce que signifie la valeur, point final. Peut-être ai-je fait plus qu'une quantité moyenne de refactorisation, mais je trouve que l'intégration de la façon dont quelque chose est implémenté dans le nom rend la refactorisation plus fastidieuse que nécessaire. Les préfixes indiquant où et comment les membres d'objet sont déclarés sont spécifiques à l'implémentation.
La plupart du temps, je ne me soucie pas de savoir si Red est une énumération, une structure ou autre, et si la fonction est si grande que je ne me souviens pas si la couleur a été déclarée localement ou est un membre, il est probablement temps de casser la fonction en unités logiques plus petites.
Si votre complexité cyclomatique est si grande que vous ne pouvez pas suivre ce qui se passe dans le code sans des indices spécifiques à l'implémentation intégrés dans les noms des choses, vous devrez probablement réduire la complexité de votre fonction / méthode.
La plupart du temps, je n'utilise «this» que dans les constructeurs et les initialiseurs.
la source
J'utilise m_ pour les variables membres juste pour profiter d'Intellisense et des fonctionnalités IDE associées. Lorsque je codifie l'implémentation d'une classe, je peux taper m_ et voir la liste déroulante avec tous les membres m_ regroupés.
Mais je pourrais vivre sans m_ sans problème, bien sûr. C'est juste mon style de travail.
la source
this->
Selon les NORMES DE CODAGE C ++ DES VÉHICULES AÉRIENS JOINT STRIKE FIGHTER (décembre 2005):
Ainsi, le préfixe "m" devient inutile car toutes les données doivent être privées.
Mais c'est une bonne habitude d'utiliser le préfixe p avant un pointeur car c'est une variable dangereuse.
la source
Beaucoup de ces conventions datent d'une époque sans éditeurs sophistiqués. Je recommanderais d'utiliser un IDE approprié qui vous permet de colorer tous les types de variables. La couleur est de loin plus facile à repérer que n'importe quel préfixe.
Si vous avez besoin d'obtenir encore plus de détails sur une variable, tout IDE moderne devrait être capable de vous la montrer en déplaçant le curseur ou le curseur dessus. Et si vous utilisez une variable d'une manière incorrecte (par exemple un pointeur avec l'opérateur.), Vous obtiendrez une erreur, de toute façon.
la source