Devo fare le mie eccezioni, o cooptare eccezioni simili per scopi leggermente non standard?

8

Questa è una domanda di design generale, ma mi sto concentrando su C # e su .NET perché quelle sono le lingue con cui sto lavorando in questo momento.

Devo creare le mie nuove classi di eccezioni o cooptare le eccezioni quadro esistenti per scopi leggermente diversi?

Ad esempio, sto trovando la necessità di un'eccezione che indica che un membro (cioè, ad esempio un tipo) era previsto, ma non è stato trovato durante la lettura di un assembly utilizzando Mono.Cecil . La libreria della classe base definisce l'eccezione MissingMemberException , che sembra comunicare esattamente quello che voglio, ma la descrizione dice:

The exception that is thrown when there is an attempt to dynamically access a class member that does not exist.

Che non si adatta esattamente, perché non sto dinamicamente accedendo al membro, ma piuttosto a lavorare con l'assembly passivamente.

    
posta GregRos 31.07.2015 - 22:00
fonte

3 risposte

7

In generale

Le sottoclassi delle eccezioni sono una buona idea per raggruppare le eccezioni nelle famiglie o nei raggruppamenti a cui appartengono. Consente inoltre al codice client di gestire le eccezioni in base a errori specifici o in generale. Di solito divido l'albero da qualche parte vicino alla radice tra gli errori logici e di runtime (ad esempio in C ++ il std::runtime_error rispetto a std::logic_error ).

Essere in grado di distinguere tra le eccezioni di sistema e le eccezioni dell'applicazione è anche una buona idea. Sarebbe strano se il codice client stia controllando un errore di sistema di qualche tipo ma rileva l'errore logico del codice (tramite una classe base).

Dato questo caso e C #

C # ha una gerarchia di eccezioni ricca e grande - non vorrei provare a prendere una classe base troppo in profondità. Seguendo il tuo esempio, sembra che tu stia generando un errore logico (o almeno un errore dell'applicazione), quindi la classe base o anche solo quell'eccezione potrebbe suggerire un errore di sistema. L'eccezione esatta può essere discussa, ma penso che in questo caso non è una buona scelta.

Gerarchia

Costruirò una gerarchia che consente di distinguere tra errori di sistema e di applicazione e successivamente tra errori di runtime ed errori logici. Non abbiate paura di usare le eccezioni interne - prendete l'errore di sistema e avvolgetelo in qualcosa di più significativo, dato il contesto in cui viene lanciato. Non esagerare, concentrati su quelle che sarebbero le principali eccezioni. Le eccezioni possono avere descrizioni testuali univoche associate ad esse - usarle per dare a un utente ancora più dettagli o suggerimenti su cosa fare per correggere il problema.

    
risposta data 31.07.2015 - 22:21
fonte
3

La risposta è ovviamente "dipende", ma dato il tuo caso d'uso, direi di no. Ecco perché:

C # è un meraviglioso graffio che è il miglior linguaggio orientato agli oggetti. È così bello, infatti, che a volte mi ritroverò a cercare di attuare una visione fanaticamente purista di ciò che è iniziato come un semplice progetto. Questo non mi succede così tanto quando scrivi codice JavaScript o Objective-C o PHP.

Quando arrivo in questa "modalità", questo tipo di paralisi, uno dei sintomi può essere un'ossessione per la gestione delle eccezioni, i generici e la meta-programmazione. A volte tutti e tre insieme. È molto più probabile che si tratti di un problema quando sto lavorando a qualcosa di nuovo, relativamente sconosciuto o con specifiche e obiettivi scadenti. Piuttosto che impantanarmi nei dettagli di implementazione , penso, perché provare a creare qualcosa che possa ospitare la maggior parte degli scenari che ragionevolmente prevedo? Poi, quando avrò modo di ottenere i dettagli, le basi saranno poste e scriverò un mucchio di piccoli e tozzi metodi, e così via. Forse qualcun altro funzionerà sul codice dell'interfaccia utente, fornirò loro solo questi servizi e questi contratti ...

Purtroppo, questo deve ancora capitare a me. Quello che tende ad accadere è che ho iniziato questo percorso lavorando su "infrastruttura" - cose come:

  • Scrittura delle mie interfacce contenitore IoC o altrimenti avvitamento con Castle.Windsor
  • Determinare come gestirò il mapping dei tipi nell'applicazione
  • Scrittura della logica del flusso di controllo per le classi di base astratte che assomigliano a Interceptors e che racchiudono le chiamate ai membri astratti con la gestione delle eccezioni
  • Creazione di classi base astratte per IRepository , IUnitOfWork , IDomainService , ICrossCuttingValidation , ecc.
  • Cercando di descrivere un modello di oggetto gerarchico per qualcosa la cui stessa natura nega un tale approccio meta- ( come IFrameworkException )

Quando rimani impiccato sul fatto che la descrizione di un'eccezione sia abbastanza precisa per i tuoi gusti, stai davvero negando l'implementazione di alcune altre funzionalità critiche. La natura dell'eccezione è anche indicativa - non è un'eccezione event -driven, si verifica evidentemente lontana da qualsiasi metodologia di input (come un'interfaccia utente o una pipe o qualcosa del genere) ed è probabilmente deterministica in natura - come in, non puoi prevedere cosa verrà inserito da un utente, ma puoi prevedere quale assembly scegli di caricare o whatnot.

A proposito, se la descrizione ti disturba tanto, non puoi scrivere un metodo di estensione per sovrascriverlo nell'ambito appropriato?

Quindi questo è solo il mio modo di proiettare su di te la mia paralisi di astrazione e astrazione, ma penso che potrebbe essere appropriato. Direi che per rimanere al sicuro, solo sottoclasse un Exception quando:

  • Hai effettivamente riscontrato un'eccezione di runtime che stai cercando di gestire in generale
  • L'eccezione di runtime non è qualcosa che potresti ragionevolmente escludere in fase di progettazione
  • L'eccezione non è già ben coperta dall'enorme numero esistente di Exception sottoclassi
  • In realtà hai un'idea di come vuoi gestire l'eccezione O se no, solo perché è così complicato che devi pensarci e tornare ad esso
  • La tua idea va oltre la modifica dei suoi metadati, il suo ambito, la sua eccezione interna, ecc. e tratta di più con l'oggetto o l'evento sottostante che produce l'eccezione e / o i mezzi per gestirlo effettivamente
  • Hai già scritto o non sei responsabile per la maggior parte del lato di input delle cose come l'interfaccia utente
risposta data 01.08.2015 - 03:43
fonte
1

Secondo me le eccezioni personalizzate hanno senso solo in 2 casi:

1) stai sviluppando una Api

2) lo usi nel tuo codice per recuperare da un errore.

In qualsiasi altro scenario, le eccezioni incorporate dovrebbero essere sufficienti.

Nel tuo caso potresti usare InvalidArgumentException

    
risposta data 01.08.2015 - 01:14
fonte

Leggi altre domande sui tag