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 !

34voto

paercebal Points 38526

Utiliser les vecteurs et les chaînes de caractères au lieu des tableaux de style C et des chars *.

Utilisez std::vecteur chaque fois que vous devez créer un tampon de données, même si la taille est fixe.

Utilisez std::string chaque fois que vous avez besoin d'une chaîne de caractères.

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

std::vector : L'utilisateur d'un vecteur peut toujours trouver sa taille, et le vecteur peut être redimensionné si nécessaire. Il peut même être donné (par la notation (&(myVector[0])) à une API C. Bien sûr, le vecteur nettoiera après lui-même.

std::string : Et le fait qu'il sera toujours correctement initialisé, qu'il ne peut pas être dépassé, qu'il gérera les modifications avec élégance, comme les concaténations, les assignations, etc. et de manière naturelle (en utilisant des opérateurs au lieu de fonctions).

32voto

Ferruccio Points 51508

Gardez les fonctions à une taille raisonnable. Personnellement, j'aime garder les fonctions en dessous de 25 lignes. La lisibilité est améliorée lorsque vous pouvez considérer une fonction comme une unité plutôt que de devoir la parcourir de haut en bas pour essayer de comprendre comment elle fonctionne. Si vous devez faire défiler le texte pour le lire, cela ne fait qu'empirer les choses.

31voto

Dustin Getz Points 8514

affirmer toutes les hypothèses, y compris les hypothèses temporaires, comme le comportement non implémenté. assert les conditions d'entrée et de sortie des fonctions si elles ne sont pas triviales. assert tous les états intermédiaires non triviaux. votre programme ne devrait jamais planter sans qu'une assert n'échoue d'abord. vous pouvez personnaliser votre mécanisme assert pour ignorer les occurrences futures.

Utilisez un code de gestion des erreurs pour les conditions que vous vous attendez à voir se produire ; utilisez des assertions pour les conditions qui ne devraient jamais se produire. La gestion des erreurs vérifie généralement les mauvaises données d'entrée ; les assertions vérifient les bogues dans le code.

Si le code de gestion des erreurs est utilisé pour traiter une condition anormale, la gestion des erreurs permettra au programme de répondre à l'erreur avec élégance. Si une assertion est déclenchée pour une condition anormale, l'action corrective ne consiste pas simplement à gérer une erreur de manière élégante - l'action corrective consiste à modifier le code source du programme, à recompiler et à publier une nouvelle version du logiciel. Une bonne façon d'envisager les assertions est de les considérer comme de la documentation exécutable - vous ne pouvez pas compter sur elles pour faire fonctionner le code, mais elles peuvent documenter les hypothèses plus activement que les commentaires du langage du programme [1].

  1. McConnell, Steve. Code Complete, deuxième édition. Microsoft Press © 2004. Chapitre 8 - Programmation défensive

29voto

paercebal Points 38526

Savoir qui est le propriétaire de que la mémoire.

  • créer des objets sur la pile autant que possible (pas de new inutile)
  • Éviter le transfert de propriété, sauf si cela est vraiment nécessaire
  • Utiliser le RAII et les pointeurs intelligents
  • Si le transfert de propriété est obligatoire (sans pointeurs intelligents), alors, documentez clairement le code (les fonctions doivent avoir un nom non ambigu, en utilisant toujours le même modèle de nom, comme "char * allocateMyString()" et "void deallocateMyString(char * p)".

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

Ne pas avoir une philosophie claire sur la propriété de la mémoire conduit à des bugs intéressants ou à des fuites de mémoire, et à une perte de temps à se demander si le char * retourné par cette fonction doit être désalloué par l'utilisateur, ou non, ou redonné à une fonction spéciale de désalllocation, etc.

Dans la mesure du possible, la fonction/objet qui alloue la mémoire doit être la fonction/objet qui la désalloue.

27voto

Luc Hermitte Points 14171

Remarque : n'imposez pas le SESE ( Entrée unique Sortie unique ) (c'est-à-dire qu'il ne faut pas interdire plusieurs return l'utilisation de break / continue /...)

En C++, c'est une utopie car throw est un autre point de retour. SESE avait deux avantages en C et dans les langages sans exception :

  • la libération déterministe des ressources, qui est maintenant gérée de façon claire par l'idiome RAII en C++,
  • rendre les fonctions plus faciles à maintenir, cela ne devrait pas être un problème puisque les fonctions doit être courts (comme le veut la règle "une fonction, une responsabilité")

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