Un metodo Connect () dovrebbe restituire false in caso di errore o generare eccezioni?

4

Ho trovato questa domanda Restituisci valore magico, genera eccezioni o restituisci falso in caso di fallimento? , tuttavia è abbastanza ampio. Vorrei una risposta più specifica.

Dire che ho un metodo chiamato Connect () che si connette a un dispositivo remoto su un socket Ethernet. Se il socket fallisce, genera SocketException.

Quindi il modo in cui lo vedo ho 2 opzioni valide.

Opzione 1: Cattura l'eccezione e restituisce true.

public void CallConnect()
{
    while(!Connect())
    {
        //** Log error 
    }

    //** do what ever
}


public bool Connect()
{
    try
    {
        _socket.Connect()
        return true;
    }
    catch(SocketException)
    {
        return false;
    }
    catch(<SomeOtherException1>)
    {
        return false;
    }
    catch(<SomeOtherException2>)
    {
        return false;
    }   
}

Opzione 2: Throw Generic Exception

public void Connect()
{
    try
    {
        _socket.Connect()
    }
    catch(SocketException ex)
    {
        throw new ConnectionException("Blah blah I failed 1", ex); 
    }
    catch(<SomeOtherException1>)
    {
        throw new ConnectionException("Blah blah I failed 2", ex);
    }
    catch(<SomeOtherException2>)
    {
        throw new ConnectionException("Blah blah I failed 3", ex);
    }   
}

public void CallConnect()
{
    bool connected == false;
    while(!connected)
    {
        try
        {
            Connect();
            connected = true;
        }
        catch(ConnectionException)
        {
            //** Log error 
        }

    }
}

Se capisco che un errore è un comportamento normale o previsto, non deve essere generata alcuna eccezione, ma se l'errore non dovrebbe mai accadere allora sì dovrebbe essere lanciata un'eccezione.

La mancata connessione potrebbe essere considerata un comportamento previsto se per consentire a qualcuno di scollegare il cavo Ethernet, o se qualcuno spegne il dispositivo con cui ha bisogno di comunicare, ma potrebbe anche essere considerato un comportamento eccezionale.

Ora se dovessi chiedere come dovrebbe gestirlo se l'invio fallisce dopo che mi sono connesso con successo, penso che la risposta sia ovviamente un'eccezione.

    
posta TheColonel26 13.04.2018 - 16:57
fonte

2 risposte

12

La convenzione con .NET è lanciare un'eccezione e se vuoi un metodo che restituisce un valore booleano crea un altro metodo chiamato TryFoo.

Quindi, void Connect() genererebbe un'eccezione per qualsiasi tipo di errore.

E bool TryConnect() restituirebbe false per qualsiasi motivo che Connect genererebbe un'eccezione.

Esempi di questa convenzione sono i vari metodi parse , come int int.Parse(string) che ha un altro metodo chiamato bool int.TryParse(string, out int) .

Il metodo int.Parse(string) genera un'eccezione se non è in grado di analizzare la stringa. Il metodo int.TryParse(string, out int) restituirà false se non è in grado di analizzare la stringa.

L'unica differenza tra questo esempio nel framework .NET e la tua situazione è l'argomento out , che non è necessario nel tuo caso.

Questo ti consente due casi d'uso:

foo.Connect();
foo.OperationThatRequiresAConnection();

L'esempio sopra non tenta di eseguire alcuna gestione degli errori. Lanciando un'eccezione è possibile garantire che la prossima istruzione successiva a una chiamata a Connect abbia una connessione aperta. L'esempio di codice precedente non può gestire il caso in caso di interruzione di una connessione e si basa sulla gestione degli errori di livello superiore nell'applicazione.

Contrasto con:

if (foo.TryConnect())
{
    foo.OperationThatRequiresAConnection();
}
else
{
    MessageBox.Show("Your username or password was incorrect. Try again.");
}

In questo scenario fittizio, il codice può recuperare da una connessione fallita chiedendo all'utente di immettere nuovamente le informazioni e riprovare l'operazione.

Classi di libreria senza accesso al codice sorgente

Se hai a che fare con una libreria di classi che ha un metodo Connect() , e non hai accesso al codice sorgente per aggiungere un metodo TryConnect --- Metodi di estensione C # per il salvataggio!

public static bool TryConnect(this LibraryClass connector)
{
    try
    {
        connector.Connect();

        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

Quindi puoi aggiungere la tua registrazione specifica per applicazioni personalizzate, se lo desideri.

    
risposta data 13.04.2018 - 18:03
fonte
1

Non sono d'accordo con la risposta di @Greg Burghardt perché dipende dal contesto.

Vuoi seguire il consiglio di lanciare eccezioni quando scrivi codice di libreria perché molto probabilmente non avrai alcuna registrazione lì e vuoi sapere cosa è andato storto.

Se tuttavia utilizzi questo codice e includi in qualche progetto helper di progetto che aggiunge la registrazione o altre cose, il tuo nuovo metodo Connect potrebbe anche restituire boolean .

    
risposta data 23.04.2018 - 10:37
fonte

Leggi altre domande sui tag