Come prevenire le indentazioni profonde? [chiuso]

16

Quali misure e misure posso adottare per evitare profonde indentazioni nel mio codice?

    
posta Tom Wijsman 09.09.2010 - 23:21
fonte

9 risposte

14

Il rientro profondo è di solito non un problema se ogni funzione / metodo nel tuo programma fa una sola cosa. Occasionalmente, potrebbe essere necessario per nidificare condizionali di qualche livello, ma posso onestamente dire che ho scritto solo codice profondamente rientrato una manciata di volte in 12+ anni di programmazione.

    
risposta data 10.09.2010 - 00:05
fonte
26

La cosa migliore che puoi fare è estrarre i metodi:

int Step1(int state)
{
    if (state == 100)
    {
        return Step2(state);
    }
    else
    {
        return Step3(state);
    }
}

int Step2(int state)
{
    if (state != 100)
    {
        throw new InvalidStateException(2, state);
    }

    // ....
}
    
risposta data 09.09.2010 - 23:28
fonte
16

Forse potresti prendere in considerazione clausole di protezione ?

invece di

public void DoSomething(int value){
    if (someCondition){
           if(someOtherCondition){
                if(yetAnotherCondition){
                       //Finally execute some code
                }
           }
    }
} 

Do

public void DoSomething(int value){
    if(!(someCondition && someOtherCondition && yetAnotherCondition)){
        return;
        //Maybe throw exception if all preconditions must be true
    }
    //All preconditions are safe execute code
}

Se mai ne hai la possibilità ti consiglio di leggere Code Complete di Steve McConnell. Ha molti ottimi consigli su questi argomenti.

link

Per ulteriori informazioni sulle "clausole di guardia" vedi: link

    
risposta data 14.08.2011 - 21:44
fonte
8

Inverti il tuo if s.

Invece di:

if (foo != null)
{
    something;
    something;
    if (x)
    {        
       something;
    }
    something;
}
else
{
    boohoo;
}

Scriverò:

if (foo == null)
{
    boohoo;
    return;
}
something;
something;
if (x)
{        
   something;
}
something;

Lo stesso vale per if - else blocchi. Se else è più breve / meno nidificato, quindi ripristinali.

Controlla i valori dei parametri in un unico punto

Controlla tutti i parametri per i valori non validi non appena inserisci il tuo metodo, quindi procedi sapendo che sei al sicuro. Rende il codice più leggibile, ma ti consente anche di accumulare blocchi condizionali in un secondo momento e di diffondere questi controlli su tutta la subroutine.

    
risposta data 15.08.2011 - 13:35
fonte
4

In genere, ho visto che il codice profondamente rientrato è in genere un codice problematico. Se stai affrontando questo problema, fai un passo indietro e valuta se la tua funzione sta facendo troppe cose.

Allo stesso tempo, per rispondere alla tua domanda, se c'è un bisogno di indentazione così profonda, ti suggerirei di lasciarlo lì. Per la semplice ragione che in tale codice, l'indentazione aiuterà poiché è probabile che sia un pezzo di codice molto lungo.

    
risposta data 21.09.2010 - 16:55
fonte
2

Rompi i componenti nidificati (specialmente quelli ripetuti) in funzioni separate (questo è più facile se la tua lingua supporta le chiusure) o sostituisci una serie di cicli annidati con una ricorsione.

Inoltre, induisci due spazi anziché quattro.

    
risposta data 10.09.2010 - 08:16
fonte
1

Non vedo rientri profondi come un problema categoriale da rimuovere (né vedo refactoring come la vera risposta per tutto).

Tipicamente invece di if annidati, mi piace scrivere affermazioni logiche:

if (foo && bar && baz) 

anziché

if foo 
 if bar
   if baz
    
risposta data 22.09.2010 - 19:24
fonte
1

Non ci credevo, ma secondo Code Complete questo è un posto appropriato per usare break (se la tua squadra è a bordo). Immagino che questo sia più accettabile con i programmatori C ++, dove break è usato in switch statement rispetto ai programmatori Delphi in cui break è usato solo quando non hai voglia di scrivere un ciclo while .

    
risposta data 08.10.2010 - 15:55
fonte
0

L'indentazione è davvero un modo per combattere, anzi. Quello che ho imparato a fare è dividere prima il metodo in pezzi, poi usare un trucco strano per saltare ogni pezzo successivo se un pezzo fallisce. Ecco un esempio:

Invece di:

 {if (networkCardIsOn() == true)
     {if (PingToServer() == true)
        {if (AccesLogin(login,pass) == true)
             {if (nextCondition == true)
                ...
         }
     }
 }

Attualmente scrivo:

 {vbContinue = true;

 if (vbContinue) {
       vbContinue = networkCardIsOn();
       if (vbContinue == false) {
             code to Handle This Error();
       } 
 }

 if (vbContinue) {
       vbContinue = PingToServer();
       if (vbContinue == false) {
             code to HandleThisError2();
       } 
 }

 if (vbContinue) {
       vbContinue = AccesLogin(login,pass);
      if (vbContinue == false) {
             HandleThisErrorToo();
       } 
 }
 ...

Questo mi è sembrato strano all'inizio, ma dal momento che lo uso, i costi di manutenzione sono stati divisi per metà e il mio cervello è più fresco alla fine della giornata.

In effetti, il guadagno introdotto da questa "tecnica" è che la complessità del codice è realmente divisa perché il codice è meno denso.

Durante la lettura del codice, non devi ricordare nulla delle condizioni passate: se sei a quel punto X nel codice, i passaggi precedenti vengono passati e sono riusciti.

Un altro vantaggio è che "percorso e condizione di fuga" da tutti quelli annidati "if-else" è semplificato.

    
risposta data 22.09.2010 - 12:12
fonte

Leggi altre domande sui tag