A maneira mais legível para formatar longas condições? [fechadas]

38

Condições if de enrolamento longo devem ser evitadas sempre que possível, mas às vezes todos terminamos por escrevê-las. Mesmo que seja uma condição muito simples, as declarações envolvidas às vezes são simplesmente muito verbosas, então a condição toda acaba sendo muito longa. Qual é a maneira mais legível para formatar esses?

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 outras preferências?

    
por deceze 14.09.2010 / 07:23
fonte

6 respostas

29

Geralmente, uma condição longa se é o sinal de código que precisa de refatoração, mas às vezes você não pode evitá-lo. Nesses casos, prefiro o primeiro:

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

Porque você é capaz de dizer o que está acontecendo com uma linha. No entanto, prefiro fazer algo assim, quando possível:

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

if (foo()) { ... }
    
por 14.09.2010 / 07:27
fonte
16

Eu gosto de manter os operadores no final para indicar continuação:

if (the_function_being_called() != RETURNCODE_SUCCESS &&
    the_possibly_useful_recovery_strategy() == RETURNCODE_EPICFAIL &&
    this_user_has_elected_to_recieve_error_reports)
{
    report_error();
}
    
por 14.09.2010 / 07:53
fonte
9

Sou muito fã de nomes de variáveis significativos:

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

if (isInAStrangeCondition) {
    thud();
}

Ou refatorar como uma função, como mencionado acima.

    
por 14.09.2010 / 08:44
fonte
7

Eu quebro as subexpressões mais confusas, ou todas elas, como variáveis booleanas. Em seguida, a lógica booleana de nível superior da instrução 'if' pode ser esclarecida. No tipo de trabalho que faço, nem sempre são várias coisas ORed ou ANDed.

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

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

Isso é especialmente bom em um depurador, onde posso ver todos os bools antes de executar o 'if'.

    
por 14.10.2010 / 18:28
fonte
6

Costumo alinhar os operadores no início de novas linhas, então lembro como estou combinando termos (tanto para lógica longa como para aritmética longa). Assim:

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

Isso só funciona se eu indentar por dois espaços ou definir meu ambiente para recuar mais predicados multilinha, ou então seria difícil dizer onde o predicado termina e o código útil começa.

    
por 14.09.2010 / 08:33
fonte
0

Sou fã dos seguintes:

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

Desta forma, ainda parece uma expressão if e não uma expressão if-down-to-pieces if. O recuo ajuda a mostrar que é uma continuação da linha anterior.

Você também pode recuá-lo até que o colchete de abertura esteja no final da linha anterior, de forma que esteja no final da expressão if como deveria ser.

    
por 14.09.2010 / 07:39
fonte