Argomenti (parametri) nominati come ausilio alla leggibilità


11

Molto tempo fa ho programmato molto in ADA ed era normale nominare argomenti quando si invocava una funzione - SomeObject.DoSomething (SomeParameterName => someValue);

Ora che C # supporta argomenti denominati, sto pensando di ripristinare questa abitudine in situazioni in cui potrebbe non essere ovvio cosa significhi un argomento.

Potresti sostenere che dovrebbe sempre essere ovvio cosa significhi un argomento, ma se hai un argomento booleano e i chiamanti stanno passando "vero" o "falso", qualificare il valore con il nome rende il sito di chiamata più leggibile.

contentFetcher.DownloadNote (nota, manuale: true);

Immagino di poter creare Enum invece di usare true o false (Manuale, Automatico in questo caso).

Cosa ne pensi di utilizzare occasionalmente argomenti con nome per rendere più facile la lettura del codice?


Anche il commento dei parametri in cima ai metodi aiuta.
Amir Rezaei,

1
@ amir-rezaei: i commenti sui parametri in cima ai metodi aiutano solo se puoi fidarti dei commenti. A meno che tu non abbia buoni sviluppatori e buoni processi di revisione del codice, non mi fiderei dei commenti.
btilly,

Come utente Ada una sola volta, sono per un uso occasionale come descrivi. È così che mi ricordo che venivano usati in Ada, BTW: non lo definirei "anormale", ma la parola "normale" sembra implicare che la maggior parte delle chiamate specificherebbe i nomi dei parametri, il che non è il modo in cui ricordo le cose. Naturalmente le convenzioni variano, ma il disordine inutile è una cattiva convenzione in qualsiasi lingua IMO.
Steve314,

Sono d'accordo sul tuo utilizzo in Ada: non è stato qualcosa che abbiamo sempre fatto, ma dove ci ha aiutato.
Damian,

Risposte:


7

Ciò è stato suggerito nello sviluppo del C ++ e Stroustrup ne parla nel suo "Design and Evolution of C ++", pagine 153 e seguenti. La proposta era ben formata e si basava su precedenti esperienze con Ada. Non è stato adottato.

Il motivo principale era che nessuno voleva incoraggiare funzioni con un gran numero di parametri. Ogni funzione aggiuntiva in una lingua costa qualcosa e non si desiderava aggiungere una funzione per facilitare la scrittura di programmi errati.

Ha anche sollevato dubbi su quali fossero i nomi dei parametri canonici, in particolare nella solita convenzione di file di intestazione e codice. Alcune organizzazioni avevano nomi di parametri più lunghi e più descrittivi nel file .h e più brevi e più facili da digitare i nomi nel file .cpp (sostituire i suffissi di file come desiderato). Richiedere che siano uguali comporterebbe un costo aggiuntivo per la compilazione e la confusione dei nomi tra i file di origine potrebbe causare bug sottili.

Può anche essere gestito utilizzando oggetti anziché chiamate di funzione. Invece di una chiamata GetWindow con una dozzina di parametri, crea una classe Window con una dozzina di variabili private e aggiungi setter come necessario. Incatenando i setter, è possibile scrivere qualcosa di simile my_window.SetColor(green).SetBorder(true).SetBorderSize(3);. È anche possibile avere funzioni diverse con impostazioni predefinite diverse che chiamano la funzione che svolge effettivamente il lavoro.

Se sei solo preoccupato per l'effetto della documentazione di contentFetcher.DownloadNote(note, manual : true);, puoi sempre scrivere qualcosa del genere contentFetcher.DownloadNote(note, /* manual */ true);, quindi non è nemmeno molto utile nella documentazione.


Stranamente quando mi sono trasferito da Ada a C, ho iniziato a usare la convenzione che descrivi, anche se i revisori del codice lo odiavano. Accetto di non utilizzarlo per un gran numero di parametri.
Damian,

7

Penso che questo sia il problema di rendere più leggibile il cattivo codice, piuttosto che la "migliore pratica".

Avere un metodo (o appaltatore) che accetta 20 parametri è un "cattivo odore" ed è probabilmente dovuto a un problema nella progettazione. Tuttavia, se sono costretto a lavorare sul codice quando i metodi accettano molti parametri, allora il parametro denominato rende il codice meno difficile da capire.

Quando i metodi hanno solo 1 o 2 parametri ed è chiaro dal nome del metodo quali sono i parametri, allora il parametro denominato non aggiunge nulla. Questo è il caso ideale per essere dentro.

Se tutto il codice su cui lavori è scritto come il libro " codice pulito ", allora avrai pochissimo uso per i parametri nominati, tuttavia viviamo nel mondo reale.


1
Una funzione con due parametri può essere fonte di confusione, se entrambi i parametri sono dello stesso tipo e senza alcun indizio su quale sia. Ovviamente puoi nominare la funzione in un modo che fornisca quell'indizio, ma stai davvero facendo ciò che fanno comunque i nomi dei parametri - tranne per il fatto che rendi obbligatorio includere quella verbosità anche quando il contesto (ad esempio le espressioni che forniscono il parametri) rendono evidente quale parametro è quale.
Steve314,

1
@ Steve314 Esempio:void TrackDataChange(Data oldData, Data newData)
Alexander

3

Sono d'accordo che l'aggiunta del nome del parametro lo rende più leggibile. Tuttavia, la maggior parte dei libri che ho letto sembrano considerare gli switch booleani una cattiva pratica. A volte lo faccio:

public Content DownloadNote(Note note)
{
    return downloadNote(note, manual: false);
}

public Content DownloadNoteManually(Note note)
{
    return downloadNote(note, manual: true);
}

Ciò ti offre maggiore flessibilità durante l'implementazione dell'API. Ti permette anche di controllare il caso in cui hai più switch booleani, ma non tutti possono essere attivi contemporaneamente.


3
Se hai x scelte, farai 2 ^ x frontend?
apoorv020,

@ apoorv020 - se avessi abbastanza parametri per una chiamata al metodo che 2 ^ x diventasse significativo, farei una nuova classe per contenere i valori dei parametri e passerei solo un parametro.
Scott Whitlock,

@ scott-whitlock: Opzione 1: crea un oggetto, imposta proprietà x, chiama un metodo una volta con il tuo oggetto. Opzione 2: chiama un metodo con x parametri denominati. Quale è meglio dipende dalla tua lingua. In un linguaggio tipizzato in modo dinamico, l'opzione 1 richiede una quantità significativamente maggiore di boiler-plate senza guadagno, e quindi è peggio. In una lingua tipicamente statica si aggiunge ancora la piastra della caldaia, ma i test per chiavi con nomi errati devono essere eseguiti in fase di compilazione anziché in fase di esecuzione. Pertanto l'opzione 1 è migliore in C #, ma l'opzione 2 è una chiara vittoria in Python.
btilly,

@btilly - come ha sottolineato Ian, Clean Code ti dice chiaramente di non avere funzioni con più di 2 o 3 parametri. Per essere onesti, si trattava di Java, che è tipicamente statico. L'OP chiede anche di C #, che è tipicamente statico. Preferirei comunque utilizzare sovraccarichi di funzioni e / o nomi di funzioni con nomi precisi diversi rispetto a un lungo elenco di parametri.
Scott Whitlock,

@ scott-whitlock: in realtà non siamo d'accordo? Siamo d'accordo su ciò che è meglio in C #. Sappiamo entrambi cosa dice Clean Code. Il mio punto era che è importante capire perché è buono, in modo da sapere quando i consigli si adattano o meno a un ambiente diverso.
btilly,

3

Sono un grande sostenitore dei parametri nominati in situazioni in cui i tipi e la semantica non sono chiari dal nome del metodo. La mia esperienza è che poche persone hanno letto la documentazione.

Detto questo, i parametri nominati non dovrebbero essere un'alternativa alla creazione di elenchi di argomenti sensibili, utilizzando oggetti helper (per "legare" argomenti semanticamente correlati) e, se pertinente, utilizzare le enumerazioni.


0

Penso che questo sia più utile nei linguaggi non OO, dove potresti avere una funzione che deve fare qualcosa in diversi modi leggermente diversi, e il modo in cui determina cosa fare si basa sui valori dei parametri. Nel mondo OOP, potremmo semplicemente sovraccaricare la funzione, ma quando ciò non è possibile, finisci per passare un gruppo di bandiere (o un gruppo di valori e se sono passate o meno è la bandiera).

Penso che sia più leggibile, in una certa misura; ma come altri hanno già detto, avere molti parametri è un odore di codice, quindi non vedo molto uso di ciò in un linguaggio orientato agli oggetti come C #.

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.