web-dev-qa-db-fra.com

Le moyen le plus lisible de formater longtemps si les conditions?

Les conditions d'enroulement long if doivent être évitées si possible, mais parfois nous finissons tous par les écrire. Même si c'est une condition très simple, les déclarations impliquées sont parfois tout simplement très verbeuses, donc la condition entière finit par être très longue. Quelle est la façon la plus lisible de les formater?

if (FoobarBaz::quxQuux(corge, grault) || !garply(waldo) || fred(plugh) !== xyzzy) {
    thud();
}

ou

if (
    FoobarBaz::quxQuux(corge, grault)
 || !garply(waldo)
 || fred(plugh) !== xyzzy
) {
    thud();
}

ou

if (FoobarBaz::quxQuux(corge, grault)
    || !garply(waldo)
    || fred(plugh) !== xyzzy) {
    thud();
}

ou

thudable = FoobarBaz::quxQuux(corge, grault);
thudable ||= !garply(waldo);
thudable ||= fred(plugh) !== xyzzy;

if (thudable) {
    thud();
}

ou d'autres préférences?

45
deceze

Souvent, une condition longue est le signe du code qui doit être refactorisé, mais parfois vous ne pouvez pas l'éviter. Dans ces cas, je préfère le premier:

if (bar || baz || quux) { ... }

Parce que vous pouvez dire ce qui se passe avec une seule ligne. Cependant, je préfère de loin faire quelque chose comme ça, lorsque cela est possible:

function foo() {
  return bar || baz || quux;
}

if (foo()) { ... }
32
user8

J'aime garder les opérateurs à la fin pour indiquer la suite:

if (the_function_being_called() != RETURNCODE_SUCCESS &&
    the_possibly_useful_recovery_strategy() == RETURNCODE_EPICFAIL &&
    this_user_has_elected_to_recieve_error_reports)
{
    report_error();
}
21
AShelly

Je suis un grand fan des noms de variables significatifs:

const bool isInAStrangeCondition =
    FoobarBaz::quxQuux(corge, grault) ||
    !garply(waldo) ||
    fred(plugh) !== xyzzy;

if (isInAStrangeCondition) {
    thud();
}

Ou refactoriser en fonction, comme mentionné ci-dessus.

12
LennyProgrammers

Je décompose les sous-expressions plus désordonnées, ou toutes, en tant que variables booléennes. La logique booléenne de niveau supérieur de l'instruction "if" peut alors être clarifiée. Dans le genre de travail que je fais, ce n'est pas toujours plusieurs choses OU ou OU.

bool goodblah = some_mess < whatever;
bool frobnacious = messy_crud != junky_expression;
bool yetanother = long_winded_condition;

if (goodblah || (frobnacious && yetanother))   {
    ...
}

C'est particulièrement bon dans un débogueur, où je peux regarder tous les bools avant d'exécuter le "si".

7
DarenW

J'ai tendance à aligner les opérateurs au début de nouvelles lignes, donc je me souviens comment je combine les termes (à la fois pour la longue logique et la longue arithmétique). Comme ça:

if (first_attempt(data) == SUCCESS
    || (reusable(data) && second_attempt(data) == SUCCESS)
    || (still_reusable(data) && third_attempt(data) == SUCCESS))
  return SUCCESS;

Cela ne fonctionne que si je fais un retrait de 2 espaces ou que je définis un environnement plus en retrait pour les prédicats multilignes, sinon il serait difficile de dire où se termine le prédicat et où commence le code utile.

6
Hoa Long Tam

Je suis fan de ce qui suit:

if (really_long_expression && another_really_really_long_expression && 
            another_very_long_expression_OMG_id_it_long){
    bugs();
}

De cette façon, il ressemble toujours à une expression if et non à une expression if en morceaux. L'indentation aide à montrer qu'il s'agit d'une continuation de la ligne précédente.

Vous pouvez également le mettre en retrait jusqu'à ce que le crochet d'ouverture soit à la fin de la ligne précédente afin qu'il se trouve à la fin de l'expression if telle qu'elle est censée être.

0
EpsilonVector