Mi vengono in mente almeno due argomenti a favore di lunghe funzioni:
Significa che hai un sacco di contesto attorno ad ogni riga. Un modo per formalizzare questo: disegna il grafico del flusso di controllo del tuo codice. A un vertice (~ = linea) tra l'ingresso e l'uscita della funzione, si conoscono tutti i bordi in entrata. Più lunga è la funzione, più ci sono tali vertici.
Molte piccole funzioni indicano che esiste un grafico delle chiamate più ampio e complesso. Scegli una linea casuale in una funzione casuale e rispondi alla domanda "in quale contesto (i) viene eseguita questa linea?" Questo diventa più difficile quanto più grande e complesso è il grafico della chiamata, perché devi guardare più vertici in quel grafico.
Ci sono anche argomenti contro le lunghe funzioni: mi viene in mente la testabilità dell'unità. Usa t̶h whene̶ ̶f̶o̶r̶c̶e̶ la tua esperienza quando scegli tra l'una e l'altra.
Nota: non sto dicendo che il tuo capo ha ragione, solo che la sua prospettiva potrebbe non essere completamente priva di valore.
Penso che il mio punto di vista sia che il buon parametro di ottimizzazione non sia la lunghezza della funzione. Penso che un desiderato più utile da pensare in termini di sia il seguente: a parità di tutti gli altri, è preferibile poter leggere dal codice una descrizione di alto livello sia della logica aziendale sia dell'implementazione. (I dettagli di implementazione di basso livello possono sempre essere letti se riesci a trovare il bit di codice rilevante.)
Commentando la risposta di David Arno :
Scrivere piccole funzioni è una seccatura perché ti costringe a spostarti in ogni piccola funzione per vedere cosa sta facendo il codice.
Se la funzione è ben denominata, non è così. isApplicationInProduction è evidente e non dovrebbe essere necessario esaminare il codice per vedere cosa fa. In realtà è vero il contrario: esaminare il codice rivela meno l'intenzione rispetto al nome della funzione (motivo per cui il tuo capo deve ricorrere ai commenti).
Il nome rende evidente quale sia il valore di ritorno means , ma non dice nulla circa gli effetti di esecuzione del codice (= ciò che il codice fa ). Nomi (solo) trasmettono informazioni relative intenti , codice trasmette informazioni circa il comportamento (da quali parti l'intento possono talvolta essere dedotti).
A volte ne vuoi uno, a volte l'altro, quindi questa osservazione non crea una regola di decisione universalmente valida unilaterale.
Metti tutto in un grande loop principale anche se il loop principale è più di 300 righe, è più veloce da leggere
Potrebbe essere più veloce scansionare, ma per "leggere" veramente il codice, devi essere in grado di eseguirlo efficacemente nella tua testa. È facile con piccole funzioni ed è molto, molto difficile con metodi lunghi 100 linee.
Sono d'accordo che devi eseguirlo nella tua testa. Se hai 500 linee di funzionalità in una grande funzione rispetto a molte piccole funzioni, non mi è chiaro perché questo diventa più facile.
Supponiamo che il caso estremo di 500 righe di codice a linea retta che abbia un forte effetto collaterale e che si desideri sapere se l'effetto A si verifica prima o dopo l'effetto B. Nel caso della grande funzione, utilizzare Pagina su / giù per individuare due linee e poi confrontare numeri di riga. Nel caso di molte piccole funzioni, devi ricordare dove si verificano gli effetti nell'albero delle chiamate e, se ti sei dimenticato, devi dedicare un tempo non banale alla riscoperta della struttura di questo albero.
Quando si attraversa l'albero delle chiamate delle funzioni di supporto, si deve anche affrontare la sfida di determinare quando si è passati dalla logica aziendale ai dettagli di implementazione. Sostengo senza prove * che più semplice è il grafico della chiamata, più facile è fare questa distinzione.
(*) Almeno ne sono onesto ;-)
Ancora una volta, penso che entrambi gli approcci abbiano punti di forza e di debolezza.
Scrivi solo piccole funzioni se devi duplicare il codice
Non sono d'accordo. Come mostra il tuo esempio di codice, piccole funzioni ben definite migliorano la leggibilità del codice e dovrebbero essere utilizzate ogni volta che [ad esempio] non sei interessato al "come", solo al "cosa" di una funzionalità.
Se sei interessato al "come" o al "cosa" è una funzione dello scopo per cui stai leggendo il codice (ad es. Ottenere un'idea generale o rintracciare un bug). Lo scopo per cui stai leggendo il codice non è disponibile durante la scrittura del programma e molto probabilmente leggerai il codice per scopi diversi; decisioni diverse ottimizzeranno per scopi diversi.
Detto questo, questa è la parte del punto di vista del capo con cui probabilmente non sono più d'accordo.
Non scrivere una funzione con il nome del commento, inserisci la tua complessa riga di codice (3-4 righe) con un commento sopra. In questo modo è possibile modificare direttamente il codice in errore
Non riesco davvero a capire il ragionamento alla base di questo, supponendo che sia davvero serio. [...] I commenti hanno un difetto fondamentale: non sono compilati / interpretati e quindi non possono essere testati in unità. Il codice viene modificato e il commento viene lasciato solo e si finisce per non sapere quale sia giusto.
I compilatori confrontano i nomi solo per uguaglianza, non ti danno mai un errore fuorviante. Inoltre, poiché diversi siti di chiamata possono invocare una determinata funzione in base al nome, a volte è più arduo e soggetto a errori cambiare un nome. I commenti non hanno questo problema. Tuttavia, questo è in qualche modo speculativo; per risolverlo davvero, probabilmente avremmo bisogno di dati sul fatto se i programmatori hanno maggiori probabilità di aggiornare commenti fuorvianti rispetto a nomi fuorvianti, e io non ce l'ho.