È una cattiva pratica riutilizzare i parametri del metodo?


12

Ci sono momenti in cui dovrò modificare un valore passato in un metodo all'interno del metodo stesso. Un esempio potrebbe essere la sanificazione di una stringa come questo metodo qui:

void SanitizeName(string Name)
{
    Name = Name.ToUpper();

    //now do something here with name
}

Questo è puramente innocuo poiché l' Nameargomento non viene passato per riferimento. Tuttavia, se, per qualche motivo, in futuro uno sviluppatore decide di far passare tutti i valori da ref, qualsiasi sanificazione della stringa influirà sul valore esterno al metodo che potrebbe avere risultati dannosi.

Pertanto, invece di riassegnare l'argomento stesso, creo sempre una copia locale in questo modo:

void SanitizeName(string Name)
{
    var SanitizedName = Name.ToUpper();

    //now do something here with name
}

Questo assicura che la modifica della trasmissione del valore non influirà mai sull'andamento del metodo, ma mi chiedo se sono eccessivamente paranoico al riguardo.


1
Sì, è una cattiva pratica; e no non è innocuo. La linea Name = Name.ToUpper();rende il codice più difficile da seguire nella tua testa come valore delle Namemodifiche. Il tuo secondo esempio non è solo più a prova di futuro, è più facile ragionare su ciò che sta facendo.
David Arno,

2
Ma che dire if (param == NULL) param = default_value;?
Aragaer,

Penso che non sia facile come sì / no.
MrSmith42,

3
Se "uno sviluppatore in futuro decidesse di far passare tutti i valori da ref" , probabilmente avrei un argomento con quel dev, il riutilizzo dei parametri coinvolto o meno ;-) Onestamente, quando si decide di passare un valore by refche non è stato passato molto prima, e quindi convertendo l'accesso locale in un accesso non locale per qualche motivo, deve sempre controllare attentamente le conseguenze.
Doc Brown,

2
Lavoro principalmente in un paradigma in cui non riassegniamo mai alcuna variabile. Mai. È divertente immaginare qualcuno alle prese con la necessità di riassegnare una piccola minoranza di variabili e poi non preoccuparsi di scatenarsi con il resto.
Karl Bielefeldt,

Risposte:


10

Penso che dipenda dalle tue convenzioni di codifica nel tuo progetto.

Personalmente lascio che eclipse aggiunga automaticamente la finalparola chiave a ogni variabile e parametro. In questo modo si vede a prima vista se un parametro viene riutilizzato.

Nel progetto al mio lavoro non consigliamo di riutilizzare i parametri, ma se si desidera semplicemente chiamare ad esempio .trim()o impostare un valore predefinito in un nullcaso, riutilizziamo il parametro la maggior parte delle volte, poiché in questi casi l'introduzione di una nuova variabile è meno leggibile rispetto al riutilizzo del parametro.

Non dovresti davvero riutilizzare un parametro per memorizzare un contenuto molto diverso perché il nome non farebbe più riferimento al suo contenuto. Ma questo è vero per ogni riassegnazione di una variabile e non limitato ai parametri.

Quindi, riuniti con il tuo team e formula convenzioni di codifica che trattano questo argomento.


0

Se si utilizza un analizzatore di codice statico per motivi di sicurezza, potrebbe essere confuso e pensare di non aver convalidato o disinfettato la variabile del parametro di input prima dell'uso. Se lo si utilizza Namein una query SQL, ad esempio, è possibile che si verifichi una vulnerabilità di iniezione SQL, che richiederebbe tempo per la spiegazione. Non va bene. D'altra parte, l'utilizzo di una variabile con un nome distinto per l'input disinfettato, senza realmente disinfettare l'input, è un modo rapido per mettere a tacere gli analizzatori di codice ingenui (rilevamento di vulnerabilità falso negativo).


Nella maggior parte dei casi è anche possibile utilizzare una sorta di annotazione o commento speciale per indicare all'analizzatore di codice che ciò è inteso e non un rischio inosservato.
MrSmith42,

0

La risposta dipende dal 100% da chi leggerà il tuo codice. Quali stili trovano più utili?

Ho scoperto che il caso più generale è che si evita di riassegnare i valori in modo che gli argomenti funzionino perché troppi sviluppatori hanno modelli mentali di come funziona la funzione di chiamata che presume che non lo si faccia mai. Questo problema può essere aggravato dai debugger che stampano i valori degli argomenti con cui si chiama ciascuna funzione. Questa informazione non è tecnicamente corretta se si modificano gli argomenti e ciò può portare a strane frustrazioni.

Detto questo, i modelli mentali cambiano. Nel tuo particolare ambiente di sviluppo, potrebbe essere desiderabile nameessere "la migliore rappresentazione del nome in questo momento". Potrebbe essere desiderabile collegare in modo più esplicito le variabili su cui stai lavorando ai loro argomenti, anche se hai apportato alcune modifiche ai loro valori lungo il percorso. Ci possono anche essere sostanziali vantaggi di runtime nel riutilizzare alcune variabili particolari piuttosto che creare oggetti più voluminosi. Dopotutto, quando lavori con stringhe da 4 GB, è bello ridurre al minimo il numero di copie extra che devi fare!


-1

Ho un problema completamente diverso con il tuo esempio di codice:

Il nome del tuo metodo è SanitizeName. In questo caso, mi aspetto che disinfetti un nome ; perché è quello che dici al lettore della tua funzione.

L' unica cosa che funzioni dovrebbe essere la sanificazione di un determinato nome . Senza leggere il tuo codice, mi aspetterei quanto segue:

string SanitizeName(string Name)
{
    //somehow sanitize the name
    return Result;
}

Ma tu insinui che il tuo metodo fa un po 'di più che solo sanitizng. Questo è un odore di codice e dovrebbe essere evitato.

La tua domanda non riguarda: è una cattiva pratica riutilizzare i parametri del metodo? È di più: gli effetti collaterali e il comportamento inesatto sono cattive pratiche?

La risposta è chiara: sì!

Questo è puramente innocuo poiché l'argomento Nome non viene passato per riferimento. Tuttavia, se, per qualche motivo, uno sviluppatore in futuro decide di far passare tutti i valori da ref, qualsiasi sanificazione della stringa influirà sul valore esterno al metodo che potrebbe avere risultati dannosi

Inganni il tuo lettore non restituendo nulla. Il nome del tuo metodo indica chiaramente che stai facendo qualcosa Name. Quindi, dove dovrebbe andare il risultato? Con la tua funzione la firma voidlegge che uso Namema non faccio alcun danno all'id, né ti dico del risultato (esplicitamente). Forse viene generata un'eccezione, forse no; ma Namenon è alterato . Questo è il contrario semantico al nome del tuo metodo.

Il problema è meno il riutilizzo degli effetti collaterali . Per evitare effetti collaterali non riutilizzare una variabile. Se non hai effetti collaterali non c'è nessun problema.


4
-1 Questo non risponde alla domanda originale. Il codice fornito è solo un codice di esempio per mostrare la domanda a portata di mano. Rispondi alla domanda, invece di "attaccare" / rivedere il codice di esempio fornito.
Niklas H,

1
@NiklasH Questo risponde perfettamente alla domanda: se manipoli il parametro all'interno della funzione e, come accennato dal TO, lavori accidentalmente con un riferimento anziché una copia, questo provoca effetti collaterali (come ho detto) e questo è male. Per evitare ciò, indica che stai per modificare la variabile scegliendo con cura il nome del metodo (pensa a "!" Di Ruby) e / o scegliendo un tipo di ritorno. Se non modifichi la variabile, lavora solo con le copie.
Thomas Junk,
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.