Non credo che le catture locali siano un anti-pattern, infatti se ricordo bene è effettivamente applicato in Java!
Qual è la chiave per me quando si implementa la gestione degli errori è la strategia generale. Potresti desiderare un filtro che intercetti tutte le eccezioni al limite del servizio, potresti volerle intercettare manualmente - entrambe vanno bene finché esiste una strategia generale, che rientrerà negli standard di codifica dei tuoi team.
Personalmente mi piace rilevare errori all'interno di una funzione quando posso eseguire una delle seguenti operazioni:
- Aggiungi informazioni contestuali (come lo stato degli oggetti o cosa stava succedendo)
- Gestire l'eccezione in modo sicuro (ad esempio un metodo TryX)
- Il sistema attraversa un limite di servizio e chiama in una libreria o API esterna
- Vuoi catturare e riproporre un diverso tipo di eccezione (forse con l'originale come eccezione interna)
- L'eccezione è stata generata come parte di alcune funzionalità in background di basso valore
Se non è uno di questi casi, non aggiungo un tentativo / cattura locale. In tal caso, a seconda dello scenario, potrò gestire l'eccezione (ad esempio un metodo TryX che restituisce un falso) o riproporre in modo che l'eccezione verrà gestita dalla strategia globale.
Per esempio:
public bool TryConnectToDatabase()
{
try
{
this.ConnectToDatabase(_databaseType); // this method will throw if it fails to connect
return true;
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
return false;
}
}
O un esempio di ripensamento:
public IDbConnection ConnectToDatabase()
{
try
{
// connect to the database and return the connection, will throw if the connection cannot be made
}
catch(Exception ex)
{
this.Logger.Error(ex, "There was an error connecting to the database, the databaseType was {0}", _databaseType);
throw;
}
}
Quindi si rileva l'errore nella parte superiore dello stack e si presenta all'utente un messaggio di facile utilizzo.
Indipendentemente dall'approccio adottato, vale sempre la pena creare unit test per questi scenari, in modo da poter assicurarsi che la funzionalità non cambi e interrompere il flusso del progetto in un secondo momento.
Non hai menzionato in quale lingua stai lavorando ma essendo uno sviluppatore .NET e hai visto questo troppe volte per non menzionarlo.
NON SCRIVERE:
catch(Exception ex)
{
throw ex;
}
Uso:
catch(Exception ex)
{
throw;
}
Il primo ripristina la traccia dello stack e rende il tuo livello più alto completamente inutile!
TLDR
Catturare localmente non è un anti-pattern, spesso può far parte di un design e può aiutare ad aggiungere ulteriore contesto all'errore.