9
votes

Normes de codage / codage Meilleures pratiques en C ++

Considérez les deux segments de code ci-dessous. Lequel est le meilleur et pourquoi? Si tu avoir une autre idée, s'il vous plaît faire mention. Où puis-je trouver des réponses à Des pratiques de codage comme celles-ci? Si tu sont conscients de tout livre / article, S'il vous plaît partager.

// code 1 xxx

// code2 xxx

Le code de nettoyage de Robert C. Martin est un bon livre qui traite de cela. Mais, je suppose que ce livre est enclin à Java.

Mise à jour:

  1. j'ai obligé de manière obligatoire do {} alors que (0); boucle comme je n'ai pas voulu utiliser goto.

  2. Je voulais me débarrasser de nombreuses déclarations si et rompre, donc j'ai proposé le code 2.

    Ce que je peux voir sur les réponses est un ensemble mixte de réponses pour le code1 et le code2. Il y a des gens qui préfèrent les goto aussi bien comparés au code 1 (que je pensais être meilleur).


2 commentaires

Plus vous avez des moyens de quitter une boucle / une fonction, plus un programmeur de maintenance qui doit la modifier dans quelques années le fera bu.


@Bill: C'est vrai si les déclarations de retour sont dispersées partout. Si vous avez des «clauses de garde» (comme dans la solution de Andy), les énoncés de retour représentant les conditions d'erreur sont tous recueillis et rendent le code restant très propre.


17 Réponses :


6
votes

Cela dépend vraiment des attentes futures du code. Le code1 ci-dessus implique qu'il peut y avoir une logique supplémentaire à ajouter pour chacune des conditions; Le code2 ci-dessus implique plutôt qu'il existe un regroupement rationnel des conditionnels. Le code1 peut être plus pertinent si vous vous attendez à ajouter une logique pour les conditions ultérieures; Si vous ne le faites pas, le code2 est probablement plus sensible à cause de la brièveté et du regroupement impliqué.


0 commentaires

40
votes

Je n'aime pas vraiment utiliser une boucle de fonctionnement / tandis que de cette façon. Une autre façon de le faire serait de casser votre conditionnel dans Code2 dans des chèques séparés. Celles-ci sont parfois appelées "clauses de garde".

bool MyApplication::ReportGenerator::GenerateReport()
{
    if (!isAdmin())
        return false;

    if (!isConditionOne())
        return false;

    // etc.

    return generateReport();

}


5 commentaires

Amen! Je n'ai jamais compris la mentalité que "les retours précoces ne sont pas autorisés". Cela mène à ce genre de désordre précisément, où un faible codeur ressemble à ce qu'ils doivent être forcés entre pervertir une construction de boucle et utiliser un goto.


De plus, cette technique est plus sûre que la mise en place de nombreux appels de fonction dans une déclaration si , si l'une de ces fonctions a des effets secondaires, étant donné que l'ordre d'évaluation peut ne pas être garanti.


@Steve: L'ordre d'évaluation est très garanti d'être laissé à droite, && -before- || , sauf si vous avez surchargé opérateur et < / code> et / ou opérateur || , puis vous devez être puni pour cela (à moins que vous soyez un contributeur de boost - ils sont autorisés :)


@mmutz: Je pense que moi-depuis - il y a 6 mois aurait pu penser à une évaluation paresseuse, par exemple Si (myfunc11 () && myfunc2 ()) {...} - Sauf si la norme indique que si le premier opérande est faux, la seconde ne doit pas être évaluée. Voir aussi Stackoverflow. com / questions / 1354138 / ... .


@Steve: Oui, la norme garantit que pour les opérateurs logiques. La question que vous référence concerne le bit-wise & , qui est une bête différente.



1
votes

Personnellement, je préfère l'échantillon 2. Il regroupe ces éléments qui n'entraîneront pas le rapport généré ensemble.

En ce qui concerne les directives générales de codage, le code de livre complète ( Amazon) est une bonne référence pour le codage de problèmes de style.


0 commentaires

4
votes

Qui pensez-vous le mieux ce que le code essaie de dire. Lequel avez-vous besoin de travailler le plus difficile pour comprendre?

Je ferais cela: xxx

parce que:

a). Préférez dire ce que je veux plutôt que ce que je ne veux pas b). Préfère la symétrie, si et bien. Clairement tous les cas couverts.


1 commentaires

Pas nécessaire mais (IMHO) meilleur style. Pour la raison, j'ai essayé d'expliquer. L'équilibre de si et d'autre facilite la compréhension de l'intention de l'auteur. Mon objectif est d'écrire un code clair, de ne pas utiliser la construction la plus minimale.



8
votes
bool MyApplication::ReportGenerator::GenerateReport(){
    if ( ! isAdmin         () ) return false ;
    if ( ! isConditionOne  () ) return false ;
    if ( ! isConditionTwo  () ) return false ;
    if ( ! isConditionThree() ) return false ;
    return generateReport() ;
}

1 commentaires

C'est la solution d'Andy présentée magnifiquement :)



-2
votes

J'ai utilisé de la même manière que dans des circonstances différentes, mais que vous avez surchargé le premier IMO:

bool MyApplication::ReportGenerator::GenerateReport(){
    bool retval = false;
    if (!isAdmin()){
    }
    else if (!isConditionOne()){
    }
    else if (!isConditionTwo()){
    }
    else if (!isConditionThree()){
    }
    else
        retval = generateReport();
    return retval;
}


2 commentaires

Je n'aime pas les déclarations manquantes à la suite de la tête si / sinon si. Il semble incomplet ou inachevé et je dois énoncer ce que votre intention était.


Bien mieux qu'un faire avec des pauses ... imo



3
votes

En ce qui concerne l'exemple 1: Si vous voulez aller, pourquoi n'écrivez-vous pas goto ??? C'est beaucoup plus clair que votre suggestion. Et compte tenu de ce que goto ne devrait être utilisé que rarement, je vote pour # 2.


1 commentaires

Fausse dichotomie. Il y a plus de solutions de rechange et les deux codes montrés sont particulièrement hideux. Bien que n ° 2 soit au moins logique.



26
votes

Je préférerais personnellement une variation de votre deuxième segment de code. Le court-circuit fonctionnera de la même manière, mais le conditionnel est moins verbeux.

bool MyApplication::ReportGenerator::GenerateReport()
{
    if(isAdmin() && isConditionOne() && isConditionTwo() && isConditionThree())
    {
        return generateReport();
    }

    return false;
}


3 commentaires

+1: Bien mieux de convertir les tests en positifs plutôt que des négatifs.


J'espère 'ou' est préféré sur "et" dans un chèque comme celui-ci, comme si celui-ci devient vrai (Isadmin () - Faux) dans if (! Isadmin () ||) Sautera probablement la vérification des autres conditions.


@Manikanda Je m'attendrais à ce que le court-circuit fonctionne de la même manière dans les deux cas. Si nous organisons des conditions, alors si une condition est fausse, le débit doit "ignorer les autres conditions" (ci-circuit). D'autre part, si nous organisons des conditions annulées, alors encore, si une condition est fausse, il devrait y avoir un court-circuit. Je suis d'avis que la syntaxe anded est plus lisible que la syntaxe négative ou la syntaxe.



4
votes

code 1 est, IMO, pire, car il ne transmet pas immédiatement le sens de l'intendant qui consiste à générer le repoort uniquement dans certaines circonstances.

Utilisation: p>

 bool MyApplication::ReportGenerator::GenerateReport(){
     if (!isAdmin()        || !isConditionOne() ||
         !isConditionTwo() || !isConditionThree()) {
        return false;
     }
     return generateReport();
 }


1 commentaires

+1 pour simplement utiliser un goto plutôt que de faire / tout en imiter un goto. Les gotos ne sont pas toujours mal.



5
votes

Je préfère une modification de l'échantillon 2: xxx

Il bénéficie d'un seul point de sortie pour la fonction, recommandé pour faciliter la maintenance. Je trouve des conditions d'empilement verticalement au lieu de plus facilement lire rapidement, et il est beaucoup plus facile de commenter des conditions individuelles si vous en avez besoin.


1 commentaires

Celui que je préfère, c'est beaucoup plus simple et cool si vous utilisez une seule déclaration de retour dans une fonction. Forcer cette habitude d'utiliser un seul retour nous fera un code plus lisible et utile dans un grand projet.



0
votes

Un commutateur serait une meilleure solution à votre problème, je pense. Vous auriez besoin de surcharger la méthode de prise dans un paramètre INT et je ne sais pas si c'est quelque chose que vous voudriez faire ou non.

Bool MyApplication::ReportGenerator::GenerateReport(int i)
{
  switch(i)
  {
    case 1:
       // do something
       break;
    case 2:
       // do something
       break;
   // etc
 }
 return GeneratReport()
}


0 commentaires

17
votes
bool MyApplication::ReportGenerator::GenerateReport()
{
   return isAdmin()  
      && isConditionOne() 
      && isConditionTwo()
      && isConditionThree()
      && generateReport();    // Everything's ok.
}

7 commentaires

Nice, mais pour moi juste un peu aussi "intelligent". Comme je l'ai lu, j'ai besoin de changer mentalement engrenage lorsque j'atteigne l'expression génératrice ().


Clever, mais je pense que si je l'ai écrit, je devrais mettre un commentaire devant lui.


C'est un gros pita si vous déboguez et que vous voulez entrer dans Isconiorthree () sans entrer dans toutes les précédentes.


Non, ne fais pas ça. C'est encore pire que d'imiter le goto avec un commutateur et une pause.


Ensuite, placez un point d'arrêt sur la ligne 'Isconditionhree ()' ou directement à l'intérieur de la fonction. Ou commenter les conditions nécessaires si vous souhaitez tester des conditions / combinaisons spécifiques.


@erikkallen, voudriez-vous s'il vous plaît élaborer? Le code de Houlalala est très propre et concis.


Ce code ne fonctionne que vraiment lorsque votre fonction renvoie un booléen. Pour la raison de débogage @graeme mentionné et la réchauffement réduite mentionnée par @djna, il est beaucoup préférable de briser chaque test dans des circuits courts à une seule doublure. En outre, plus facile à diffuser dans la commande source plus tard.




0
votes

Code Complete est un livre communément recommandé qui passe en détail sur ces types de problèmes stylistiques. Envisagez également de jeter un coup d'œil à certains des guides de style d'organisation publiés pour voir s'ils ont des opinions sur la question; Guide de style de Google , par exemple.

sur ce que je préfère, le deuxième exemple est beaucoup mieux à mon esprit. Le premier est essentiellement un abus du do {} tout en construisant pour éviter d'utiliser un goto, collant dogmatiquement à la lettre "Éviter les gotos à tout prix" tout en manquant son esprit de "Code de clarté, n'utilise pas de tours de langue inobvie" . P>

En fait, la seule raison d'utiliser un goto du tout serait de coller dogmatiquement à une approche «une seule déclaration de retour par fonction» lorsque vous pourriez vous éloigner avec un simple, lisible p>

if (!isAdmin()){
    return false;
}
else if (!isConditionOne()){
    return false;    }
else if (!isConditionTwo()){
    return false;    }
else if (!isConditionThree()){
    return false;    }
else
    return generateReport();


0 commentaires

0
votes

Personnellement, je préfère mon pour , tandis que et do ... tandis que Les boucles sont des boucles réelles. Dans le premier exemple de code, ce n'est pas le cas. Donc, je choisirais par exemple 2. ou, comme d'autres d'autres l'ont déjà dit, pour avoir enfreint l'exemple 2 dans un certain nombre de si ... renvoyer les déclarations .


0 commentaires

4
votes

J'aime les réponses qui sont une variante de la version 2, mais juste pour donner une alternative: si ces conditions sont logiquement liées ensemble, il y a de fortes chances que vous fassiez vérifier à nouveau dans d'autres endroits. Si cela est vrai, peut-être qu'une fonction d'assistance ferait mieux le travail. Quelque chose comme ceci: xxx

Comme cette fonction est petite, vous pouvez peut-être même l'aligner (ou laisser le compilateur décider;)). Un autre bonus est que si vous voulez inclure des contrôles supplémentaires à l'avenir, il vous suffit de changer cette fonction et non tous les endroits où il est utilisé.


1 commentaires

Tout ce que vous avez fait est de déplacer le problème de style sur IsRePortable () qui va maintenant regarder exactement la même chose que d'autres exemples ici, à l'exception de la dernière ligne sera retourne vrai; .



2
votes

Mon habitude est d'éviter les blocs IF de cette façon:

bool MyApplication::ReportGenerator::GenerateReport(){
    bool report = !( isAdmin()        || isConditionOne() || 
                     isConditionTwo() || isConditionThree() );
    return report ? generateReport() : false; 
}


1 commentaires

Je pense que vous devriez remplacer le || avec && .