Restituisce sempre il parametro quando è cambiato nel metodo?

2

Quando hai un metodo che sta facendo cose e le modifiche si verificano nei parametri, dovresti sempre restituire l'oggetto modificato in questo modo:

public SomeModel DoSomething(SomeModel someModel) {

[something made changes to the model in here]

return someModel;
}

In questo modo quando qualcuno legge la riga che si verifica quando il metodo è stato usato, vede che l'oggetto return equivale a un oggetto parametro, quindi sanno che ci sono state modifiche a questo oggetto. D'altra parte quando ci sono più parametri e tutti hanno avuto delle modifiche, non è possibile utilizzare questa tecnica.

Non restituire nulla:

public void DoSomething(SomeModel someModel) {

[something made changes to the model in here]

}

In questo modo non sapresti se il parametro SomeModel è cambiato. Questo potrebbe essere (forse) indicato dal nome del metodo comunque.

    
posta MuhKuh 06.12.2018 - 18:54
fonte

3 risposte

6

Non sono d'accordo. Ci sono troppi modi in cui questo può fallire nell'usarlo per trasmettere informazioni. Se non altro, il nome del metodo dovrebbe rendere chiaro se muta l'input, piuttosto che fare affidamento su indecenti indizi del tipo restituito.

Considera queste modalità di errore piuttosto comuni (scusate lo stile Java-esque):

public Model copy(Model m)

Il nome implica l'azione - fa solo una copia (anche se non riesce a dire se è profondo o superficiale, se differiscono in questo caso). Sarebbe piuttosto brutto se pensassi che questo muta il modello e lo restituisca, solo sulla base dell'essere utilizzato per il tuo schema.

public Collection<Model> readInput(Input in)

Questo metodo ha una firma appropriata ed è ovvio cosa sta facendo. C'è una buona probabilità che muta in e non sarà in grado di ripristinarlo allo stato originale (né dovrebbe, davvero). Se sei abituato al tuo metodo, non riuscirai a interpretare correttamente ciò che sta facendo.

Una possibile "correzione" sarebbe passare in una raccolta per aggiungere nuovi modelli a, ma poi hai 2 parametri mutati.

Un'altra "correzione" è di avere una raccolta di istanze locali da usare, ma c'è una miriade di motivi per cui è una cattiva idea. Mi concentrerò su 1 di loro in particolare: Un flusso di input completamente letto è inutile da restituire . Non c'è letteralmente niente che puoi fare con esso, tranne chiuderlo. La maggior parte delle volte, il tuo output verrà semplicemente ignorato.

Generalmente preferisco i metodi void quando si tratta di metodi il cui obiettivo principale è di mutare i loro parametri o lo stato locale. Un metodo void che non muta nulla potrebbe anche essere un codice morto (con la sola eccezione dei metodi di asserzione che throw ). In quanto tale, se vedi un metodo void , sai che qualcosa sarà mutato.

C'è una buona ragione per restituire il tuo argomento mutato, ovvero rendere la tua API amichevole per concatenare . Quando hai ragione di credere che l'utente invocherà più metodi in una riga, e non c'è niente di meglio da restituire, restituisci l'input mutato.

Ma che tu stia concatenando, copiando, leggendo o consumando, l'idea principale è che la firma del metodo dovrebbe darti le informazioni rilevanti su cosa fa e quali effetti collaterali ha . Probabilmente ciò comporterà un certo ammontare di convenzioni, ma c'è da aspettarselo, davvero. L'output darà qualche idea in più su come utilizzare il risultato del metodo, ma non su ciò che fa.

    
risposta data 06.12.2018 - 19:55
fonte
3

Se vedo:

public SomeModel DoSomething(SomeModel someModel)

quindi, a meno che non abbia accesso alla fonte e legga per scoprire altrimenti, in genere presumo che restituisca un nuovo SomeModel , lasciando invariato l'originale. Se lo modifichi, viene violato il principio di minimo stupore :

var model = new SomeModel();
var newmodel = DoSomething(model);
// What the? model just changed!

Se il tuo metodo ha per modificare model , fallo un metodo void e rendi chiaro dal nome che modifica il parametro. Ma direi che, se possibile, è meglio creare una nuova copia dal parametro, modificarla e restituirla, lasciando il parametro invariato.

    
risposta data 07.12.2018 - 11:12
fonte
-1

In effetti, è una pratica scorretta cambiare gli oggetti in un metodo che non appartiene a quell'oggetto, quindi dovresti evitarlo. Puoi provare a spostare il codice che modifica l'oggetto nella classe SomeModel. Questo è molto più intuitivo per gli sviluppatori.

Se per qualche motivo, non vuoi il codice all'interno della classe SomeModel, ti suggerisco di scrivere un metodo di estensione. In questo modo il consumatore della classe SomeModel può ancora scrivere lo stesso codice.

Per entrambe le soluzioni, dovresti comunque rendere molto chiaro nel tuo nome del metodo che l'oggetto è cambiato.

    
risposta data 07.12.2018 - 11:27
fonte

Leggi altre domande sui tag