ti-enxame.com

A maneira mais legível de formatar longas condições?

As condições de enrolamento longo if devem ser evitadas, se possível, mas às vezes todos acabamos escrevendo-as. Mesmo que seja uma condição muito simples, as declarações envolvidas às vezes são simplesmente muito prolixo, portanto toda a condição acaba sendo muito longa. Qual é a maneira mais legível de 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?

45
deceze

Freqüentemente, uma condição longa se é o sinal do código que precisa ser refatorado, mas às vezes você não pode evitá-lo. Nesses casos, eu 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()) { ... }
32
user8

Eu gosto de manter os operadores no final para indicar a 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();
}
21
AShelly

Sou um grande 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, conforme mencionado acima.

12
LennyProgrammers

Divido 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 há 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 eu posso ver todos os bools antes de executar o 'if'.

7
DarenW

Tendo a alinhar os operadores no início de novas linhas, lembro-me de como estou combinando termos (tanto para lógica longa quanto para aritmética longa). Como isso:

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 recuar por 2 espaços ou definir o meu ambiente para recuar mais predicados de várias linhas, ou então seria difícil dizer onde o predicado termina e o código útil começa.

6
Hoa Long Tam

Sou fã do seguinte:

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

Dessa forma, ainda parece uma expressão if e não uma expressão if quebrada em pedaços. 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, para que fique no final da expressão if como deveria estar.

0
EpsilonVector