Domanda

Le routine possono avere parametri, questa non è una novità. Puoi definire tutti i parametri di cui potresti aver bisogno, ma troppi di essi renderanno la tua routine difficile da capire e mantenere.

Ovviamente, potresti usare una variabile strutturata come soluzione alternativa: mettere tutte quelle variabili in una singola struttura e passarle alla routine. In effetti, l'uso delle strutture per semplificare gli elenchi di parametri è una delle tecniche descritte da Steve McConnell in Codice completo . Ma come dice:

  

I programmatori attenti evitano di raggruppare i dati più di quanto sia logicamente necessario.

Quindi se la tua routine ha troppi parametri o usi uno struct per mascherare un grande elenco di parametri, probabilmente stai facendo qualcosa di sbagliato. Cioè, non stai mantenendo l'accoppiamento allentato.

La mia domanda è: quando posso considerare un elenco di parametri troppo grande? Penso che più di 5 parametri siano troppi. Cosa ne pensi?

È stato utile?

Soluzione

Quando una cosa è considerata così oscena da essere qualcosa che può essere regolata nonostante il 1 ° emendamento garantisca la libertà di parola? Secondo il giudice Potter Stewart, "lo so quando lo vedo." Lo stesso vale qui.

Odio fare regole dure e veloci come questa perché la risposta cambia non solo in base alle dimensioni e alla portata del tuo progetto, ma penso che cambi anche fino al livello del modulo. A seconda di cosa sta facendo il tuo metodo o di ciò che la classe dovrebbe rappresentare, è possibile che 2 argomenti siano troppi ed è un sintomo di troppo accoppiamento.

Suggerirei che ponendo la domanda in primo luogo, e qualificando la tua domanda tanto quanto te, sai davvero tutto questo. La soluzione migliore qui non è fare affidamento su un numero forte e veloce, ma piuttosto guardare revisioni del progetto e revisioni del codice tra i tuoi colleghi per identificare le aree in cui hai bassa coesione e accoppiamento stretto.

Non aver mai paura di mostrare ai tuoi colleghi il tuo lavoro. Se hai paura, questo è probabilmente il segno più grande che qualcosa non va nel tuo codice e che lo sai già .

Altri suggerimenti

Una funzione può avere troppi parametri solo se alcuni dei parametri sono ridondanti. Se vengono utilizzati tutti i parametri, la funzione deve avere il numero corretto di parametri. Prendi questa funzione usata spesso:

HWND CreateWindowEx
(
  DWORD dwExStyle,
  LPCTSTR lpClassName,
  LPCTSTR lpWindowName,
  DWORD dwStyle,
  int x,
  int y,
  int nWidth,
  int nHeight,
  HWND hWndParent,
  HMENU hMenu,
  HINSTANCE hInstance,
  LPVOID lpParam
);

Sono 12 i parametri (9 se si raggruppano x, y, w e h come un rettangolo) e ci sono anche i parametri derivati ??dal nome della classe. Come riduresti questo? Desideri ridurre ulteriormente il numero al punto?

Non lasciare che il numero di parametri ti dia fastidio, assicurati solo che sia logico e ben documentato e che intellisense * ti aiuti.

* Sono disponibili altri assistenti di codifica!

In Clean Code , Robert C. Martin ha dedicato quattro pagine all'argomento . Ecco l'essenza:

  

Il numero ideale di argomenti per a   la funzione è zero (niladic). Il prossimo arriva   uno (monadico), seguito da vicino da due   (Diadica). Tre argomenti (triadico)   dovrebbe essere evitato ove possibile. Di Più   di tre (poliadico) richiede molto   giustificazione speciale - e poi   non dovrebbe essere usato comunque.

Alcuni codici con cui ho lavorato in passato utilizzavano variabili globali solo per evitare di passare troppi parametri in giro.

Per favore, non farlo!

(di solito).

Se inizi a dover contare mentalmente i parametri nella firma e abbinarli alla chiamata, allora è il momento di refactoring!

Grazie mille per tutte le risposte:

  • È stato un po 'sorprendente trovare persone che pensano (come faccio io) che 5 parametri siano un buon limite per la sanità mentale del codice.

  • Generalmente, le persone tendono a concordare sul fatto che un limite tra 3 e 4 è una buona regola empirica. Questo è ragionevole poiché le persone di solito si divertono a contare più di 4 cose.

  • Come Milano punti , in media le persone possono tenere in mente più o meno 7 cose alla volta. Ma penso che non puoi dimenticare che, quando progetti / mantieni / studi una routine, devi tenere a mente più cose che solo i parametri.

  • Alcune persone ritengono che una routine debba avere tutti gli argomenti necessari. Sono d'accordo, ma solo per alcuni casi specifici (chiamate alle API del sistema operativo, routine in cui l'ottimizzazione è importante, ecc.). Suggerisco di nascondere la complessità di queste routine aggiungendo uno strato di astrazione appena sopra queste chiamate ogni volta che è possibile.

  • Nick ha alcuni pensieri interessanti su questo. Se non vuoi leggere i suoi commenti, ti riassumo per te: in breve, dipende :

      

    Odio fare regole dure e veloci come questa perché la risposta cambia non solo in base alle dimensioni e alla portata del tuo progetto, ma penso che cambi anche fino al livello del modulo. A seconda di cosa sta facendo il tuo metodo o di ciò che la classe dovrebbe rappresentare, è possibile che 2 argomenti siano troppi ed è un sintomo di troppo accoppiamento.

    La morale qui non ha paura di mostrare il tuo codice ai tuoi coetanei, discuti con loro e cerca di " identificare aree in cui hai bassa coesione e stretto accoppiamento " .

  • Infine, penso che wnoise sia molto d'accordo con Nick, e conclude il suo contributo satirico con questa visione poetica (vedi commenti sotto) dell'arte della programmazione:

      

    La programmazione non è ingegneria. L'organizzazione del codice è un'arte perché dipende da fattori umani, che dipendono troppo dal contesto per qualsiasi regola rigida.

Questa risposta assume una lingua OO. Se non ne usi uno, salta questa risposta (in altre parole questa non è una risposta agnostica).

Se stai passando più di 3 o più parametri (in particolare tipi / oggetti intrinseci), non è che è " Troppi " ma che potresti non avere la possibilità di creare un nuovo oggetto.

Cerca gruppi di parametri che vengono passati in più di un metodo - anche un gruppo passato in due metodi garantisce quasi che dovresti avere un nuovo oggetto lì.

Quindi rifatti la funzionalità nel tuo nuovo oggetto e non crederesti quanto aiuti sia il tuo codice che la tua comprensione della programmazione OO.

Sembra che ci siano altre considerazioni oltre al semplice numero, eccone alcune che mi vengono in mente:

  1. relazione logica con lo scopo principale della funzione rispetto alle impostazioni una tantum

  2. Se sono solo flag di ambiente, il raggruppamento può essere molto utile

Uno dei più noti epigrammi di programmazione di Alan Perlis (raccontato in ACM SIGPLAN Avvisi 17 (9), settembre 1982) afferma che "Se hai una procedura con 10 parametri, probabilmente ne hai perso alcuni. "

Secondo Steve McConnell in Codice completo , dovresti

  

Limita il numero di una routine   parametri a circa sette

Per me, quando l'elenco incrocia una riga sul mio IDE, allora è un parametro di troppo. Voglio vedere tutti i parametri in una riga senza interrompere il contatto visivo. Ma questa è solo la mia preferenza personale.

Sono generalmente d'accordo con 5, tuttavia, se c'è una situazione in cui ho bisogno di più ed è il modo più chiaro per risolvere il problema, allora ne userei di più.

Sette cose nella memoria a breve termine?

  1. Nome della funzione
  2. Restituisce il valore della funzione
  3. Scopo della funzione
  4. Parametro 1
  5. Parametro 2
  6. Parametro 3
  7. Parametro 4

In Peggiori 5 frammenti di codice , controlla il secondo," Questo è un costruttore ". Ha circa 37 · 4 ˜ 150 parametri:

  

Qui un programmatore ha scritto questo costruttore [... S] qualcuno di voi potrebbe pensare di sì, è un grande costruttore, ma ha usato gli strumenti di generazione automatica del codice di eclissi [.] NOO, in questo costruttore c'era un piccolo bug che ho scoperto, che mi ha fatto concludere che questo costruttore è stato scritto a mano. (a proposito, questa è solo la parte superiore del costruttore, non è completa).

     

costruttore con oltre 150 parametri

Uno in più del necessario. Non intendo essere glib, ma ci sono alcune funzioni che necessitano necessariamente di alcune opzioni. Ad esempio:

void *
mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t offset);

Ci sono 6 argomenti e ognuno di essi è essenziale. Inoltre, non esiste un collegamento comune tra loro per giustificare il raggruppamento. Forse potresti definire "struct mmapargs", ma sarebbe peggio.

Secondo Best Practices Perl , 3 va bene, 4 è troppa. È solo una linea guida, ma nel nostro negozio è ciò a cui cerchiamo di attenerci.

Definirei il limite per le funzioni pubbliche con 5 parametri.

IMHO, gli elenchi di parametri lunghi sono accettabili solo nelle funzioni di supporto private / locali che devono essere richiamate solo da alcuni punti specifici del codice. In questi casi, potrebbe essere necessario trasmettere molte informazioni sullo stato, ma la leggibilità non è così importante poiché solo tu (o qualcuno che manterrà il tuo codice e dovrebbe capire i fondamenti del tuo modulo) devi preoccuparti chiamando quella funzione.

Una domanda correlata che dovresti prendere in considerazione è quanto coesiva sia la routine. Un gran numero di parametri può essere un odore che ti dice che la routine stessa sta cercando di fare troppo e quindi la sua coesione è sospetta. Concordo sul fatto che un numero duro e veloce di parametri sia probabilmente impossibile ma immagino che una routine di alta coesione implicherebbe un basso numero di parametri.

97 suoni proprio nel modo giusto.

Almeno e perdi flessibilità.

Mi fermo a tre parametri come regola generale. Ancora ed è tempo di passare invece una matrice di parametri o un oggetto di configurazione, il che consente anche di aggiungere parametri futuri senza modificare l'API.

Una limitazione di lunghezza su un elenco di parametri è solo un'altra limitazione. E restrizione significa violenza applicata. Sembra divertente, ma puoi essere non violento anche durante la programmazione. Lascia che il codice imponga le regole. È ovvio che se hai molti parametri, il corpo del metodo funzione / classe sarà abbastanza grande da usarli. E i frammenti di codice di grandi dimensioni di solito possono essere refactored e suddivisi in blocchi più piccoli. Quindi ottieni la soluzione contro avere molti parametri come bonus gratuito, poiché sono suddivisi tra i pezzi di codice refactored più piccoli.

Una cosa che vorrei sottolineare dal punto di vista delle prestazioni è che, a seconda di come si passano i parametri a un metodo, passare molti parametri per valore rallenterà il programma perché ogni parametro deve essere copiato e quindi posto nello stack.

L'uso di una singola classe per comprendere tutti i parametri funzionerebbe meglio perché un singolo parametro passato per riferimento sarebbe elegante, più pulito e più veloce!

Secondo me potrebbero esserci casi in cui supererai 4 o un numero fisso. Le cose da guardare potrebbero essere

  1. Il tuo metodo sta facendo troppo e devi fare il refactoring.
  2. Potresti prendere in considerazione l'utilizzo di una raccolta o di una struttura di dati.
  3. Ripensa al design della tua classe, forse alcune cose non devono essere passate in giro.

Da un punto di vista della facilità d'uso o della facilità di lettura del codice, penso quando è necessario un po '"parola a capo" la firma del tuo metodo, che dovrebbe farti fermare e pensare, a meno che non ti senta impotente e tutti gli sforzi per rendere la firma più piccola non portano a nessun risultato. Alcune librerie molto buone in passato e presente usano più di 4-5 carrozzine.

La mia regola empirica è che devo essere in grado di ricordare i parametri abbastanza a lungo per guardare una chiamata e dire cosa fa. Quindi, se non riesco a guardare il metodo e poi passare a una chiamata di un metodo e ricordare quale parametro fa quello, allora ce ne sono troppi.

Per me equivale a circa 5, ma non sono così brillante. Il chilometraggio può variare.

È possibile creare un oggetto con proprietà per contenere i parametri e passarlo se si supera il limite impostato. Vedi Refactoring e il capitolo su come semplificare le chiamate al metodo.

Dipende fortemente dall'ambiente in cui stai lavorando. Prendi ad esempio javascript. In javascript il modo migliore per passare parametri è usare oggetti con coppie chiave / valore, che in pratica significa che hai solo un parametro. In altri sistemi il punto debole sarà alle tre o alle quattro.

Alla fine, tutto si riduce a gusti personali.

Sono d'accordo con 3 va bene, 4 è troppa come linea guida. Con più di 3 parametri, stai inevitabilmente facendo più di un compito. Più di un'attività dovrebbe essere suddivisa in metodi separati.

Tuttavia, se guardassi l'ultimo progetto a cui ho lavorato, le eccezioni abbonderebbero e la maggior parte dei casi sarebbe difficile scendere a 3 parametri.

Se ho 7-10 parametri in una routine guardo a raggrupparli in una nuova classe ma non se quella classe non sarebbe altro che un mucchio di campi con getter e setter - la nuova classe deve fare qualcosa di diverso dai valori shuffle dentro e fuori. Altrimenti preferirei sopportare la lunga lista di parametri.

È noto che, in media, le persone possono tenere in testa 7 +/- 2 cose alla volta. Mi piace usare quel principio con parametri. Supponendo che i programmatori siano tutti persone intelligenti al di sopra della media, direi che tutto 10+ sono troppi.

A proposito, se i parametri sono simili in qualche modo, li metterei in un vettore o in una lista piuttosto che in una struttura o in una classe.

Baserei la mia risposta sulla frequenza con cui viene chiamata la funzione.

Se è una funzione init che viene chiamata una sola volta, allora lascia che impieghi almeno 10 parms, a chi importa.

Se viene chiamato un sacco di volte per fotogramma, allora tendo a creare una struttura e semplicemente a passare un puntatore ad essa poiché tende ad essere più veloce (supponendo che non si stia ricostruendo la struttura ogni volta).

Secondo Jeff Bezos della fama di Amazon, non più di quanto si possa nutrire con due pizze :

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top