Come gestire una gerarchia di eccezioni: mediante il wrapping o l'ereditarietà?

2

Sto scrivendo una libreria riutilizzabile e sto cercando un modo per gestire le eccezioni che potrebbero verificarsi durante l'elaborazione. Ad esempio, ho la seguente classe:

public interface IObjectFetcher
{
    public IObject GetObject(int objectId);
}

public class WidgetFetcher : IObjectFetcher
{
    public IObject GetObject(int objectId)
    {
        var fileName = DetermineWidgetFileName(objectId);
        var widget = GetWidgetFromFile(fileName);
        widget.Frob = GetWidgetFrob(objectId);
        return widget;
    }

    private string DetermineWidgetFileName(int widgetId)
    {
        return someExternalDbService.GetFileNameForWidget(widgetId); //throws DbException
    }

    private Widget GetWidgetFromFile(string fileName)
    {
        return someExternalFileService.GetWidgetFromFile(fileName); //throws FileException
    }

    private Frob GetFrobForWidget(int widgetId)
    {
        return someExternalDbService.GetFrobForWidget(widgetId); //throws DbException
    }
}

Come gestire DbException e FileException in modo che:

  • il contratto di eccezione di IObjectFetcher.GetObject non diventa troppo complesso e può consentire implementazioni diverse
  • c'è un modo per accedere alla causa sottostante dell'eccezione, come una connessione al database fallita o un file mancante
  • c'è un modo per distinguere tra DbException causato dalla ricerca di un nome file e il DbException causato dal recupero di un Frob
  • è possibile allegare i metadati delle eccezioni come l'ID oggetto e il nome del file in modo strutturato, ad es. per estrarre i modelli di messaggi di eccezione in un file di risorse

Mi sembra che dovrei creare eccezioni personalizzate per ogni fase del processo (con InnerException come DbException o FileException ), e quindi ho due modi per affrontare il problema - o fare in modo che tali eccezioni personalizzate ereditino da una singola classe di base, o che siano racchiuse da una singola classe di eccezioni. Quale approccio è corretto? O dovrei semplificarlo ulteriormente?

    
posta Maciej Stachowski 20.02.2018 - 15:45
fonte

1 risposta

3

IMHO una struttura di classi di eccezioni complesse è spesso semplicemente sovra-ingegneristica.

Prima assicurati che i proiettili che hai elencato siano realmente requisiti di alcuni utenti della tua libreria.

In particolare metterei in discussione l'importanza di differenziare tra diverse cause di eccezione. Chi ha bisogno di questo? dalla mia esperienza, un'eccezione è destinata a:

  • Dì al chiamante del metodo che non è riuscito a rispettare il suo contratto. Questo non ha bisogno di più tipi di eccezione.
  • Supporta la registrazione dei problemi, fornendo un messaggio utile e una traccia dello stack. Anche questo non ha bisogno di classi di eccezione diverse.
  • Permetti al chiamante di riprovare l'azione fallita, magari decidendo l'alternativa migliore in base al tipo di errore. Fare ciò può fare buon uso del tipo di eccezione, ma raramente ho visto un simile modello nel software reale.

Quindi, se pensi che alcuni utenti della tua libreria vorranno fare "tentativi intelligenti" (e la tua libreria offre la possibilità di farlo), vai per una gerarchia di classi di eccezioni che permetta di farlo, altrimenti assicurati solo che le eccezioni portare messaggi decenti per scopi di registrazione.

    
risposta data 20.02.2018 - 19:30
fonte

Leggi altre domande sui tag