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é:
- choisissez une convention et respectez-la
- par exemple,
function_like_this(struct TypeLikeThis variable)
est commun
é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.
é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 FILE
est é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 setsockopt
pour 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.