Come indicato nel titolo, sono utili parametri opzionali, come quelli usati in C # o sono un ostacolo alla manutenzione dell'applicazione e dovrebbero essere evitati in quanto possono rendere il codice più difficile da capire?
Come indicato nel titolo, sono utili parametri opzionali, come quelli usati in C # o sono un ostacolo alla manutenzione dell'applicazione e dovrebbero essere evitati in quanto possono rendere il codice più difficile da capire?
Risposte:
I parametri opzionali, secondo la mia esperienza, sono stati una buona cosa. Non li ho mai trovati confusi (almeno non più confusi della funzione reale), dal momento che posso sempre ottenere i valori predefiniti e sapere come viene chiamato.
Un uso per loro è quando devo aggiungere un altro parametro a una funzione che è già in uso generale, o almeno nell'interfaccia pubblica. Senza di loro, dovrei rifare la funzione originale per chiamarne una che ha un altro argomento e che può diventare davvero vecchia se finissi per aggiungere argomenti più di una volta.
new Circle(size, color, filled, ellipseProportions)
dove size
e color
sono richiesti e il resto è predefinito.
In generale, se hai spesso bisogno di molti / parametri opzionali, le tue funzioni stanno facendo troppo e dovrebbero essere suddivise. Probabilmente stai infrangendo SRP (Single Responsibility Principle).
Cerca i parametri che possono essere raggruppati, ad esempio (xey, diventano un punto).
Questi flag di parametri opzionali sono predefiniti? Se stai usando flag, la funzione dovrebbe essere divisa.
Questo non vuol dire che non dovresti mai avere parametri opzionali, ma in generale più di uno o due parametri suggeriscono un odore di codice.
Potrebbe anche essere un indizio che la funzione, in realtà, dovrebbe essere una classe, con i parametri opzionali cambiati in proprietà e i parametri richiesti fanno parte del costruttore.
I parametri opzionali vanno bene
In genere la giustificazione è che a) sai di avere molti argomenti possibili per il tuo metodo ma non vuoi sovraccaricare per paura di ingombrare l'API, oppure b) quando non conosci tutti i possibili argomenti ma tu non voglio forzare l'utente a fornire un array. In ogni caso i parametri opzionali vengono in soccorso in modo pulito ed elegante.
Ecco alcuni esempi:
1. Si desidera evitare il sovraccarico e non si desidera specificare un array
Dai un'occhiata a printf () da C, Perl, Java ecc. È un ottimo esempio della potenza dei parametri opzionali.
Per esempio:
printf("I want %d %s %s",1,"chocolate","biccies");
printf("I want %d banana",1);
Nessun sovraccarico, nessuna matrice, semplice e intuitivo (una volta acquisiti i codici di formato stringa standard). Alcuni IDE ti diranno anche se la tua stringa di formato non corrisponde ai tuoi parametri opzionali.
2. Si desidera consentire l'uso dei valori predefiniti e tenerli nascosti all'utente del metodo
sendEmail ( "test@example.org");
Il metodo sendEmail rileva la mancanza di vari valori essenziali e li riempie usando valori predefiniti definiti (soggetto, corpo, cc, ccn ecc.). L'API è mantenuta pulita, ma flessibile.
Una nota su troppi parametri
Tuttavia, come altri hanno affermato, avere troppi parametri obbligatori in un metodo indica che probabilmente hai qualcosa di sbagliato nel tuo design. Ciò è particolarmente vero se condividono lo stesso tipo in quanto possono essere scambiati dallo sviluppatore per errore portando a risultati strani in fase di esecuzione:
String myMethod(String x, String y, String z, String a, int b, String c, int d) {}
è un candidato ideale per il refactoring di Introduce Parameter Object da creare
String myMethod(ParameterObject po) {}
class ParameterObject {
// Left as public for clarity
public String x;
public String y;
... etc
}
Questo a sua volta può portare a un design migliore basato su un modello Factory con una specifica fornita come oggetto parametro.
Uno dei problemi con i parametri predefiniti in C # (sto pensando che DoSomething sia vuoto (int x = 1)) è che sono costanti. Ciò significa che se si modifica il valore predefinito, sarà necessario ricompilare tutti gli utenti di tale chiamata del metodo. Mentre questo è abbastanza facile da fare ci sono occasioni in cui questo è pericoloso.
Dipende da cosa sta facendo il tuo codice. Se ci sono valori predefiniti sensibili, allora dovresti usare parametri opzionali ma se non ci sono valori predefiniti ragionevoli, l'aggiunta di parametri opzionali renderà il tuo codice più complicato. In molti casi i parametri opzionali sono un modo semplice per eludere i controlli zero e tagliare la logica di ramificazione. Javascript non ha parametri opzionali ma esiste un modo per emularli con || (logico o) e lo uso sempre quando faccio cose relative al database perché se l'utente non fornisce alcun valore, sostituisco i miei valori con l'aiuto di || che mi fa risparmiare la fatica di scrivere un sacco di istruzioni if then.
I parametri opzionali sono un ottimo modo per rendere le cose semplici cose semplici e complicate possibili contemporaneamente. Se esiste un chiaro ragionevole default che la maggior parte degli utenti vorrà, almeno in casi di utilizzo rapido e sporco, non dovrebbero scrivere la piastra di caldaia per specificarlo manualmente ogni volta che chiamano la tua funzione. D'altra parte, se le persone potrebbero avere una buona ragione per volerlo cambiare, allora deve essere esposto.
L'uso di una classe è IMHO una soluzione terribile, in quanto verbosa, inefficiente e incoerente con il tipico modello mentale di ciò che fa una classe. Una funzione è l'astrazione perfetta per un verbo, cioè fare qualcosa e tornare. Una classe è l'astrazione giusta per un sostantivo, cioè qualcosa che ha uno stato e può essere manipolato in diversi modi. Se il primo dovrebbe essere il modello mentale dell'utente API, non renderlo una classe.
Il problema con gli argomenti opzionali è che le persone tendono a nascondere sempre più (e più) argomenti alla funzione invece di estrarre il codice rilevante in una nuova funzione. Questo è portato all'estremo in php . Per esempio:
bool array_multisort ( array &$arr [, mixed $arg = SORT_ASC
[, mixed $arg = SORT_REGULAR [, mixed $... ]]] )
Inizialmente ho adorato questa funzionalità in Python e l'ho usata per "estendere" i metodi già utilizzati. E sembrava carino e facile, ma tornò presto; perché quando ho aggiunto un parametro opzionale, questo stava modificando il comportamento di un metodo esistente su cui si basava il vecchio client e in un modo che non era stato rilevato dai casi di unit test esistenti. Fondamentalmente farlo è infrangere il principio aperto chiuso; il codice è aperto per l'estensione ma chiuso per modifica. Quindi credo che usare questa funzione per modificare il codice esistente non sia una buona idea; ma va bene se usato dall'inizio
Penserei che sarebbe meglio sovraccaricare una funzione con firme diverse (cioè parametri) piuttosto che usare parametri opzionali.