2010-06-08 15 views
8

Stavo guardando un codice che ho ereditato e non ho potuto decidere se mi piace un po 'di codice.Un metodo di connessione può restituire un valore?

In sostanza, v'è un metodo che è simile al seguente:

bool Connect(connection parameters){...} 

Restituisce vero se si collega con successo, falso altrimenti.

Ho scritto codice simile in passato, ma ora, quando vedo questo metodo, non mi piace per una serie di motivi.

  1. È un codice facile da scrivere che ignora il valore restituito o non si rende conto che restituisce un valore.

  2. Non è possibile restituire un messaggio di errore.

  3. Controllo del ritorno del metodo in realtà non un aspetto gradevole:

    se {....}

ho potuto riscrivere il codice per (Connect (...)!) lanciare un'eccezione quando non si connette correttamente, ma non considero questa una situazione eccezionale. Invece sto pensando di refactoring del codice come segue:

void Connect(Connection Parameters, out bool successful, out string errorMessage){...} 

Mi piace che altri sviluppatori sono tenuti a fornire le stringhe di successo e di errore in modo da conoscere il metodo ha le condizioni di errore e posso sapere restituire un messaggio

Qualcuno ha qualche idea in merito?

Grazie -Matt

risposta

3

Ho solo un'opinione, quindi prendilo per quello che vale.

Un metodo denominato "Connetti" è un ordine. È come darlo a un soldato, "Salta" o "Spara". Non ti aspetti che il soldato faccia rapporto a meno che non sia in grado di completare l'ordine, e questo sarebbe un evento raro.

Come tale, ho la tendenza a non avere un valore di ritorno per tali metodi, ma se c'è una possibilità che con l'uso regolare del metodo, ci saranno errori, quindi costruisco un secondo metodo, chiamato TryXYZ, restituire un bool e, se necessario, fornirmi i risultati di qualsiasi parametro XYZ come out.

Questo segue lo standard definito dai metodi Parse di vari tipi numerici nel BCL .NET.

Quindi nel tuo caso, probabilmente avrei:

void Connect(connection parameters); 
bool TryConnect(connection parameters, out status); 

La cosa bella è che se si costruisce il metodo TryConnect correttamente, Connect diventa davvero facile.

Esempio:

public bool TryConnect(string connectionString, out ConnectionStatus status) 
{ 
    ... try to connect 
    ... set status, and return true/false 
} 

public void Connect(string connectionString) 
{ 
    ConnectionStatus status; 
    if (!TryConnect(connectionString, out status)) 
     switch (status) 
     { 
      case ConnectionStatus.HostNotFound: 
       throw new HostNameNotFoundException(); 
      ... 
     } 
} 

Non mi aspetto che i miei ordini a non è completa, ma nel senso che potrebbe, voglio essere esplicito su di esso.

+0

Mi piace questo approccio. Certamente rende le cose chiare. Penso che combinare il metodo TryConnect (...) con il suggerimento di Foovanadil su un tipo di reso personalizzato sia ciò che sto per fare. –

+0

Se la tua connessione è di breve durata potresti anche considerare la restituzione IDisposable per consentire una facile pulizia della connessione in questo modo: usando (var connection = connect (...)) { // usa la connessione } –

12

opterei per l'eccezione rispetto ai parametri out. Se vuoi che i consumatori della tua classe si preoccupino, falli curare con l'eccezione, oppure lasciali soli. Usando i parametri out, stai semplicemente rendendo le loro vite più scomode se non lo fanno hanno da rendere facendo uso di variabili throwaway. Considera anche che se la tua funzione è già in circolazione, stai introducendo un cambio di rottura se cambi la firma (invece di fornire un sovraccarico aggiuntivo).

I programmatori prevedono eccezioni nei casi di errore, in particolare in linguaggi come C#. Siamo stati addestrati

+1

sono d'accordo con questa risposta. Normalmente, non essere in grado di connettersi a qualcosa è considerato un caso eccezionale e tende a essere trattato come tale in .NET Framework (ADO.NET, WCF). Restituire una coppia di messaggi di errore/successo è la programmazione in stile API di vecchia scuola - è molto più semplice gestire un'eccezione fortemente tipizzata con un try/catch (e questa è la convenzione). Se hai gli strumenti a tua disposizione, dovresti usarli. – luksan

1

Vedo i tuoi punti ma per aggiungere il mio 2c.

In genere non sono un fan dei parametri di output. Se è necessario restituire più valori da una funzione per rivalutare ciò che sta facendo la funzione, nella maggior parte dei casi i valori di ritorno multipli sono un segno che un metodo fa troppo. Nel tuo caso è legittimo che un tipo complesso venga restituito dal tuo metodo di connessione (oltre un semplice booleano).

Sarei favorevole alla restituzione di un tipo personalizzato dal metodo connect che memorizza tutte le informazioni rilevanti anziché i parametri di output multipli. Pensa all'estensione futura, e se hai bisogno di includere più informazioni lungo la strada.L'aggiunta di ulteriori parametri di output è un cambiamento di rottura

Inoltre, io tendo a non essere d'accordo costringendo un utente a fornire allocazioni di memoria per tutti i dati di stato. Ci possono essere momenti in cui non mi interessa il messaggio di successo (forse mi interessa solo se commette errori) nel qual caso dover passare entrambi i parametri di output è un problema.

Sono d'accordo però che controllare il valore di ritorno del metodo iniziale pubblicato non è l'ideale.

0

Non sono sicuro che questo sia meglio del codice di refactoring, ma spero che questo possa darvi un'altra idea.

Per i miei progetti, creo un metodo che restituisce l'ultimo messaggio di errore.

string Error = ''; 
bool Connect(connection parameters) 
{ 
// do my connection here 
// if there's an error set string variable Error 
// This way you can set different error message depending on what you're doing 
} 

string lastErrorMessage(){ 
// return Error string 
} 

In questo modo si può fare questo:

if(!connect(...)) 
{ 
string message = lastErrorMessage(); 
// Then do what you need here. 
} 

questo potrebbe non essere il modo migliore, ma dovrebbe aiutare :)

1

non mi dispiace la funzione Connect restituisce un valore booleano e non sono un grande fan dei parametri di output. Se la funzione non ha restituito lo stato della connessione, probabilmente dovresti scrivere una funzione/proprietà IsConnected (a seconda del tuo stile) in ogni caso per consentire a qualcuno di controllarlo, quindi salva un passaggio.

Per quanto riguarda le aspettative, lasciare che l'eccezione venga catturata dal codice chiamante, che costringerà il chiamante a preoccuparsi. :)

1

Sono d'accordo sul fatto che non riuscire a stabilire una connessione (nella maggior parte dei casi) non dovrebbe essere visto come una situazione eccezionale. Tuttavia, forzare l'utente a fornire argomenti per la stringa di errori, ecc. Non è bello. Altre possibili soluzioni:

  1. Utilizzare la registrazione. L'inconveniente è che i messaggi vengono scritti nel registro ma non (senza molto sforzo) disponibili per il chiamante.
  2. Utilizza il ritorno booleano e fornisce i metodi per interrogare l'ultimo errore (come errno in C). IMHO non è bello neanche.
  3. Rif. Codice, restituisce un oggetto di una classe di connessione. Fornire metodi per interrogare lo stato della connessione.
  4. restituire un'istanza di una classe che raccoglie tutte le informazioni pertinenti, alias isSuccessfull(), getErrorString, ecc
Problemi correlati