2013-08-15 8 views
15

Ho installato una beta di Netbeans 7.4, e c'è un nuovo suggerimento che dice "Troppi blocchi annidati nella dichiarazione di funzione - è buona norma introdurre nuove funzioni ...".Perché è consigliabile evitare blocchi nidificati in una funzione? (PHP)

Cerco di evitare blocchi nidificati all'interno di una funzione per una migliore leggibilità, ma c'è qualche altra ragione per cui questa sarebbe una migliore "idea", specificamente per PHP, se questo è importante.

+1

Di solito è uno di questi: (a) a molti se-else, tempo per il polimorfismo (b) a molto se si va avanti, estendendo la classe e modificando solo un po 'di comportamento richiederebbe reimplementare una funzione enorme invece di solo un po. Come in ogni regola, ci sono naturalmente delle eccezioni. – Wrikken

+4

Questa domanda sembra essere fuori tema perché riguarda la pratica di programmazione generale. Probabilmente è più adatto a programmers.stackexchange.com ma non esiste un'opzione di migrazione per quel sito – GordonM

risposta

20

Il nome formale per questo è Cyclomatic Complexity.

Questa è una misura della complessità di una funzione, in base al numero di "punti di decisione" nella funzione. Più alto è il numero, più complessa è la funzione.

La complessità è determinata dal numero di punti di decisione in un metodo più uno per l'immissione del metodo. I punti decisionali sono "se", "while", "for" e "case label". Generalmente, 1-4 è a bassa complessità, 5-7 indica complessità moderata, 8-10 è alta complessità e 11+ è una complessità molto elevata.

(tratto da http://phpmd.org/rules/codesize.html)

Il motivo è considerato male avere i valori di complessità troppo alto è perché rende la funzione difficile da testare.

Per testare una funzione al suo massimo potenziale, è necessario disporre di un test separato per ogni possibile percorso di codice. Il numero di percorsi di codice aumenta in modo esponenziale con ogni nuovo punto di decisione, il che significa che quando avrai più di una manciata di decisioni in una singola funzione, inizierai a richiedere centinaia di test per essere sicuro di aver coperto il problema tutta la gamma di funzionalità che potrebbe eseguire.

Centinaia di test per una singola funzione sono chiaramente troppi, quindi l'opzione migliore è ridurre il numero di punti decisionali per funzione suddividendolo in diverse funzioni più piccole con meno decisioni ciascuna.

È inoltre necessario rendere le funzioni discrete in modo che non si facciano affidamento l'uno sull'altro per l'esecuzione. Ciò consente loro di essere testati separatamente l'uno dall'altro. (altrimenti hai ancora il problema originale di troppe decisioni in una singola chiamata)

Puoi quindi testare ciascuna di queste funzioni con solo una manciata del numero di test che avresti originariamente richiesto.

Il processo di test delle funzioni in isolamento tra loro è denominato Unit Testing. Questo è un argomento molto ampio di per sé, ma vale la pena studiarlo se vuoi saperne di più sulle buone pratiche di sviluppo del software.

Dal momento che hai codificato questa domanda PHP, vi puntare nella direzione di alcuni strumenti che aiutano a mgiht:

  • PHP Unit - questo è il pacchetto di test di unità standard de-facto per PHP.
  • PHPMD - "PHP Mess Detector"; uno strumento per analizzare il tuo codice per cercare cose come l'eccessiva complessità.
  • pDepend - Un altro strumento simile.

Ci sono un sacco di altri strumenti disponibili, ma questo è probabilmente sufficiente per iniziare; conosci prima quelli. Incontrerai gli altri in modo naturale mentre studi l'argomento.

1

Un buon vantaggio è limitare l'ambito. Riducendo il blocco a un metodo separato rendi chiaro ai futuri lettori che questo blocco di codice dipende solo dai parametri forniti.

In pseudo-codice

$some_variable = "something"; 
$some_other_variable = "something else"; 
if(x < y) { 
    ... lots of code ... 
    some_method($some_variable); 
    ... more code ... 
} 

Estraendo il condizionale a un metodo individuale, diventa chiaro che la logica all'interno di tale ramo non dipende $some_other_variable.

Se si dispone di metodi grandi con un sacco di ramificazioni e un sacco di variabili, diventa più difficile mantenere il metodo ed è più probabile che si interrompa inavvertitamente qualcosa.

1

Il codice Fancy provoca incubi di manutenzione ... Almeno nel modello KISS, mantienilo semplice, e il tuo debugging sarà un gioco da ragazzi.

Questa risposta mantiene al modello di BACIO, è una risposta semplice

2

In generale, le funzioni/metodi sono scritti bene se lo fanno solo una cosa, ma farlo bene.

Quando un metodo inizia a mostrare nidificazione oltre 1 o 2 livelli è un segno sicuro che sta provando a fare più di una cosa alla volta.

Quando c'è un sacco di nidificazione e condizionali in una funzione, rende anche la sua logica più complicata e difficile da seguire, oltre che più difficile da testare in modo robusto.

Infine, se c'è una funzionalità sepolta in un nido in un altro metodo, non è possibile riutilizzarla facilmente. Dovrai tagliarlo e incollarlo dove vuoi utilizzarlo (il che porta sempre a un incubo di manutenzione) o aggiungere un altro switch aggiuntivo e un altro condizionale al metodo di hosting (che esacerba il problema). Se si refactoring tale funzionalità nel proprio metodo di riutilizzo è banale.

Problemi correlati