Conventions de dénomination utilisées pour les variables et fonctions en C [fermé]


13

Lors du codage d'un grand projet dans CI, un problème est survenu. Si je continue à écrire plus de code, il y aura un moment où il sera difficile pour moi d'organiser le code. Je veux dire que la dénomination des fonctions et des variables pour différentes parties du programme peut sembler mélangée.

Je me demandais donc s'il existe des conventions de dénomination utiles que je peux utiliser pour les variables et les fonctions C?

La plupart des langues suggèrent une convention de dénomination. Mais pour C, la seule chose que j'ai lu jusqu'à présent est que les noms doivent être descriptifs pour la lisibilité du code.

ÉDITER:

Exemples de quelques exemples de conventions de dénomination suggérées:

J'ai lu quelques conventions de dénomination pour java quelque part mais je ne me souvenais pas où.


Citez quelques exemples de langues avec des conventions de nommage suggérées. Et où nous pouvons trouver ces conventions de dénomination.
Philip

@Philip Exemples ajoutés
Aseem Bansal

1
Il ne devrait pas y avoir de problème avec les variables car vous n'utilisez pas de globaux. Et pour les noms de fonction: si le nom du module est order.c, vous pouvez nommer les fonctions order_add(), order_del()etc. Certains anciens systèmes peuvent vous indiquer que le nom doit être unique parmi les 8 premiers caractères. Lorsque vous passez au c ++ plus tard par accident, vous adorerez écrire order::add()et order::del()ensuite.
ott--

Réponses:


17

Si je continue à écrire plus de code, il y aura un moment où il sera difficile pour moi d'organiser le code.

C'est votre problème: obtenir la bonne organisation et le style devrait couler plus facilement.

Ne pas attendre d'organiser votre code: garder votre code organisé comme vous allez. Bien que le langage ne le fasse pas pour vous, le code doit toujours être organisé en modules avec un faible couplage et une forte cohésion.

Ces modules fournissent alors naturellement un espace de noms. Abréger le nom du module (s'il est long) et préfixer les noms de fonction avec leur module pour éviter les collisions.

Au niveau des identifiants individuels, ceux-ci sont à peu près en ordre croissant de subjectivité:

  1. choisissez une convention et respectez-la
    • par exemple, function_like_this(struct TypeLikeThis variable)est commun
  2. éviter absolument la notation hongroise (désolé JNL)

    • sauf si vous êtes prêt à l'utiliser comme prévu à l'origine, ce qui signifie la notation des applications de Simonyi plutôt que la terrible version des systèmes

      Pourquoi? Je pourrais écrire un essai à ce sujet, mais je vous suggérerai plutôt de lire cet article de Joel Spolsky, puis de chercher un peu plus si vous êtes intéressé. Il y a un lien vers le papier original de Simonyi en bas.

  3. éviter les pointeurs typedefs à moins qu'ils ne soient de véritables types de cookies opaques - ils ne font que confondre les choses

    struct Type *ok;
    typedef struct Type *TypePtr;
    TypePtr yuck;

    Qu'est-ce que j'entends par un type de cookie opaque ? Je veux dire quelque chose utilisé dans un module (ou une bibliothèque, ou autre) qui doit être transmis au code client, mais ce code client ne peut pas être utilisé directement. Il le renvoie simplement à la bibliothèque.

    Par exemple, une bibliothèque de base de données peut exposer une interface comme

    /* Lots of buffering, IPC and metadata magic held in here.
       No, you don't get to look inside. */
    struct DBContextT;
    /* In fact, you only ever get a pointer, so let's give it a nice name */
    typedef struct DBContexT *DBContext;
    
    DBContext db_allocate_context(/*maybe some optional flags?*/);
    void db_release_context(DBContext);
    int db_connect(DBContext, const char *connect);
    int db_disconnect(DBContext);
    int db_execute(DBContext, const char *sql);

    Maintenant, le contexte est opaque pour le code client, car vous ne pouvez pas regarder à l'intérieur. Vous venez de le renvoyer à la bibliothèque. Quelque chose comme FILEest également opaque, et un descripteur de fichier entier est également un cookie , mais n'est pas opaque.


Une note sur le design

J'ai utilisé la phrase couplage bas et cohésion élevée ci-dessus sans explication, et je me sens un peu mal à ce sujet. Vous pouvez le rechercher et trouver probablement de bons résultats, mais je vais essayer d'y répondre brièvement (encore une fois, je pourrais écrire un essai mais j'essaierai de ne pas le faire).

La bibliothèque DB esquissée ci-dessus montre un faible couplage car elle expose une petite interface au monde extérieur. En masquant ses détails d'implémentation (en partie avec l'astuce de cookie opaque), il empêche le code client de dépendre de ces détails.

Imaginez au lieu du cookie opaque, nous déclarons la structure de contexte afin que son contenu soit visible, et qui inclut un descripteur de fichier socket pour une connexion TCP à la base de données. Si nous modifions ensuite l'implémentation pour prendre en charge l'utilisation d'un segment de mémoire partagée lorsque la base de données s'exécute sur la même machine, le client doit être recompilé plutôt que simplement ré-lié. Pire encore, le client aurait pu commencer à utiliser le descripteur de fichier, par exemple en appelant setsockoptpour modifier la taille de tampon par défaut, et maintenant il a également besoin d'un changement de code. Tous ces détails doivent être cachés à l'intérieur de notre module lorsque cela est possible, et cela donne un faible couplage entre les modules.

L'exemple montre également une cohésion élevée , dans la mesure où toutes les méthodes du module concernent la même tâche (accès DB). Cela signifie que seul le code qui a besoin de connaître les détails de l'implémentation (c'est-à-dire le contenu de notre cookie) y a réellement accès, ce qui simplifie le débogage.

Vous pouvez également voir que le fait d'avoir une seule préoccupation a facilité le choix d'un préfixe pour regrouper ces fonctions.

Maintenant, dire que cet exemple est bon est facile (d'autant plus qu'il n'est même pas complet), mais ne vous aide pas immédiatement. L'astuce consiste à surveiller, pendant que vous écrivez et étendez votre code, les fonctions qui font des choses similaires ou qui fonctionnent sur les mêmes types (qui pourraient être candidates à leur propre module), ainsi que les fonctions qui font beaucoup de choses distinctes qui ne sont pas '' t vraiment liés, et pourraient être candidats à la séparation.


Pouvez-vous m'aider à comprendre pourquoi le hongrois est évité? Juste curieux d'en savoir plus. :)
JNL

@JNL: Un commentaire est trop court pour être correctement expliqué. Je vous suggère de le poster comme une nouvelle question.
Bart van Ingen Schenau

with low coupling and high cohesion. Qu'est-ce que ça veut dire? Et veuillez expliquer les types de cookies opaques. Je n'ai aucune idée de ce que ça veut dire.
Aseem Bansal

J'ai essayé d'aborder les deux brièvement, et franchement, j'ai échoué en termes de concision. J'espère que cela devrait vous aider à démarrer.
inutile

Je réponds après quelques jours. Désolé. J'ai lu votre description de low coupling and high cohesion. Donc, cela signifie essentiellement encapsuler les choses quand je le peux et cela devrait être fait de manière à ce que les fonctions qui ont réellement besoin aient accès. Certaines choses ont dépassé ma tête, mais je pense que j'ai compris votre point de vue.
Aseem Bansal

5

À mon avis, 90% du problème de dénomination est résolu si vous gardez trois choses à l'esprit: a) rendez vos noms de variable et de fonction aussi descriptifs que possible, b) soyez cohérent dans tout votre code (c.-à-d., Si une fonction est nommée addNumbers, a la deuxième fonction doit être nommée multiplyNumbers et non numberMul) et c) essayez de raccourcir les noms si possible, car nous devons les saisir.

Cela étant dit, si vous souhaitez examiner d'autres aspects de ce sujet, la page Wikipédia sur les conventions de dénomination contient une bonne liste de choses que vous devez garder à l'esprit. Il a également une section sur C et C ++:

En C et C ++, les mots clés et les identificateurs de bibliothèque standard sont pour la plupart en minuscules. Dans la bibliothèque standard C, les noms abrégés sont les plus courants (par exemple isalnum pour une fonction testant si un caractère est alphanumérique), tandis que la bibliothèque standard C ++ utilise souvent un trait de soulignement comme séparateur de mots (par exemple out_of_range). Les identifiants représentant les macros sont, par convention, écrits en utilisant uniquement des lettres majuscules et des traits de soulignement (ceci est lié à la convention dans de nombreux langages de programmation d'utiliser des identifiants tout en majuscules pour les constantes). Les noms contenant un double trait de soulignement ou commençant par un trait de soulignement et une lettre majuscule sont réservés à l'implémentation (compilateur, bibliothèque standard) et ne doivent pas être utilisés (par exemple réservé__ ou _Réservé). [5] [6] C'est superficiellement similaire au stropping, mais la sémantique diffère:


3
"essayez de raccourcir les noms si possible" Utilisez un IDE avec auto-complétion, alors les noms de vos fonctions peuvent être aussi longs et descriptifs qu'ils doivent l'être car vous n'avez besoin de les taper qu'une seule fois.
Joel

1
@Joel terrible conseil. Tout le monde n'utilisera pas le même IDE que vous.
James

6
@James Ils n'en ont pas besoin, ils peuvent simplement utiliser n'importe quel IDE décent. Vous n'avez alors pas à sacrifier la clarté pour la productivité.
Joel

Le terme IDE est un peu mince maintenant de quelques jours. Techniquement, Notepad ++ est un IDE car vous pouvez le configurer pour compiler et exécuter votre projet, mais c'est principalement un éditeur de texte. Et il se complète automatiquement.
Philip

5

La seule contrainte difficile en C est qu'il n'y a pas d'espaces de noms. Par conséquent, vous devez trouver un moyen de rendre la rename()fonction de votre bibliothèque de système de fichiers distincte de la rename()fonction de votre bibliothèque multimédia . La solution habituelle est un préfixe, tel que: filesystem_rename()et media_rename().

L'autre conseil général est: rester cohérent au sein d'un projet ou d'une équipe. La lisibilité sera améliorée.


+1: Cela est particulièrement vrai pour les symboles exportés dans une bibliothèque. "Je suis désolé, mais cette bibliothèque de système de fichiers ne va pas avec cette bibliothèque multimédia, car les deux ont une fonction exportée renommée.
Residuum

2

SI VOUS RECHERCHEZ UN FORMAT GLOBALEMENT ACCEPTÉ

MISRA / JSF / AUTOSAR couvre près de 100% de toutes les normes de l'industrie pour nommer et organiser le code C / C ++. Le problème est qu'ils ne seront pas disponibles gratuitement, c'est-à-dire que chacun des guides coûte de l'argent. Je sais que le livre standard de codage MISRA 2008 C / C ++ coûte probablement environ 50 USD.

Vous pouvez les considérer comme le référencement Harvard pour la bibliographie et la lecture supplémentaire lorsque vous écrivez un journal. J'ai utilisé MISRA et c'est un bon moyen de nommer vos fonctions et variables, et de les organiser pour une utilisation appropriée.

SI VOUS RECHERCHEZ QUELQUE CHOSE DE TEMPORAIRE

Les références que vous avez fournies pour Python et Java sont correctes, je suppose. J'ai vu des gens adopter le style javadoc pour commenter, nommer et organiser le code. En fait, dans mon dernier projet, j'ai dû écrire du code C ++ dans des fonctions / noms de variables de type Java. Deux raisons à cela:

1) C'était apparemment plus facile à suivre.

2) Les exigences du code de production n'ont pas touché le fond des normes de systèmes logiciels critiques pour la sécurité.

3) Le code hérité était (en quelque sorte) dans ce format.

4) Doxygen a permis de commenter la sirop de Javadoc. À ce moment, nous utilisions doxygen pour générer de la documentation pour les gars de la production.

De nombreux programmeurs seront opposés à cela, mais personnellement, je pense qu'il n'y a rien de mal à adopter le nom de fonction / variable de style javadoc en C / C ++. OUI, bien sûr, les pratiques d'organisation de votre contrôle de flux, la sécurité des threads, etc. doivent être abordées indépendamment. Cependant, je ne suis pas un candidat ici. Je ne sais pas non plus à quel point vos exigences de format de code de production sont strictes. Sans le détourner vers un domaine hors sujet, je vous suggère de revoir vos exigences, de savoir à quel point vous dépendez d'une convention de dénomination spécifique et de choisir une solution mentionnée dans la mienne et dans les réponses des autres.

J'espère que cela a aidé!?


En fait, je demandais ceci pour des codes C personnels. Mais je me souviendrai de votre suggestion.
Aseem Bansal

@AseemBansal Personnel ou professionnel, ceux-ci sont bons à apprendre et aussi bons à mettre sur votre CV :) .... A vous de voir.
hagubear

0

Peu de choses importantes à considérer lors de la dénomination seraient;

  1. Regardez le type actionObject ou ObjectAction. (Objet pas pour C. Mais en général quand vous allez dans d'autres langages orientés objet) Cela devrait aider

  2. Le reste serait CONSTANT, court et descriptif à coup sûr.

  3. En outre, avoir un seul objectif pour chaque variable et fonction définie, par exemple: si c'est pour stocker une valeur temporairement, nommez-la comme nTempVal pour int
  4. Les variables doivent être nom et les méthodes doivent être verbe.

6
La notation hongroise (préfixant une variable avec des lettres indiquant le type) n'entraîne pas de fin de douleur. Heureusement, il est surtout passé de mode.
Gort the Robot

@StevenBurnap Étiez-vous simplement curieux de savoir pourquoi le format hongrois est évité? Je crois que c'est ce qu'ils nous ont enseigné à l'école et j'ai vu un tel code dans certains lieux de travail aussi. Lequel recommanderiez-vous sinon hongrois. Merci
JNL

1
La meilleure convention de dénomination n'est qu'une seule utilisée de manière cohérente, avec des noms clairs et descriptifs idéalement gardés relativement courts sans abréviation excessive et en évitant les préfixes redondants. La notation hongroise a peu d'utilité réelle, rend le code plus difficile à lire et rend les changements de types plus difficiles.
Gort the Robot

2
Voici une description de l'intention originale et de l'abomination que la notation hongroise est devenue: joelonsoftware.com/articles/Wrong.html
Residuum

@Residuum C'était un bon lien. Beaucoup aidé. Je l'apprécie.
JNL

0

La plupart des réponses sont bonnes, mais je veux dire quelques choses sur les conventions de dénomination pour les bibliothèques et les fichiers inclus, similaires à l'utilisation d'espaces de noms dans d'autres langages comme C ++ ou Java:

Si vous créez une bibliothèque, trouvez un préfixe commun pour vos symboles exportés, à savoir les fonctions globales, les typedefs et les variables. Cela empêchera les conflits avec d'autres bibliothèques et identifiera les fonctions comme provenant de la vôtre. Ceci est un peu d'applications notations hongroises.

Peut-être aller encore plus loin et regrouper vos symboles exportés: libcurl utilise curl_ * pour les symboles globaux, curl_easy_ *, curl_multi_ * et curl_share_ * pour les différentes interfaces. Ainsi, en plus d'utiliser curl_ * pour toutes les fonctions, ils ont ajouté un autre niveau "d'espaces de noms" pour les différentes interfaces: appeler une fonction curl_easy_ * sur une poignée curl_multi_ * semble désormais incorrect, voir les noms de fonctions sur http: // curl. haxx.se/libcurl/c/

En gardant les règles pour les symboles exportés, vous devez les utiliser pour les fonctions statiques dans les #includefichiers ed: Essayez de trouver un préfixe commun pour ces fonctions. Peut-être que vous avez des fonctions utilitaires de chaînes statiques dans un fichier appelé "my_string"? Préfixez toutes ces fonctions avec my_string_ *.


Par symboles exportés, vous entendez des variables globales, des fonctions, des typedefs, etc. si je me trompe. Pouvez-vous expliquer un peu le regroupement des symboles exportés? Je pensais que vous l'aviez déjà expliqué au paragraphe précédent. Qu'avez-vous ajouté au 3e paragraphe?
Aseem Bansal
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.