Linee guida per la codifica: i metodi non devono contenere più di 7 affermazioni?

76

Stavo osservando le Linee guida per la codifica AvSol per C # e sono d'accordo con quasi tutto, ma sono davvero curioso di vedere cosa pensano gli altri di una regola specifica.

AV1500

Methods should not exceed 7 statements A method that requires more than 7 statements is doing too much, or has too many responsibilities. It also requires the human mind to analyze the exact statements to understand what the code is doing. Break it down in multiple small and focused methods with self-explaining names.

La maggior parte di voi segue questa regola? Anche se c'è poco da salvare dalla creazione di un nuovo metodo (il tuo codice è ancora DRY ) oltre a una notevole leggibilità ? E il tuo numero è ancora a 7? Tenderei di più verso il 10.

Non sto dicendo che violento questa regola dappertutto - al contrario, i miei metodi sono al 95% piccoli e concentrati, ma dire che non dovresti mai violare questa regola mi ha davvero sconvolto.

Voglio solo sapere cosa pensano tutti di non violare MAI questa regola (è un '1' sullo standard di codifica - che significa MAI farlo). Ma penso che avresti problemi a trovare un codebase che non lo fa.

    
posta brian 29.07.2014 - 12:16
fonte

17 risposte

194

Questo è un "odore standard" per me. Ogni volta che vedo standard di codifica con limiti specifici in loro, mi preoccupo. Ci si imbatte quasi sempre in un caso in cui un metodo deve essere più grande di quanto consentito dallo standard (indipendentemente dalla lunghezza della linea / numero, numero di variabili, numero di punti di uscita, ecc.). Gli standard dovrebbero essere più simili a linee guida e consentire un margine sufficiente per esercitare un buon giudizio. Non fraintendermi, è bello avere degli standard, ma non dovrebbero diventare "microgestione per procura".

    
risposta data 27.02.2012 - 16:39
fonte
82

Di solito è una buona idea dividere le cose in piccoli metodi. Ma l'importante è dividere le cose dove ha senso.

Se non ha senso dividere, allora non dividere. Questo è spesso il caso per alcune procedure o codice GUI.

Steve McConnell dichiarato in Codice completo che non si è sempre più produttivi quando si utilizzano metodi brevi. Se dividi quando non ha senso, aggiungi complessità al codice senza alcun beneficio.

Come sempre con le linee guida, è bene ricordare perché esistono i vincoli, quindi puoi imparare quando non si applica. Nella maggior parte del codice i metodi saranno brevi, o probabilmente hai un problema con DRY o separazione dei dubbi . Ma se non è il caso, allora va bene.

    
risposta data 27.02.2012 - 19:45
fonte
28

Dovrebbe essere considerato una regola empirica.

Cose come "Non più di 80 (100.120) colonne di testo", "un punto di uscita per metodo", "non più di 2 livelli di nidificazione", sono quelle che chiamerei soglie per gli indicatori di odore di codice. Se li violate occasionalmente, quello non significa necessariamente che il codice è cattivo. Se ti ritrovi a violarle in modo coerente, allora qualcosa odora nel codice e potresti voler fare una pausa e ripensare al tuo approccio.

Per me, i criteri più importanti sono: "Questo codice è comprensibile?", "È ripetitivo?", "È suddiviso in posti logici?", "È accoppiato in modo approssimativo?" Ce ne sono alcuni altri, ma penso che l'idea di base possa essere riassunta ricordando il consiglio di Donald Knuth: "I programmi sono pensati per essere letti dagli umani e solo incidentalmente per i computer da eseguire."

    
risposta data 27.02.2012 - 17:45
fonte
18

Non mi sono mai preso il tempo di contare realmente il numero di affermazioni nei miei metodi, ma mi sforzo di scrivere metodi che eseguano in modo pulito uno scopo unico e chiaro. Finché il tuo codice è pulito, leggibile e segue DRY e Single Responsibility principi, probabilmente hai fatto il tuo lavoro. Penso che dividere arbitrariamente un metodo a parte solo per far rispettare il limite di sette istruzioni potrebbe rendere il tuo codice meno leggibile / mantenibile.

    
risposta data 27.02.2012 - 16:32
fonte
11

È approssimativo

Questo tipo di regole non dovrebbero essere prese troppo alla lettera. Avrebbero potuto dire che i " metodi dovrebbero essere brevi ". Tuttavia, alcune persone l'avrebbero interpretato come "meno di 1 pagina" e altri come "2 righe al massimo."

Supporrei che abbiano detto "7 affermazioni" per darti un'idea approssimativa (anche se penso che avrebbero dovuto dire "circa 7"). Se hai bisogno di 9 una volta ogni tanto, non preoccuparti. Ma se stai colpendo 20, saprai che non sei nel campo giusto per questa regola.

    
risposta data 27.02.2012 - 18:25
fonte
10

7 è un numero completamente arbitrario senza alcun significato.

La complessità ciclica è un problema più grande del numero di affermazioni. Ho visto il codice che aveva centinaia di istruzioni in un unico metodo (che pensavo fosse terribile), ma aveva una complessità ciclomatica di 1 e in realtà faceva solo 1 cosa. C'erano solo molti passaggi. Abbiamo discusso suddividendolo in metodi più piccoli, ma quei metodi sarebbero stati chiamati solo con questo metodo.

Anche se questo è un caso abbastanza estremo, il punto è che è necessario mantenere il codice ASCIUTTO e una bassa complessità ciclomatica. Questo è più importante del numero di linee in un metodo.

Ad esempio, prendi l'istruzione switch / case. Se hai più di 7 valori possibili hai bisogno di rompere la valutazione in più metodi? Certo che no, sarebbe sciocco.

Rompere artificialmente il codice in più metodi solo per mantenere il numero di istruzioni sotto 7 rende solo il codice peggiore.

La linea guida dovrebbe essere Ogni metodo dovrebbe fare 1 cosa e mantenere il tuo codice ASCIUTTO.

    
risposta data 28.02.2012 - 09:54
fonte
4

Beh, dipende un po '. Scrivo molto codice che accede ai database. Il codice della piastra della caldaia per la gestione delle eccezioni è più che sette dichiarazioni lunghe in molti casi. Direi che la migliore linea guida è assicurarsi che la tua funzione abbia uno scopo

    
risposta data 27.02.2012 - 16:40
fonte
4

Tutto è un compromesso. Il problema con l'approccio proposto - il refactoring in diversi metodi e classi in modo che ogni metodo sia breve - è che, sebbene per ragioni diverse, porta a un codice illeggibile quando viene portato all'estremo.

Immagina un metodo foo() che fa 7 cose. Potresti obiettare che 7 cose sono troppe. Forse in molti casi hai ragione. D'altra parte, queste 7 cose potrebbero essere strettamente correlate; la logica può fluire senza intoppi e leggere come prosa; potresti non avere problemi a comprenderlo quando ne hai veramente bisogno. Quello che potrebbe finire molto peggio è avere queste 7 cose distribuite su un grande albero di sorgenti, così che se guardi foo() non hai idea di cosa faccia senza guardare in 7 posti diversi.

Molte persone hanno regole come questa nella loro testa, e il risultato è quello che penso come spaghetti OO. Tutto è pulito, inscatolato nel suo piccolo metodo o classe, con micro-transazioni atomiche che si verificano in ogni luogo. Ma è impossibile arrivare alla base di questo codice e sapere cosa sta facendo. Ti perdi.

    
risposta data 27.02.2012 - 17:57
fonte
4

non è una cattiva linea guida. Non mi sono mai pentito di aver diviso i metodi e le classi (non ho mai trovato di averne troppe) purché siano raggruppati e correlati abbastanza bene.

Il trucco è NON dividerlo verticalmente (basta pizzicare un metodo su un punto e avviarne uno nuovo). Il trucco, come con il test delle unità, è quello di tenere a mente una simile regola sin dall'inizio in modo da progettare in modo migliore, passare il 3 o il 4 istruzioni a metà metodo a un altro metodo perché avere una chiamata al metodo descrive ciò che stai facendo meglio di quelle 3 o 4 dichiarazioni nel mezzo del tuo codice.

Questo tipo di suddivisione, anche se arbitraria e utilizzata solo una volta, può portare a successivi migliori refactoring a causa di una nuova chiarezza del codice, questo vale anche per le classi più piccole.

Pensa a come faresti un test unitario. Se provi ad aggiungere test unitari dopo il fatto che è difficile ea volte sembra impossibile, ma se lo elabori dall'inizio, in realtà rende tutto il tuo codice migliore.

Sommario? Se si confronta l'odore del design di "Utilizzare meno di 7 affermazioni" per l'odore del codice di "Ho usato più di 7 affermazioni", preferirei eliminare l'odore del codice.

    
risposta data 27.02.2012 - 19:31
fonte
4

Wow! Non mi sarei mai aspettato di trovare una discussione così intensa su una semplice linea guida che dice approssimativamente che i tuoi metodi dovrebbero essere molto piccoli. Poiché sono sempre sviluppatori che vogliono che le loro linee guida siano esplicite, ho scelto 7 perché sembrava una bella soglia.

Alcuni di voi hanno già citato il disclaimer all'inizio del documento. Ma per essere chiari, questo documento rappresenta una raccolta di linee guida che cercano di aiutare a scrivere codice migliore e progettare sistemi migliori. Non ho mai affermato che qualsiasi cosa dovrebbe essere una regola, anche se una linea guida è contrassegnata come livello 1. Questi livelli sono semplicemente l'opinione collettiva delle molte persone che hanno utilizzato questo documento per un po '.

Inoltre non ho mai preteso di essere un esperto. Ma sono stato in questa professione da 15 anni, con circa 4 anni di esperienza in C ++ e 11 anni di esperienza in C #. Originariamente era basato su Industrial Strength C ++, ma da allora l'ho perfezionato con gli input della community.

Indipendentemente da ciò, il punto che stavo cercando di sollevare è che dovresti continuare a pensare da solo. Se pensate che la linea guida delle 7 affermazioni non sia utile, fatela semplicemente di più. Diamine, ho persino violato quella linea guida una volta ogni tanto. Lo violento in modo pazzesco e accetto le conseguenze.

    
risposta data 28.02.2012 - 20:50
fonte
3

In primo luogo: è una linea guida, non una regola. Si chiama una linea guida, quindi per favore trattala come tale. Ciò implica che anche il tuo giudizio è richiesto (come sempre)

A parte questo, posso pensare ad abbondanti esempi di buon codice che non aderiscono a questo vincolo. Anche se è solo una linea guida, è scarsa.

    
risposta data 27.02.2012 - 23:28
fonte
2

Sono d'accordo con la dichiarazione sopra di me. Questa è solo una linea guida e in un mondo perfetto tutto sarebbe oggetto, riutilizzato in ogni programma, e il mondo sarebbe un posto bellissimo. Non è sempre vero e a volte ciò comporterebbe un sovraccarico di risorse o sprechi. Devi metterlo a mente anche.

    
risposta data 27.02.2012 - 18:42
fonte
2

Abbastanza sciocco quando aggiungi la gestione delle eccezioni nella miscela.

Dopo "prova, prendi, finalmente" ti rimangono quattro istruzioni per metodo!

Considera anche un metodo "validateForm" per un modulo di 20 campi, anche se gestisci tutte le singole convalide in metodi separati hai ancora 20 metodi di convalida dei campi da richiamare. Secondo queste linee guida si finirebbe con una divisione inutile come "validateTopOfScreen", "validateMiddleOfScreen" e "validateBottomOfScreen".

    
risposta data 28.02.2012 - 09:21
fonte
2

La domanda è fondere "regole" con "linee guida". Le regole devono essere rispettate - le linee guida sono consigli che servono a farti prendere in considerazione ciò che stai facendo e se davvero potrebbe essere fatto in un modo migliore.

Direi che, in media, la maggior parte della programmazione è probabilmente migliorata seguendo le linee guida, ma ci saranno sempre casi in cui seguire le linee guida dogmaticamente causerà più problemi di quanti non intendessero risolvere. Ecco perché non vengono presentati come regole, ma come linee guida.

Un precedente rispondente ha dimostrato che gli autori delle linee guida non hanno mai inteso che fossero applicati dogmaticamente e includevano dichiarazioni in tal senso nel loro documento.

    
risposta data 29.02.2012 - 16:40
fonte
0

Sono d'accordo con Soe dei commenti sopra. 7 per me è arbitrario e potrebbe essere utile in alcune lingue dove Ruby, ma per le lingue come C #, Java, C ++ dubito di questa convenzione "7 linee". Permettetemi di darvi un esempio. La mia attuale applicazione ha 22 campi di testo e io eseguo la validazione lato server. Il metodo è chiamato validateInput () e la mia preferenza è di convalidare tutti i campi in un metodo stesso, a meno che non abbia convalidato qualcosa di complesso come checkEmailFormat (). Quindi in pratica il mio codice del metodo validateInput è di 108 righe con chiamate occasionali a convalida complessa.

Ora immagina se ho chiamato 25 metodi per convalidare ogni campo. Se arriva un nuovo sviluppatore, dovrà entrare e uscire dal metodo principale per saltare attraverso 25 metodi che a loro volta potrebbero chiamare altri. È destinato a perdersi in grandi progetti.

Ciò che davvero faccio per rendere chiaro il mio codice è fornire commenti chiari che in pratica dicono che cosa stanno facendo queste 4 righe -

validateInput (UserObj user) {

// Convalida il nome ....... ......

// convalida il cognome ...... ......

// convalida la posta elettronica ..... // troppo complesso per controllare l'espressione regolare del formato di posta elettronica checkEmailFormat (); .... .....

e così via .. }

    
risposta data 29.02.2012 - 03:26
fonte
0

Cattiva regola. Con il codice per la gestione delle eccezioni, l'impostazione dei campi del database, la convalida, in che modo la maggior parte dei metodi può essere inferiore a sette istruzioni? Non dovremmo mai fare funzioni lambda in linea?

Le linee di codice sono un conteggio arbitrario di complessità. Con i metodi di estensione posso creare un codice come

                Parallel.ForEach(regions, region => {   Console.Write(region.Resorts.Where(x => x.name == "Four Seasons").OrderBy(x => x.RegionId).ThenBy(x => x.ResortId).ThenBy(x => x.name).ToList());   });
    
risposta data 01.03.2012 - 20:41
fonte
-1

Tutti i programmatori junior dovrebbero essere obbligati ad aderire a questo principio. Ciò li costringerebbe a pensare alla struttura di ciò che sono occupati, invece di aggiungere semplicemente un numero sempre maggiore di code code.

Attualmente sto esaminando un metodo di 550 righe di codice con un sacco di istruzioni if else e continua e ritorna in esso. E 'spazzatura. Se il programmatore fosse stato costretto a pensare a quello che stava facendo ...

    
risposta data 27.02.2013 - 00:12
fonte

Leggi altre domande sui tag