31 votes

Les éléments les plus importants d'une norme de codage C++ légère

J'ai participé à l'élaboration de normes de codage assez élaborées. D'après ma propre expérience, il est difficile de les faire respecter si l'on ne dispose pas de processus appropriés pour les maintenir et de stratégies pour les faire respecter.

Aujourd'hui, je travaille et je dirige un environnement où il est encore moins probable que des processus et des stratégies de suivi soient mis en place depuis longtemps. Je veux néanmoins maintenir un niveau minimum de code respectable. J'ai donc pensé que je pourrais obtenir de bonnes suggestions ici, et que nous pourrions ensemble produire un sous-ensemble raisonnable et léger des pratiques standard de codage les plus importantes pour que d'autres puissent l'utiliser comme référence.

Donc, pour souligner l'essentiel ici :

Quels éléments d'une norme de codage C++ sont les plus importants à respecter ?

  • Règles de réponse/vote

    • 1 candidat par réponse, de préférence avec un bref motivation.

    • Vote négatif candidats qui se concentrent sur le style et les directives de formatage subjectives. Il ne s'agit pas d'indiquer qu'elles sont sans importance, mais seulement qu'elles sont moins pertinentes dans ce contexte.

    • Vote négatif les candidats se concentrant sur la manière de commenter/documenter le code. Il s'agit d'un sujet plus vaste qui pourrait même mériter son propre billet.

    • Votez pour des candidats qui facilitent clairement un code plus sûr, qui minimise le risque de bogues énigmatiques, qui augmente la maintenabilité, etc.

    • Ne votez pas dans n'importe quelle direction sur les candidats dont vous avez des doutes. Même s'ils semblent raisonnables et intelligents, ou au contraire "quelque chose que personne n'utiliserait", votre vote doit être basé sur une compréhension claire et une expérience.

0 votes

Il est probable que vous créiez ici une collection de règles incohérentes, dont la plupart ne résoudront pas les problèmes résultant d'un comportement indéfini.

1 votes

Une autre approche consiste à prendre une norme de codage existante (par exemple AV JSF, MISRA C++, www.codingstandard.com) et à afficher les règles qui vous semblent être de bons candidats.

0 votes

Comment le style peut valoir un vote négatif. Vous demandez les meilleures pratiques dans les normes, puis vous insistez pour ignorer les meilleures. Un code où chacun choisit sa propre convention de nommage (par exemple) est le moins lisible possible. Votez comme vous voulez, mes frères !

4voto

unwind Points 181987

Si la chaîne d'outils utilisée (ou dont l'utilisation est prévue) a une implémentation inefficace de exceptions il peut être judicieux d'éviter leur utilisation. J'ai travaillé dans de telles conditions.

Mise à jour : aquí est le raisonnement de quelqu'un d'autre pour le "C++ intégré", qui semble exclure les exceptions. Il présente les points suivants :

  • Il est difficile d'estimer le temps entre le moment où une exception s'est produite et celui où le contrôle est passé à un gestionnaire d'exception correspondant.
  • Il est difficile d'estimer la consommation de mémoire pour la gestion des exceptions.

Il y a un texte plus élaboré sur cette page, je ne voulais pas tout copier. De plus, elle a 10 ans, elle n'est peut-être plus utile, c'est pourquoi j'ai inclus la partie concernant la chaîne d'outils. Peut-être devrait-on également lire "si la mémoire n'est pas considérée comme un problème majeur", et/ou "si une réponse prévisible en temps réel n'est pas nécessaire", etc.

4voto

Jasper Bekkers Points 4949

Noms de méthodes et de variables dans un schéma de dénomination commun pour des raisons de cohérence ; je n'ai pas tendance à être dérangé par autre chose lorsque je lis les sources.

4voto

Luc Hermitte Points 14171

L'héritage public doit modéliser le principe de substitution de Liskov (LSP).

La réutilisation/importation de code sans substituabilité doit être implémentée avec l'héritage privé lorsqu'un couplage très fort a un sens, ou avec l'agrégation sinon.

4voto

paercebal Points 38526

Attention à l'API C

L'API C peut être très efficace, mais nécessitera l'exposition de données brutes (c'est-à-dire des pointeurs, etc.), ce qui n'aidera pas à la sécurité du code. Utilisez plutôt l'API C++ existante, ou encapsulez l'API C avec du code C++.

Par exemple :

// char * d, * s ;
strcpy(d, s) ; // BAD

// std::string d, s ;
d = s ;        // GOOD

Ne jamais utiliser strtok

strtok n'est pas réentrant. Ce qui signifie que si une strtok est lancée alors qu'une autre n'est pas terminée, l'une corrompra les "données internes" de l'autre.

Comment cela facilite clairement un code plus sûr, qui minimise le risque de bogues énigmatiques, qui augmente la maintenabilité, etc ?

L'utilisation de l'API C implique l'utilisation de types bruts, ce qui peut conduire à des bogues intéressants tels que le dépassement de tampon (et la corruption potentielle de la pile) lorsqu'un sprintf va trop loin (ou le détournement de chaîne lors de l'utilisation de snprintf, qui est une sorte de corruption de données). Même en travaillant sur des données brutes, malloc peut être facilement abusé, comme le montre le code suivant :

int * i = (int *) malloc(25) ; // Now, I BELIEVE I have an array of 25 ints!
int * j = new int[25] ;        // Now, I KNOW I have an array of 25 ints!

Etc. etc.

Quant à strtok : C et C++ sont des langages à pile, qui permettent à l'utilisateur de ne pas se soucier des fonctions qui se trouvent au-dessus des siennes sur la pile, et des fonctions qui seront appelées en dessous des siennes sur la pile. strtok supprime cette liberté de "ne pas se soucier".

4voto

Évitez d'utiliser le constructeur de copie généré et l'opérateur= par défaut.

  • Si vous voulez que votre objet soit copiable.
    • Si chaque attribut peut être copié de manière triviale, commentez clairement que vous utilisez délibérément le constructeur de copie implicite et l'opérateur=.
    • Sinon, écrivez vos propres constructeurs, en utilisant le champ d'initialisation pour initialiser les attributs et en suivant l'ordre de l'en-tête (qui est le véritable ordre de construction).
  • Si vous ne savez toujours pas ( option par défaut ) ou si vous pensez ne pas vouloir copier les objets d'une certaine classe, déclarez son constructeur de copie et son opérateur= comme privés. De cette façon, le compilateur vous fera savoir quand vous faites quelque chose que vous ne voulez pas faire.

    class foo
    {
       //...
    private:
       foo( const foo& );
       const foo& operator=( const foo& );
    };

Ou dans un manière plus propre si vous utilisez le boost :

    class foo : private boost::noncopyable
    {
      ...
    };

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X