90 votes

Si déclaration - évaluation de court-circuit vs lisibilité

Parfois, une instruction if peut être assez compliquée ou longue, il est donc préférable, pour des raisons de lisibilité, d'extraire les appels compliqués avant le if.

par exemple, cela:

if (SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall())
{
    // faire quelque chose
}

devient ceci

bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();

if (b1 || b2)
{
    //faire quelque chose
}

(l'exemple donné n'est pas si mal, c'est juste pour l'illustration... imaginez d'autres appels avec plusieurs arguments, etc.)

Mais avec cette extraction, j'ai perdu l'évaluation de circuit court (SCE).

  1. Est-ce que je perds vraiment SCE à chaque fois? Y a-t-il un scénario où le compilateur est autorisé à "l'optimiser" tout en fournissant toujours SCE?
  2. Y a-t-il des moyens de conserver la lisibilité améliorée du deuxième extrait sans perdre SCE?

118voto

Horia Coman Points 6847

Une solution naturelle ressemblerait à ceci :

bool b1 = SomeCondition();
bool b2 = b1 || SomeOtherCondition();
bool b3 = b2 || SomeThirdCondition();
// toute autre condition
bool bn = bn_1 || SomeFinalCondition();

if (bn)
{
  // faire quelque chose
}

Cela présente l'avantage d'être facile à comprendre, applicable à tous les cas et ayant un comportement de court-circuit.


C'était ma solution initiale : Un bon motif dans les appels de méthodes et les corps de boucles for est le suivant :

if (!SomeComplicatedFunctionCall())
   return; // ou continuer

if (!SomeOtherComplicatedFunctionCall())
   return; // ou continuer

// faire quelque chose

On obtient les mêmes avantages de performance agréables de l'évaluation en court-circuit, mais le code semble plus lisible.

31voto

AmigoJack Points 622

Je tends à répartir les conditions sur plusieurs lignes, par exemple :

if( SomeComplicatedFunctionCall()
 || OtherComplicatedFunctionCall()
  ) {

Même lorsque vous traitez avec plusieurs opérateurs (&&), il vous suffit de faire avancer l'indentation avec chaque paire de crochets. SCE entre toujours en jeu - pas besoin d'utiliser de variables. Écrire du code de cette manière a rendu la lecture beaucoup plus facile pour moi depuis des années déjà. Exemple plus complexe :

if( one()
 ||( two()> 1337
  &&( three()== 'foo'
   || four()
    )
   )
 || five()!= 3.1415
  ) {

28voto

Joachim Pileborg Points 121221

Si vous avez de longues chaînes de conditions et que vous souhaitez conserver une partie du court-circuit, vous pouvez utiliser des variables temporaires pour combiner plusieurs conditions. En reprenant votre exemple, il serait possible de faire par exemple :

bool b = SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
if (b && some_other_expression) { ... }

Si vous avez un compilateur compatible C++11, vous pouvez utiliser des expressions lambda pour combiner des expressions en fonctions, de manière similaire à ce qui précède :

auto e = []()
{
    return SomeComplicatedFunctionCall() || OtherComplicatedFunctionCall();
};

if (e() && some_other_expression) { ... }

21voto

SJuan76 Points 16867

1) Oui, vous n'avez plus SCE. Sinon, vous auriez cela

bool b1 = SomeComplicatedFunctionCall();
bool b2 = OtherComplicatedFunctionCall();

fonctionne d'une manière ou d'une autre selon s'il y a une déclaration if plus tard. Bien trop complexe.

2) C'est basé sur l'opinion, mais pour des expressions raisonnablement complexes, vous pouvez faire :

if (SomeComplicatedFunctionCall()
    || OtherComplicatedFunctionCall()) {

Si c'est trop complexe, la solution évidente est de créer une fonction qui évalue l'expression et l'appeler.

21voto

KIIV Points 2626

Vous pouvez également utiliser :

bool b = someComplicatedStuff();
b = b || otherComplicatedStuff(); // it has to be: b = b || ...;  b |= ...; is bitwise OR and SCE is not working then 

et SCE fonctionnera.

Mais ce n'est pas beaucoup plus lisible que par exemple :

if (
    someComplicatedStuff()
    ||
    otherComplicatedStuff()
   )

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