Modo più leggibile per formattare lungo se le condizioni? [chiuso]
https://softwareengineering.stackexchange.com/questions/3450
-
16-10-2019 - |
Domanda
Long winding condizioni if
dovrebbe essere evitato se possibile, eppure a volte siamo tutti finiscono per scriverli. Anche se si tratta di una condizione molto semplice, le dichiarazioni coinvolti sono a volte semplicemente molto prolisso, in modo che l'intera condizione finisce per essere molto lungo. Qual è il modo più leggibile per formattare quelli?
if (FoobarBaz::quxQuux(corge, grault) || !garply(waldo) || fred(plugh) !== xyzzy) {
thud();
}
o
if (
FoobarBaz::quxQuux(corge, grault)
|| !garply(waldo)
|| fred(plugh) !== xyzzy
) {
thud();
}
o
if (FoobarBaz::quxQuux(corge, grault)
|| !garply(waldo)
|| fred(plugh) !== xyzzy) {
thud();
}
o
thudable = FoobarBaz::quxQuux(corge, grault);
thudable ||= !garply(waldo);
thudable ||= fred(plugh) !== xyzzy;
if (thudable) {
thud();
}
o qualsiasi altre preferenze?
Soluzione
Spesso, un lungo se la condizione è il segno di codice che deve refactoring, ma a volte non si può evitare. In questi casi, io preferisco la prima:
if (bar || baz || quux) { ... }
Perché tu sei in grado di dire che cosa sta succedendo con una linea. Tuttavia, mi piacerebbe molto meglio fare qualcosa di simile, quando possibile:
function foo() {
return bar || baz || quux;
}
if (foo()) { ... }
Altri suggerimenti
I come tenere gli operatori al fine di indicare seguito:
if (the_function_being_called() != RETURNCODE_SUCCESS &&
the_possibly_useful_recovery_strategy() == RETURNCODE_EPICFAIL &&
this_user_has_elected_to_recieve_error_reports)
{
report_error();
}
Sono un grande fan di nomi di variabili significative:
const bool isInAStrangeCondition =
FoobarBaz::quxQuux(corge, grault) ||
!garply(waldo) ||
fred(plugh) !== xyzzy;
if (isInAStrangeCondition) {
thud();
}
O refactoring come una funzione, come detto sopra.
I rompere le sottoespressioni Messier, o tutti loro, come variabili bool. Poi la logica booleana di livello superiore del 'se' dichiarazione può essere chiaro. Nel tipo di lavoro che faccio, non è sempre diverse cose ORed o ANDed.
bool goodblah = some_mess < whatever;
bool frobnacious = messy_crud != junky_expression;
bool yetanother = long_winded_condition;
if (goodblah || (frobnacious && yetanother)) {
...
}
Ciò è particolarmente utile in un debugger, dove posso guardare tutti i Caccio prima di eseguire il 'se'.
I tendono ad allineare gli operatori all'inizio di nuove linee così mi ricordo come sto combinando termini (sia a lungo logica e lungo l'aritmetica). In questo modo:
if (first_attempt(data) == SUCCESS
|| (reusable(data) && second_attempt(data) == SUCCESS)
|| (still_reusable(data) && third_attempt(data) == SUCCESS))
return SUCCESS;
Questo funziona solo se mi trattino da 2-spazi o set impostato il mio ambiente di predicati più righe di rientro più, altrimenti sarebbe difficile dire dove finisce predicato e codice utile comincia.
Sono un fan dei seguenti:
if (really_long_expression && another_really_really_long_expression &&
another_very_long_expression_OMG_id_it_long){
bugs();
}
In questo modo appare ancora come un se espressione e non un caso espressione down to-pezzi rotti. Il rientro aiuta a dimostrare che si tratta di una continuazione della linea precedente.
È anche possibile rientro fino a quando la parentesi di apertura si trova alla fine della riga precedente in modo che sia alla fine del se espressione come si suppone che sia.