Commentaires
Réponse
Si je continue écrire plus de code alors il y aura un moment où il me sera difficile dorganiser le code.
Voici votre problème: bien organiser lorganisation, et le style devrait couler plus facilement.
Nattendez pas pour organiser votre code: gardez votre code organisé au fur et à mesure. 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éviez le nom du module (sil est long) et préfixez les noms des fonctions avec leur module pour éviter les collisions.
Au niveau des identifiants individuels, ceux-ci sont à peu près par ordre croissant de subjectivité:
- choisissez une convention et respectez-la
- par exemple,
function_like_this(struct TypeLikeThis variable)
est courant
- par exemple,
-
évitez définitivement la notation hongroise (désolé JNL)
-
à moins que vous « ne vouliez lutiliser comme prévu à lorigine, ce qui signifie la notation apps 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 ya un lien vers le papier original de Simonyi en bas.
-
-
évitez les typedefs de pointeur à moins quils ne soient des types de cookies véritablement opaques – ils confondre les choses
struct Type *ok; typedef struct Type *TypePtr; TypePtr yuck;
Quest-ce que jentends par type de cookie opaque ? Je veux dire quelque chose utilisé dans un module (ou une bibliothèque, ou peu importe) qui doit être transmis au code client, mais ce code client peut « t utiliser 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 au code client, car vous ne pouvez pas regarder à lintérieur. Il vous suffit de le renvoyer à la bibliothèque. Quelque chose comme
FILE
est également opaque, et un descripteur de fichier entier est également un cookie , mais nest pas opaque.
Une note sur la conception
Jai utilisé lexpression faible couplage et haute cohésion ci-dessus sans explication, et je me sens un peu mal à ce sujet. Vous pouvez le rechercher, et probablement trouver de bons résultats, mais jessaierai dy répondre brièvement (encore une fois, je pourrais écrire un essai mais jessaierai de ne pas le faire).
La bibliothèque DB esquissée ci-dessus montre faible couplage car il expose une petite interface au monde extérieur. En cachant ses détails dimplémentation (en partie avec lastuce du 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 pour que son contenu soit visible, et cela inclut un descripteur de fichier socket pour une connexion TCP à la base de données. Si nous changeons par la suite limplémentation pour prendre en charge lutilisation dun segment de mémoire partagée lorsque le La base de données sexécute sur la même machine, le client doit être recompilé plutôt que simplement re-lié. Pire encore, le client aurait pu démarrer en utilisant le descripteur de fichier, par exemple en appelant setsockopt
pour changer la taille de la mémoire tampon par défaut, et maintenant il a également besoin dun changement de code. Tous ces détails ils doivent être cachés dans notre module lorsque cela est possible, ce qui donne un faible couplage entre modules.
Lexemple montre également une cohésion élevée , en ce que tous les les méthodes du module concernent la même tâche (accès à la base de données). Cela signifie que seul le code qui a besoin de connaître les détails de limplémentation (cest-à-dire le contenu de notre cookie) y a effectivement accès, ce qui simplifie le débogage.
Vous pouvez également voir que le fait davoir un seul souci a facilité le choix dun préfixe pour regrouper ces fonctions.
Maintenant, dire que cet exemple est bon est facile (dautant plus quil nest pas « t même complet), mais ne vous aide pas immédiatement. Lastuce consiste à surveiller, au fur et à mesure que vous écrivez et étendez votre code, les fonctions qui font des choses similaires ou fonctionnent sur les mêmes types (qui pourraient être des candidats pour leur propre module), ainsi que les fonctions qui font beaucoup de choses séparées qui ne sont pas » t vraiment lié, et pourraient être des candidats à la scission.
Commentaires
- Pouvez-vous maider à comprendre pourquoi le hongrois est évité? Juste curieux den savoir plus à ce sujet. 🙂
- @JNL: Un commentaire est trop court pour être expliqué correctement. Je vous suggère de le poster comme une nouvelle question.
-
with low coupling and high cohesion
. Quest-ce que cela signifie? Et veuillez expliquer les types de cookies opaques. Je nai aucune idée de ce que cela signifie. - Jai essayé de répondre brièvement et franchement, jai échoué à la concision. Jespère que cela devrait vous aider a commencé.
- Je réponds après quelques jours. Désolé pour cela. Jai lu votre description de
low coupling and high cohesion
. Donc, cela signifie essentiellement encapsuler les choses quand je le peux et il doit être fait de manière à ce que les fonctions qui en ont réellement besoin devraient y avoir accès. Certaines choses mont dépassé la tête, mais je pense quand même avoir compris votre point.
Réponse
À mon avis 90 % du problème de dénomination est résolu si vous gardez trois choses à lesprit: a) rendez vos noms de variables et de fonctions aussi descriptifs que possible, b) être cohérent dans tout votre code (cest-à-dire, si une fonction est nommée addNumbers, une deuxième fonction doit être nommée multiplyNumbers et non numbersMul) et c) essayez de rendre les noms courts si possible, car nous devons les taper.
Cela étant dit, si vous souhaitez examiner dautres aspects de ce sujet, la page Wikipédia sur les Conventions de dénomination contient une bonne liste de choses que vous devriez Gardez à lesprit. Il a également une section sur C et C ++:
En C et C ++, les mots-clés et les identifiants 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 mot (par exemple out_of_range). Les identificateurs 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 dutiliser des identificateurs entièrement en majuscules pour les constantes). Les noms contenant un double trait de soulignement ou commençant par un trait de soulignement et une majuscule sont réservés pour limplémentation (compilateur, bibliothèque standard) et ne doivent pas être utilisés (par exemple, reserved__ ou _Reserved). [5] [6] Ceci est superficiellement similaire au stropping, mais la sémantique diffère: les traits de soulignement font partie de la valeur de lidentifiant, plutôt que dêtre des guillemets (comme le stropping): la valeur de __foo est __foo (qui est réservé), pas foo (mais dans un espace de noms différent).
Commentaires
- " essayez de rendre les noms courts si possible " Utilisez un IDE avec saisie semi-automatique, alors vos noms de fonctions peuvent être aussi longs et descriptifs que nécessaire, car vous en avez seulement besoin à taper une fois.
- @Joel terrible conseil. Tout le monde nutilisera pas le même IDE que vous.
- @James Ils nont ' pas besoin, ils peuvent simplement utiliser nimporte quel IDE décent. Ensuite, vous navez ' à sacrifier la clarté au profit de la productivité.
- Le terme IDE est un peu trop court depuis quelques jours. Techniquement, Notepad ++ est un IDE car vous pouvez le configurer pour compiler et exécuter votre projet, mais ' est avant tout un éditeur de texte. Et il se termine automatiquement.
Réponse
La seule contrainte dure en C est quil ny a pas despaces de noms. Par conséquent, vous devez trouver un moyen de différencier la fonction rename()
de votre bibliothèque système de fichiers de la rename()
fonction de votre bibliothèque media . La solution habituelle est un préfixe, tel que: filesystem_rename()
et media_rename()
.
Lautre conseil général est: restez cohérente au sein dun projet ou dune équipe. La lisibilité sera améliorée.
Commentaires
- +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 un renommage de fonction exporté.
Réponse
SI VOUS CHERCHEZ UN MONDE FORMAT ACCEPTÉ
MISRA / JSF / AUTOSAR couvre presque 100% de toutes les normes de lindustrie pour nommer et organiser le code C / C ++. Le problème est quils ne seront pas gratuits, cest-à-dire que chacun des guides coûte de largent. 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 de Harvard pour la bibliographie et la lecture supplémentaire lorsque vous écrivez un journal. Jai utilisé MISRA et cest un bon moyen de nommer vos fonctions et variables, et de les organiser pour une utilisation correcte.
SI VOUS CHERCHEZ QUELQUE CHOSE DE TEMPORAIRE
Les références que vous avez fournies pour Python et Java sont correctes, je suppose. Jai vu des gens adopter le style javadoc pour commenter, nommer et organiser le code. En fait, dans mon dernier projet, jai 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 nont pas touché le terrain des normes de systèmes logiciels critiques pour la sécurité.
3) Le code hérité était (dune manière ou dune autre) dans ce format.
4) Doxygen autorisait les commentaires de style Javadoc. À ce moment-là, nous utilisions doxygen pour générer de la documentation pour les gars de la production.
De nombreux programmeurs seront opposés à cela, mais je pense personnellement quil ny a rien de mal à adopter le nom de fonction / variable de style javadoc en C / C ++. OUI BIEN, les pratiques dorganisation de votre contrôle de flux, de sécurité des threads, etc. doivent être abordées de toute façon. Cependant, je ne suis pas candidat ici. Je ne sais pas non plus à quel point vos exigences en matière de format de code de production sont strictes. Sans le détourner vers une zone hors sujet, je vous suggère de revoir vos exigences, de découvrir dans quelle mesure vous dépendez dune convention de dénomination spécifique et dopter pour une solution mentionnée dans les miennes et dautres « réponses
Jespère que cela a aidé !?
Commentaires
- En fait, je demandais ceci pour des codes C personnels . Mais je ' je me souviendrai de votre suggestion.
- @AseemBansal Personnel ou professionnel, ce sont bons à apprendre et aussi bons à mettre sur votre CV 🙂 … . À vous de décider.
Réponse
Peu de choses importantes à prendre en compte lors de la dénomination seraient;
-
Regardez le type actionObject ou ObjectAction. (Object Not for C. Mais en général lorsque vous passez à dautres Langages Orientés Objet) Cela devrait aider
-
Le repos serait COHÉRENT, bref et descriptif à coup sûr.
- un seul but de chaque variable et fonction définie, par exemple: si cest pour stocker une valeur temporairement, nommez-le comme nTempVal pour int
- Les variables doivent être des noms et les méthodes doivent être des verbes.
Commentaires
- La notation hongroise (préfixer une variable avec des lettres indiquant le type) conduit à la douleur sans fin. Il est heureusement passé de mode.
- @StevenBurnap Était simplement curieux de savoir pourquoi le format hongrois est-il évité? Je crois que ' est ce qu’ils nous ont appris à l’école et j’ai également vu ce code dans certains lieux de travail. Lequel recommanderiez-vous sinon le hongrois. Merci
- La meilleure convention de dénomination est juste une convention constamment utilisée, avec des noms clairs et descriptifs idéalement maintenus relativement courts sans abréviation excessive et en évitant les préfixes redondants. La notation hongroise a peu dutilité réelle, rend le code plus difficile à lire et rend le changement de type plus difficile.
- Voici une description de lintention originale et de labomination que la notation hongroise est devenue: joelonsoftware.com/articles/Wrong.html
- @Residuum Cétait un bon lien. Jai beaucoup aidé. Je lapprécie.
Réponse
La plupart des réponses sont bonnes, mais je veux dire quelques choses sur la dénomination conventions pour les bibliothèques et les fichiers inclus, similaire à lutilisation despaces de noms dans dautres langages comme C ++ ou Java:
Si vous construisez une bibliothèque, trouvez un préfixe commun pour vos symboles exportés, cest-à-dire les fonctions globales, les typedefs et les variables. Cela évitera les conflits avec dautres bibliothèques et identifiera les fonctions comme venant de la vôtre. Ceci est un peu des notations hongroises des applications.
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.Donc, en plus dutiliser 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 un handle curl_multi_ * semble maintenant incorrect, voir les noms des fonctions à http://curl.haxx.se/libcurl/c/
En gardant les règles pour les symboles exportés, vous devriez utiliser celles pour les fonctions statiques dans #include
ed fichiers: essayez de trouver un préfixe commun pour ces fonctions. Peut-être avez-vous des fonctions utilitaires de chaînes statiques dans un fichier appelé « ma_ chaîne »? Préfixez toutes ces fonctions avec my_string_ *.
Commentaires
- Par symboles exportés, vous entendez les variables globales, les fonctions, les typedefs, etc. Pouvez-vous expliquer le regroupement des symboles exportés? Je pensais que vous aviez déjà expliqué cela dans le paragraphe précédent. Quavez-vous ajouté dans le troisième paragraphe?
order.c
, vous pouvez nommer les fonctionsorder_add()
,order_del()
et autres. Il peut y avoir danciens systèmes qui vous indiquent que le nom doit être unique dans les 8 premiers caractères. Lorsque vous passez ultérieurement à C ++ par accident, vous ' adorerez écrireorder::add()
etorder::del()
alors.