Quando e perché dovresti usare void (invece di ad esempio bool / int)

29

Occasionalmente mi imbatto in metodi in cui uno sviluppatore ha scelto di restituire qualcosa che non è fondamentale per la funzione. Voglio dire, quando guardo il codice, a quanto pare funziona altrettanto bene di void e dopo un momento di riflessione, chiedo "Perché?" Ti sembra familiare?

A volte sono d'accordo che molto spesso è meglio restituire qualcosa come bool o int , piuttosto che fare solo un void . Non sono sicuro, però, nel quadro generale, dei pro e dei contro.

A seconda della situazione, restituire un int può rendere consapevole il chiamante della quantità di righe o oggetti interessati dal metodo (ad es. 5 record salvati in MSSQL). Se un metodo come "InsertSomething" restituisce un valore booleano, posso avere il metodo progettato per restituire true in caso di successo, altrimenti false . Il chiamante può scegliere di agire o meno su tali informazioni.

D'altra parte,

  • Può portare a uno scopo meno chiaro di una chiamata al metodo? La cattiva codifica mi costringe spesso a ricontrollare il contenuto del metodo. Se restituisce qualcosa, ti dice che il metodo è di un tipo che ha per fare qualcosa con il risultato restituito.
  • Un altro problema sarebbe, se l'implementazione del metodo ti è sconosciuta, che cosa ha deciso lo sviluppatore di restituire che non è una funzione critica? Certo che puoi commentarlo.
  • Il valore restituito deve essere elaborato, quando l'elaborazione può essere terminata nella parentesi chiusa del metodo.
  • Cosa succede sotto il cofano? Il metodo chiamato ha ottenuto false a causa di un errore generato? O ha restituito false a causa del risultato valutato?

Quali sono le tue esperienze con questo? Come agiresti su questo?

    
posta Independent 13.04.2011 - 11:15
fonte

5 risposte

31

Nel caso di un valore di ritorno bool per indicare il successo o il fallimento di un metodo, preferisco il paradigma Try -prefix usato in vari metodi .NET.

Ad esempio, un metodo void InsertRow() potrebbe generare un'eccezione se esiste già una riga con la stessa chiave. La domanda è, è ragionevole presumere che il chiamante assicuri che la loro riga sia unica prima di chiamare InsertRow? Se la risposta è no, allora fornirei anche un bool TryInsertRow() che restituisce false se la riga esiste già. In altri casi, come gli errori di connettività db, TryInsertRow potrebbe comunque generare un'eccezione, presupponendo che la manutenzione della connettività db sia responsabilità del chiamante.

    
risposta data 13.04.2011 - 11:36
fonte
27

L'IMHO che restituisce un "codice di stato" deriva dai tempi storici, prima che le eccezioni diventassero comuni in linguaggi di livello medio-alto come C #. Al giorno d'oggi è meglio lanciare un'eccezione se qualche errore imprevisto impedisce al metodo di avere successo. In questo modo è sicuro che l'errore non passa inosservato e che il chiamante può gestirlo nel modo appropriato. Quindi, in questi casi, è perfettamente corretto che un metodo non restituisca nulla (cioè void ) anziché un flag di stato booleano o un codice di stato intero. (Ovviamente si dovrebbe documentare quali eccezioni il metodo può lanciare e quando.)

D'altra parte, se si tratta di una funzione in senso stretto, cioè esegue alcuni calcoli in base ai parametri di input e si prevede che restituisca il risultato di tale calcolo, il tipo restituito è ovvio.

C'è una zona grigia tra i due, quando uno può decidere di restituire alcune informazioni "extra" dal metodo, se è ritenuto utile per i suoi chiamanti. Come il tuo esempio sul numero di righe interessate in un inserto. O per un metodo per inserire un elemento in una raccolta associativa, può essere utile restituire il valore precedente associato a quella chiave, se ce n'era. Tali usi possono essere identificati analizzando attentamente gli scenari di utilizzo (noti e previsti) di un'API.

    
risposta data 13.04.2011 - 11:25
fonte
14

La risposta di Peter copre bene le eccezioni. Un'altra considerazione qui coinvolge Comando-Separazione query

Il principio CQS afferma che un metodo dovrebbe essere un comando o una query e non entrambi. I comandi non devono mai restituire un valore, modificare solo lo stato e le query devono solo restituire e non modificare lo stato. Ciò mantiene la semantica molto chiara e aiuta a rendere il codice più leggibile e mantenibile.

Ci sono alcuni casi che violano il principio CQS è una buona idea. Questi sono in genere relativi alle prestazioni o alla sicurezza dei thread.

    
risposta data 13.04.2011 - 11:34
fonte
3

Qualunque sia la strada che hai intenzione di percorrere con questo. Non avere valori di ritorno in là per un uso futuro (ad esempio se le funzioni restituiscono sempre true) si tratta di un terribile spreco di energie e non rende il codice più chiaro da leggere. Quando hai un valore di ritorno dovresti sempre usarlo, e per poterlo usare dovresti avere almeno 2 possibili valori di ritorno.

    
risposta data 13.04.2011 - 12:02
fonte
1

Ero solito scrivere molte funzioni void. Ma dal momento che ho preso tutto il metodo di concatenare crack, ho iniziato a restituire questo piuttosto che vuoto - potrebbe anche permettere a qualcuno di sfruttare il ritorno perché non si può fare lo squat con il nulla. E se non vogliono fare nulla con esso, possono semplicemente ignorarlo.

    
risposta data 13.04.2011 - 15:21
fonte

Leggi altre domande sui tag