Codice pulito: funzioni con pochi parametri [chiuso]


49

Ho letto i primi capitoli di Clean Code di Robert C. Martin, e mi sembra abbastanza buono, ma ho dei dubbi, in una parte si dice che è buono (cognitivo) che le funzioni dovrebbero avere il minor numero di parametri per quanto possibile, suggerisce persino che 3 o più parametri siano troppo per una funzione (che trovo molto esagerata e idealistica), quindi ho iniziato a chiedermi ...

Sia le pratiche di utilizzo delle variabili globali che il passaggio di molti argomenti sulle funzioni sarebbero cattive pratiche di programmazione, ma l'uso di variabili globali può ridurre notevolmente il numero di parametri nelle funzioni ...

Quindi volevo sentire cosa ne pensi, vale la pena usare variabili globali per ridurre il numero di parametri delle funzioni o no? In quali casi sarebbe?

Quello che penso è che dipende da diversi fattori:

  • Dimensione del codice sorgente.
  • Numero di parametri in media delle funzioni.
  • Numero di funzioni
  • Frequenza in cui vengono utilizzate le stesse variabili.

Secondo me se la dimensione del codice sorgente è relativamente piccola (come meno di 600 righe di codice), ci sono molte funzioni, le stesse variabili vengono passate come parametri e le funzioni hanno molti parametri, quindi varrebbe la pena usare variabili globali, ma io vorrei sapere ...

  • Condividi la mia opinione
  • Cosa ne pensi di altri casi in cui il codice sorgente è più grande, ecc.?

PS . Ho visto questo post , i titoli sono molto simili, ma non mi chiede cosa voglio sapere.


144
Non penso che l'alternativa sarebbe globale, ma invece consolidare argomenti in oggetti. Probabilmente è più un suggerimento che postLetter(string country, string town, string postcode, string streetAddress, int appartmentNumber, string careOf)è una versione puzzolente di postLetter(Address address). Continua a leggere il libro, si spera che dirà qualcosa del genere.
Nathan Cooper,

3
@DocBrown Ho preso la domanda per significare qualcosa di più come lo zio Bob dice che non usi più di 3 parametri in modo da aggirare quel problema usando le variabili globali giusto? :-) Penso che probabilmente l'autore non sappia che ci sono modi migliori per aggirare questo problema, come menzionato nelle risposte di seguito.
bytedev,

9
Non più di n parametri è una regola empirica (per qualsiasi valore di n), non incisa su un diamante. Non confondere un buon consiglio per un mandato. Molti parametri sono generalmente un odore di codice che hai troppe cose in corso in una funzione / metodo. Le persone erano solite evitare di suddividere in più funzioni per evitare l'overhead aggiuntivo delle chiamate extra. Poche applicazioni sono più intense di questo perf e un profiler può dirti quando e dove è necessario evitare chiamate extra.
Jared Smith,

14
Ciò mostra cosa c'è di sbagliato in questo tipo di regola senza giudizio: apre le porte a "soluzioni" senza giudizio. Se una funzione ha molti argomenti, può indicare un design non ottimale, in genere non solo della funzione, ma del contesto in cui viene utilizzata. La soluzione (se necessaria) è cercare di refactoring il codice. Non posso darti una regola semplice, generale, senza giudizio su come farlo, ma ciò non significa che "non più di N argomenti" sia una buona regola.
sdenham,

4
Se hai troppi parametri per una funzione, le probabilità sono alcune di esse correlate e dovrebbero essere raggruppate in un oggetto che poi diventa un singolo parametro che incapsula più parti di dati. C'è una terza opzione qui.

Risposte:


113

Non condivido la tua opinione. Secondo me l'uso di variabili globali è una pratica peggiore di più parametri indipendentemente dalle qualità che hai descritto. Il mio ragionamento è che più parametri possono rendere un metodo più difficile da capire, ma le variabili globali possono causare molti problemi per il codice tra cui scarsa testabilità, bug di concorrenza e accoppiamento stretto. Indipendentemente dal numero di parametri di una funzione, non avrà intrinsecamente gli stessi problemi delle variabili globali.

... le stesse variabili vengono passate come parametri

Esso può essere un odore di progettazione. Se si hanno gli stessi parametri passati alla maggior parte delle funzioni nel proprio sistema, potrebbe esserci un problema trasversale che dovrebbe essere gestito introducendo un nuovo componente. Non penso che passare la stessa variabile a molte funzioni sia un valido ragionamento per introdurre variabili globali.

In una modifica della tua domanda hai indicato che l'introduzione di variabili globali potrebbe migliorare la leggibilità del codice. Non sono d'accordo. L'uso di variabili globali è nascosto nel codice di implementazione mentre i parametri di funzione sono dichiarati nella firma. Le funzioni dovrebbero idealmente essere pure. Dovrebbero funzionare solo sui loro parametri e non dovrebbero avere effetti collaterali. Se hai una funzione pura, puoi ragionare sulla funzione guardando solo una funzione. Se la tua funzione non è pura, devi considerare lo stato di altri componenti e diventa molto più difficile ragionare.


Ok, è bello ascoltare altre opinioni, ma riguardo all'odore del design , sto programmando problemi in C che sono risolti con metodi di intelligenza artificiale e tendo ad usare molte funzioni che usano quasi sempre le stesse matrici, array o variabili (che Passo come parametri alle funzioni), lo sto dicendo perché non sento di poter inserire queste variabili in un concetto / cosa comune come una struttura o unione in modo da non sapere come realizzare un design migliore, quindi è per questo che penso che valga la pena l'uso di variabili globali in questo caso, ma molto probabilmente mi sbaglio.
OiciTrap,

1
Non sembra un problema di progettazione. Penso ancora che passare i parametri alle funzioni sia il miglior design. In un sistema di intelligenza artificiale come quello che stai descrivendo, troverei utile scrivere unit test per testare i pezzi del sistema, e il modo più semplice per farlo è con i parametri.
Samuel,

96
Più parametri rendono una subroutine più difficile da capire, le variabili globali rendono l'intero programma, cioè tutte le subroutine più difficili da capire.
Jörg W Mittag,

2
Mantengo una base di codice in cui alcune funzioni accettano più di una dozzina di parametri. È una perdita di tempo enorme: ogni volta che devo chiamare la funzione, devo aprire quel file in un'altra finestra in modo da sapere in quale ordine devono essere specificati i parametri. Se avessi usato un IDE che mi avesse dato qualcosa come intellisense o se avessi usato un linguaggio con parametri, non sarebbe stato così male, ma chi può ricordare in quale ordine sono presenti una dozzina di parametri per tutte quelle funzioni?
Jerry Jeremiah,

6
La risposta è corretta in quello che dice, tuttavia sembra dare per scontato i malintesi dei PO sulle raccomandazioni nel "Codice pulito". Sono sicuro che non ci sono raccomandazioni per sostituire i parametri di funzione con i globuli in quel libro.
Doc Brown,

68

Dovresti evitare variabili globali come la peste .

Non metterei un limite rigido al numero di argomenti (come 3 o 4), ma se vuoi, tieni al minimo.

Usa structs (o oggetti in C ++) per raggruppare le variabili in una singola entità e passarle (per riferimento) alle funzioni. Di solito una funzione ottiene una struttura o un oggetto (con alcune cose diverse al suo interno) passati ad essa insieme ad un paio di altri parametri che dicono alla funzione di fare qualcosa al struct.

Per un codice profumato, pulito e modulare, cerca di attenersi al principio della responsabilità singola . Fallo con le tue strutture (o oggetti), le funzioni e i file sorgente. In tal caso, il numero naturale di parametri passati a una funzione sarà ovvio.


5
Qual è la differenza principale tra il passaggio di decine di parametri nascosti in una struttura e il loro passaggio esplicito?
Ruslan,

21
@Ruslan Cohesion.
abuzittin gillifirca,

9
E è più probabile che la funzione venga trasformata in funzioni più piccole, poiché è possibile semplicemente passare un parametro alle sotto-funzioni anziché decine di parametri. E meno rischi di confondere i parametri se si usano argomenti posizionali.
Hans Olsson,

8
Va bene, ma devi garantire la coerenza nelle Struct - assicurati che i parametri raggruppati in Struct siano "correlati". È possibile utilizzare più di un Struct in alcune circostanze.
Andrew Dodds,

8
@abuzittingillifirca Non si ottiene automaticamente la coesione. Se l'unica giustificazione per mettere i parametri in una struttura è passarli a una particolare funzione, allora la coesione è probabilmente illusoria.
sdenham,

55

Stiamo parlando di carico cognitivo, non di sintassi. Quindi la domanda è ... Qual è un parametro in questo contesto?

Un parametro è un valore che influenza il comportamento della funzione. Più parametri, più combinazioni possibili di valori ottieni, più diventa difficile il ragionamento sulla funzione.

In tal senso, le variabili globali utilizzate dalla funzione sono parametri. Sono parametri che non compaiono nella sua firma, che hanno problemi di ordine di costruzione, controllo degli accessi e rimanenza.

A meno che detto parametro non sia ciò che viene definito una preoccupazione trasversale , ovvero uno stato a livello di programma che tutto utilizza ma che non altera nulla (ad esempio un oggetto di registrazione), non è necessario sostituire i parametri di funzione con variabili globali. Sarebbero ancora parametri, ma più cattivi.


11
Per te un +1, che si tratti di una toilette o di un comò, puzzano lo stesso. Bel lavoro sottolineando il lupo travestito da pecora.
Jared Smith,

1
+1 per affermare che sia molti parm sia vars globali sono cattivi. Ma voglio chiarire qualcosa. Nella maggior parte delle lingue, i parametri primitivi vengono passati per valore per impostazione predefinita (Java) e in altri è possibile passarli in modo esplicito per valore (PL / SQL). D'altra parte si accede sempre alle primitive globali per riferimento (per così dire). Quindi i parametri, almeno dei tipi primitivi, sono sempre più sicuri delle variabili globali. Anche se ovviamente avere più di due o tre parametri è un odore, e avere dodici parametri è un odore enorme che deve essere riformulato.
Tulains Córdova,

4
Assolutamente, una variabile globale È un parametro nascosto.
Bill K,

+1 Al tuo punto, ho visto simulazioni MATLAB che si basano su variabili globali per passare i dati. Il risultato era completamente illeggibile perché era così difficile dire quali variabili fossero parametri per quale funzione.
Cort Ammon,

34

IMHO la tua domanda si basa su un malinteso. In "Clean Code", Bob Martin non suggerisce di sostituire i parametri delle funzioni ripetute con i globali, sarebbe un consiglio davvero terribile. Suggerisce di sostituirli con variabili membro private della classe della funzione. E propone anche classi piccole e coerenti (in genere più piccole delle 600 righe di codice che hai citato), quindi queste variabili membro non sono assolutamente globali.

Quindi, quando si ha un'opinione in un contesto con meno di 600 righe "vale la pena usare variabili globali" , quindi si condivide perfettamente l'opinione di Zio Bob. Naturalmente, è discutibile se "3 parametri al massimo" è il numero ideale, e se questa regola a volte porta a troppe variabili membro anche in classi di piccole dimensioni. IMHO questo è un compromesso, non esiste una regola rigida dove tracciare la linea.


10
Non ho mai capito perché qualcuno preferirebbe rendere la propria classe stateful inserendo i parametri in un costruttore invece di vivere semplicemente con un argomento reale. Questo mi ha sempre colpito come un enorme aumento della complessità. (Un esempio di vita reale che ho visto di questo è un oggetto di connessione al database, che ha reso quasi impossibile provare a tenere traccia dello stato del database attraverso il programma quando combinato con l'iniezione di dipendenza.) Ma forse Clean Code ha più da dire su quel particolare soggetto. I globali sono, ovviamente, un'opzione ancora peggiore per quanto riguarda il rendere le cose di stato.
jpmc26,

2
@ jpmc26: si ottiene un "enorme aumento della complessità" se le classi diventano troppo grandi e ottengono troppe variabili membro, quindi il risultato non è più coerente.
Doc Brown,

4
Penso che la risposta ignori la difficoltà nella gestione dello stato (che potrebbe anche essere mutevole) che si sviluppa su molte classi. Quando una funzione dipende non solo dagli argomenti, ma anche dal modo in cui l'oggetto è stato costruito (o addirittura modificato nel corso della sua vita), diventa più difficile comprendere il suo stato attuale quando si effettua una chiamata particolare. Ora devi rintracciare la costruzione di un altro oggetto, solo per capire cosa farà la chiamata. L'aggiunta di variabili di istanza aumenta attivamente la quantità di stato del programma, a meno che non si costruisca l'oggetto e lo si butti immediatamente?
jpmc26,

3
@ jpmc26 Un modello che uso regolarmente durante il refactoring è che il costruttore agisce come l'impostazione di un contesto, quindi gli argomenti del metodo sono specifici di un'azione. L'oggetto non è esattamente stato, perché lo stato che detiene non cambia mai, ma lo spostamento di tali azioni comuni nei metodi di questo contenitore migliora significativamente la leggibilità laddove viene utilizzato (il contesto viene impostato una sola volta, simile ai gestori di contesto di Python) e riduce la duplicazione se vengono effettuate più chiamate ai metodi dell'oggetto.
Izkata,

3
+1 Per dire chiaramente che le variabili membro non sono variabili globali. Molte persone pensano di esserlo.
Tulains Córdova,

34

Avere molti parametri è considerato indesiderabile, ma trasformarli in campi o variabili globali è molto peggio perché non risolve il problema reale ma introduce nuovi problemi.

Avere molti parametri non è di per sé il problema, ma è un sintomo che potresti avere un problema. Considera questo metodo:

Graphics.PaintRectangle(left, top, length, height, red, green, blue, transparency);

Avere 7 parametri è un segnale di avvertimento definito. Il problema di fondo è che questi parametri non sono indipendenti ma appartengono a gruppi. lefte topappartengono insieme come una Positionstruttura, lengthe heightcome una Sizestruttura e red, bluee greencome una Colorstruttura. E forse Colore la trasparenza appartiene a una Brushstruttura? Forse Positione Sizeappartiene insieme in una Rectanglestruttura, nel qual caso potremmo addirittura considerare di trasformarlo in un Paintmetodo Rectanglesull'oggetto? Quindi potremmo finire con:

Rectangle.Paint(brush);

Missione compiuta! Ma la cosa importante è che abbiamo effettivamente migliorato la progettazione generale e la riduzione del numero di parametri è una conseguenza di ciò. Se riduciamo semplicemente il numero di parametri senza affrontare i problemi sottostanti, potremmo fare qualcosa del genere:

Graphics.left = something;
Graphics.top = something;
Graphics.length = something;
...etc
Graphics.PaintRectangle();

Qui abbiamo ottenuto la stessa riduzione del numero di parametri, ma in realtà abbiamo peggiorato la progettazione .

Bottom line: per qualsiasi consiglio di programmazione e regole empiriche è davvero importante capire il ragionamento sottostante.


4
+1 risposta piacevole, costruttiva, comprensibile, non teorica.
AnoE

1
Per non parlare di cosa diavolo sta facendo il tuo "quadrato" con l'attributo lunghezza E altezza. :)
Wildcard il

1
+1 per riconoscere che l'ovvia terza via implicita in alcune risposte (ad es. Molte assegnazioni a una struttura / oggetto prima della chiamata di funzione) non è migliore.
benxyzzy,

@Wildcard: grazie, l'ho cambiato in "rettangolo" per evitare di confondere il problema!
JacquesB,

7

vale la pena usare variabili globali per ridurre il numero di parametri delle funzioni o no?

Non

Ho letto i primi capitoli di questo libro

Hai letto il resto del libro?

Un globale è solo un parametro nascosto. Causano un dolore diverso. Ma è ancora dolore. Smetti di pensare a come aggirare questa regola. Pensa a come seguirlo.

Cos'è un parametro?

È roba. In una scatola ben etichettata. Perché importa quante scatole hai quando puoi mettere qualsiasi cosa al suo interno?

È il costo di spedizione e gestione.

Move(1, 2, 3, 4)

Dimmi che puoi leggerlo. Dai, prova.

Move(PointA, PointB)

Ecco perchè.

Questo trucco si chiama introduce parametro object .

E sì, è solo un trucco se tutto ciò che stai facendo è contare i parametri. Quello che dovresti contare è IDEE! Astrazioni! Quanto mi stai facendo pensare subito? Mantienilo semplice.

Ora questo è lo stesso conteggio:

Move(xyx, y)

OW! È orribile! Cosa è andato storto qui?

Non è sufficiente limitare il numero di idee. Devono essere idee chiare. Che diamine è un xyx?

Ora questo è ancora debole. Qual è un modo più potente di pensarci?

Le funzioni dovrebbero essere piccole. Non più piccolo di quello.

Zio Bob

Move(PointB)

Perché fare in modo che la funzione funzioni più di quanto sia realmente necessario? Il principio della responsabilità singola non è solo per le classi. Seriamente, vale la pena cambiare un'intera architettura solo per impedire a una funzione di trasformarsi in un incubo sovraccarico con 10 parametri a volte correlati alcuni dei quali non possono essere utilizzati con altri.

Ho visto il codice in cui il numero più comune di righe in una funzione era 1. Scherzi a parte. Non sto dicendo che devi scrivere in questo modo, ma non dirmi che un globale è l'UNICO modo in cui puoi rispettare questa regola. Smetti di cercare di uscire dal refactoring che funzioni correttamente. Sai che puoi. Potrebbe essere suddiviso in alcune funzioni. Potrebbe effettivamente trasformarsi in alcuni oggetti. Inferno, potresti persino dividerne una parte in un'applicazione completamente diversa.

Il libro non ti dice di contare i tuoi parametri. Ti sta dicendo di prestare attenzione al dolore che stai causando. Tutto ciò che risolve il dolore risolve il problema. Basta essere consapevoli quando si scambia semplicemente un dolore per un altro.


3
"Hai letto il resto del libro?"
Risposte

Sono completamente d'accordo - il punto è scomporre il problema in piccoli pezzi. Gli oggetti possono davvero aiutare a organizzare questi pezzi e raggrupparli, inoltre permettono a una singola unità concettuale di essere passata come parametro piuttosto che un mucchio di pezzi non collegati. Ottengo ansioso quando vedo un metodo con più di 3 parametri. 5 è un'indicazione che il mio progetto è andato a schifo e ho bisogno di un altro giro di refactoring. Il modo migliore che ho trovato per risolvere problemi di progettazione come il conteggio dei parametri è semplicemente il refactoring delle cose in unità più piccole e più semplici (classi / metodi).
Bill K,

2
Il tono di questa risposta potrebbe essere migliorato. Sembra molto brusco e duro. Ad esempio: "Dimmi che puoi leggerlo. Dai, prova." sembra molto aggressivo e potrebbe essere riscritto come "Delle due chiamate di funzione sopra / sotto, quale è più facile da leggere?" Dovresti provare a capire il punto senza l'aggressività. L'OP sta solo cercando di imparare.
Kyle A

Non dimenticare che anche l'OP sta cercando di rimanere sveglio.
candied_orange,

4

Non userei mai le variabili globali per ridurre i parametri. Il motivo è che le variabili globali possono essere modificate da qualsiasi funzione / comando, rendendo quindi l'input inaffidabile e incline a valori che non rientrano nell'ambito di ciò che la funzione può gestire. E se la variabile fosse cambiata durante l'esecuzione della funzione e metà della funzione avesse valori diversi rispetto all'altra metà?

Passando i parametri, d'altra parte, limita l'ambito della variabile solo alla propria funzione in modo tale che solo la funzione possa modificare un parametro una volta chiamato.

Se è necessario passare variabili globali anziché un parametro, è preferibile riprogettare il codice.

Solo i miei due centesimi.


"Non userei mai le variabili globali per ridurre i parametri" sono totalmente d'accordo. Crea accoppiamenti inutili.
bytedev,

2

Sono con lo zio Bob su questo e concordo sul fatto che più di 3 parametri è qualcosa da evitare (uso molto raramente più di 3 parametri in una funzione). Avere molti parametri su una singola funzione crea un problema di manutenzione più grande ed è probabilmente un odore che la tua funzione stia facendo troppo / abbia troppe responsabilità.

Se stai usando più di 3 in un metodo in un linguaggio OO, dovresti considerare che i parametri non sono in qualche modo collegati tra loro e quindi dovresti davvero passare un oggetto?

Inoltre, se crei più funzioni (più piccole) noterai anche che le funzioni tendono ad avere più spesso 3 parametri o meno. Estrai funzione / metodo è tuo amico :-).

Non usare le variabili globali come modo per aggirare avere più parametri! Questo è scambiare una cattiva pratica con una ancora peggiore!


1

Una valida alternativa a molti parametri di funzione è l'introduzione di un oggetto parametro . Ciò è utile se si dispone di un metodo composto che passa (quasi) tutti i suoi parametri a un gruppo di altri metodi.

In casi semplici questo è un DTO semplice che non ha nient'altro che i vecchi parametri come proprietà.


1

L'uso delle variabili globali sembra sempre un modo semplice per codificare (specialmente in un piccolo programma), ma renderà difficile l'estensione del codice.

Sì, è possibile ridurre il numero di parametri in una funzione utilizzando un array per associare i parametri in un'entità.

function <functionname>(var1,var2,var3,var4.....var(n)){}

La funzione sopra sarà modificata e cambiata in [usando un array associativo] -

data=array(var1->var1,
           var2->var2
           var3->var3..
           .....
           ); // data is an associative array

function <functionname>(data)

Concordo con la risposta di Robert Bristow-Johnson : puoi persino usare una struttura per legare i dati in una singola entità.


1

Prendendo un esempio da PHP 4, guarda la firma della funzione per mktime():

  • int mktime ([ int $hour = date("H") [, int $minute = date("i") [, int $second = date("s") [, int $month = date("n") [, int $day = date("j") [, int $year = date("Y") [, int $is_dst = -1 ]]]]]]] )

Non lo trovi confuso? La funzione si chiama "make time" ma richiede parametri di giorno, mese e anno, nonché tre parametri di tempo. Quanto è facile ricordare in quale ordine vanno? E se vedessi mktime(1, 2, 3, 4, 5, 2246);? Riesci a capirlo senza dover fare riferimento a nient'altro? Viene 2246interpretato come un "22:46" di 24 ore? Cosa significano gli altri parametri? Sarebbe meglio come un oggetto.

Passando a PHP 5, ora c'è un oggetto DateTime. Tra i suoi metodi ci sono due chiamati setDate()e setTime(). Le loro firme sono le seguenti:

  • public DateTime setDate ( int $year , int $month , int $day )
  • public DateTime setTime ( int $hour , int $minute [, int $second = 0 ] )

Devi ancora ricordare che l'ordine dei parametri va dal più grande al più piccolo, ma è un grande miglioramento. Si noti che non esiste un solo metodo che consente di impostare tutti e sei i parametri contemporaneamente. Devi fare due chiamate separate per farlo.

Ciò di cui lo zio Bob sta parlando è evitare di avere una struttura piatta. I parametri correlati dovrebbero essere raggruppati in un oggetto e, se hai più di tre parametri, è molto probabile che tu abbia uno pseudo oggetto lì, che ti dà l'opportunità di creare un oggetto appropriato per una maggiore separazione. Sebbene PHP non abbia una classe Datee una Timeclasse separate , potresti considerare che DateTimecontiene davvero un Dateoggetto e un Timeoggetto.

Potresti avere la seguente struttura:

<?php
$my_date = new Date;
$my_date->setDay(5);
$my_date->setMonth(4);
$my_date->setYear(2246);

$my_time = new Time;
$my_time->setHour(1);
$my_time->setMinute(2);
$my_time->setSecond(3);

$my_date_time = new DateTime;
$my_date_time->setTime($my_time);
$my_date_time->setDate($my_date);
?>

È obbligatorio impostare due o tre parametri ogni volta? Se vuoi cambiare solo l'ora o solo il giorno, ora è facile farlo. Sì, l'oggetto deve essere convalidato per assicurarsi che ciascun parametro funzioni con gli altri, ma in ogni caso era già così.

La cosa più importante è, è più facile da capire e quindi mantenere? Il blocco di codice in fondo è più grande di una singola mktime()funzione, ma direi che è molto più facile da capire; anche un non programmatore non avrebbe molti problemi a capire cosa fa. L'obiettivo non è sempre un codice più breve o un codice più intelligente, ma un codice più gestibile.

Oh, e non usare i globi!


1

Molte buone risposte qui, ma la maggior parte non sta affrontando il punto. Perché queste regole empiriche? Riguarda l'ambito, riguarda le dipendenze e riguarda la modellazione corretta.

I globali per gli argomenti sono peggiori perché sembra solo che tu l'abbia reso più semplice, ma in realtà hai solo nascosto la complessità. Non lo vedi più nel prototipo, ma devi comunque esserne consapevole (il che è difficile poiché non è più lì per te vedere) e farti aggirare la logica della funzione non ti aiuterà perché potrebbe esserci essere un'altra logica nascosta che interferisce dietro la schiena. Il tuo ambito è andato ovunque e hai introdotto una dipendenza da qualsiasi cosa, perché qualsiasi cosa ora può rovinare la tua variabile. Non bene.

La cosa principale da mantenere per una funzione è che puoi capire cosa fa guardando il prototipo e chiamando. Quindi il nome dovrebbe essere chiaro e inequivocabile. Ma anche più argomenti ci sono, più sarà difficile capire cosa fa. Allarga la portata nella tua testa, troppe cose stanno succedendo, ecco perché vuoi limitare il numero. Indipendentemente dal tipo di argomenti con cui hai a che fare, alcuni sono peggiori di altri. Un valore booleano aggiuntivo opzionale che consente l'elaborazione insensibile al maiuscolo / minuscolo non rende la funzione più difficile da comprendere, quindi non vorrai fare molto. Come nota a margine, gli enum sostengono argomenti migliori dei booleani perché il significato di un enum è ovvio nella chiamata.

Il problema tipico non è che scrivi una nuova funzione con un'enorme quantità di argomenti, ne inizierai solo con alcuni quando non ti rendi conto di quanto sia complesso il problema che stai risolvendo. Man mano che il programma si evolve, gli elenchi di argomenti tendono gradualmente ad allungarsi. Una volta che un modello ti è stato in mente, vuoi mantenerlo perché è un riferimento sicuro che conosci. Ma a posteriori il modello potrebbe non essere così eccezionale. Hai perso un passo o troppo nella logica e non hai riconosciuto un'entità o due. "OK ... Potrei ricominciare da capo e passare un paio di giorni a refactoring del mio codice o ... Potrei aggiungere questo argomento in modo da poterlo fare dopo tutto e fare con esso. Per ora. Per questo scenario . Per rimuovere questo bug dal mio piatto in modo da poter spostare la nota adesiva su ".

Più spesso vai con la seconda soluzione, più costosa sarà l'ulteriore manutenzione e più diventerà difficile e poco attraente un refattore.

Non esiste una soluzione della piastra della caldaia per ridurre il numero di argomenti in una funzione esistente. Raggrupparli in composti non semplifica davvero le cose, è solo un altro modo di cancellare la complessità sotto il tappeto. Farlo nel modo giusto implica rivedere l'intero stack di chiamate e riconoscere ciò che manca o è stato fatto in modo errato.


0

Diverse volte ho scoperto che raggruppare molti parametri inviati insieme migliorava le cose.

  • Ti costringe a dare un buon nome a questo gruppo di concetti che vengono usati insieme. Se si utilizzano questi parametri insieme, è possibile che abbiano una relazione (o che non si dovrebbe usare insieme).

  • Una volta con l'oggetto di solito trovo che si possa spostare un po 'di funzionalità rispetto a questo oggetto apparentemente stufo. Di solito è facile da testare e con una grande coesione e un basso accoppiamento rendono la cosa ancora migliore.

  • La prossima volta che devo aggiungere un nuovo parametro, ho un bel posto per includerlo senza cambiare la firma di molti metodi.

Quindi potrebbe non funzionare il 100% delle volte, ma chiediti se questo elenco di parametri deve essere raggruppato in un oggetto. E per favore Non utilizzare classi non tipizzate come Tuple per evitare di creare l'oggetto. Stai utilizzando una programmazione orientata agli oggetti, non preoccuparti di creare più oggetti se ne hai bisogno.


0

Con tutto il rispetto, sono abbastanza sicuro di aver perso completamente il punto di avere un piccolo numero di parametri in una funzione.

L'idea è che il cervello può contenere così tante "informazioni attive" alla volta e se hai n parametri in una funzione, hai n più pezzi di "informazioni attive" che devono essere nel tuo cervello in modo facile e preciso capire cosa sta facendo il pezzo di codice (Steve McConnell, in Code Complete (un libro molto migliore, IMO), dice qualcosa di simile su 7 variabili nel corpo di un metodo: raramente lo raggiungiamo, ma non di più e stai perdendo il abilità mantenere tutto dritto nella tua testa).

Il punto di un basso numero di variabili è essere in grado di mantenere piccoli i requisiti cognitivi per lavorare con questo codice, in modo da poterlo lavorare (o leggerlo) in modo più efficace. Una causa secondaria di ciò è che un codice ben ponderato tenderà ad avere sempre meno parametri (ad esempio, un codice scarsamente fatturato tende a raggruppare un mucchio di cose in un pasticcio).

Passando oggetti invece di valori, forse ottieni un livello di astrazione per il tuo cervello perché ora ha bisogno di rendersi conto di sì, ho un SearchContext con cui lavorare qui invece di pensare alle 15 proprietà che potrebbero trovarsi in quel contesto di ricerca.

Tentando di utilizzare le variabili globali, sei andato completamente nella direzione sbagliata. Ora non solo non hai risolto i problemi di avere troppi parametri per una funzione, ma hai preso quel problema e lo hai gettato in un problema molto, molto meglio che ora devi portare in giro nella tua mente!

Ora invece di lavorare solo a livello di funzione, devi considerare anche l'ambito globale del tuo progetto (stupore, che terribile! Rabbrividisco ...). Non hai nemmeno tutte le tue informazioni di fronte a te nella funzione (merda, qual è quel nome di variabile globale?) (Spero che questo non sia stato cambiato da qualcos'altro da quando ho chiamato questa funzione).

Le variabili con portata globale sono una delle cose peggiori da vedere in un progetto (grande o piccolo). Indicano una disabilità per una corretta gestione dell'ambito, che è un'abilità fondamentale per la programmazione. Essi. Siamo. Il male.

Spostando i parametri fuori dalla tua funzione e inserendoli in globi, ti sei sparato nel pavimento (o nella gamba o nella faccia). E Dio ti proibisca mai di decidere che ehi, posso riutilizzare questo globale per qualcos'altro ... la mia mente trema al pensiero.

L'intero ideale è mantenere le cose facili da gestire, e le variabili globali NON lo faranno. Andrei al punto di dire che sono una delle cose peggiori che puoi fare per andare nella direzione opposta.


-1

Ho trovato un approccio altamente efficace (in JavaScript) per ridurre al minimo l'attrito tra le interfacce: utilizzare un'interfaccia uniforme per tutti i moduli , in particolare: singole funzioni param.

Quando sono necessari più parametri: utilizzare un singolo oggetto / hash o matrice.

Abbi pazienza, prometto che non sto trollando ...

Prima di dire "a che serve un singolo parametro?" O "C'è una differenza tra 1 array e funzioni multi-arg?"

Beh si. È forse visivamente sottile, ma la differenza è molte volte: qui esploro i numerosi vantaggi

Apparentemente alcuni ppl pensano che 3 sia il numero giusto di argomenti. Alcuni pensano che sia 2. Bene, ciò pone ancora la domanda "quale parametro va in arg [0]?" Invece di scegliere l'opzione che vincola l'interfaccia con una dichiarazione più rigida.

Immagino di sostenere una posizione più radicale: non fare affidamento su argomenti posizionali. Sento solo che è fragile e porta a discussioni sulla posizione di quei maledetti argomenti. Salta e passa direttamente all'inevitabile combattimento sui nomi di funzioni e variabili. 😉

Seriamente, dopo che la denominazione si deposita, si spera che tu finisca con un codice come segue, che è in qualche modo auto-documentante, non sensibile alla posizione e consente di gestire future modifiche ai parametri all'interno della funzione:

function sendMessage({toUser, fromUser, subject, body}) { }

// And call the method like so:
sendMessage({toUser: this.parentUser, fromUser: this.currentUser, subject: ‘Example Alert’})


6
La falsificazione di argomenti con nome non significa in realtà passare solo un argomento.
JDługosz,

Perché è "falso" se ho raggiunto un obiettivo che mi ero prefissato? Sto ponendo una priorità più alta sugli argomenti nominati. Poiché gli argomenti posizionali non sono ovvi nel chiamare il codice, e con il numero di funzioni nominate uno sviluppatore deve memorizzare che non è utile ricordare quali parametri sono dove e quali facoltativi. ... Alla fine vorrai aggiungere un parametro richiesto dopo gli optionals, buona fortuna per documentare e aggiornare quel castello di carte.
Dan Levy,

2
I parametri nominati sono anche un trucco per l'apprendimento del rinforzo: gli umani attribuiscono più significato alle raccolte di parole.
Dan Levy,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.