2011-11-11 16 views
7

Quando si introducono nuovi tipi di eccezioni, sono sempre un ma incerto su come farlo correttamente. C'è una convenzione comune? Come si fa?Come denominate e organizzate le vostre eccezioni?

Sono interessato l'ambito si organizzarli (Tenerli nell'unità vengono utilizzati in? Avere un'unità a livello di componente? Livello di pacchetto? Applicazione?)

questo influenza anche la denominazione. Quanto contesto includi? È meglio renderli molto specifici (come EPersonIDNotFoundError) o provare a renderli riutilizzabili (come ENotFoundError)?

E il suffisso "Errore" - quando devo aggiungerlo e quando lo si lascia? Non riesco a vedere la logica, ad es. in Classes.pas:

EWriteError = class(EFilerError); 
    EClassNotFound = class(EFilerError); 
    EResNotFound = class(Exception); 
+0

Penso che sia opportuno organizzare eccezioni per gravità e per pacchetto. Per gravità es. eccezioni di convalida separate dagli errori di caricamento/salvataggio dei dati. L'istanza dell'eccezione può contenere dettagli più specifici sull'occasione in cui si è verificata. – too

+1

Questa non è una domanda ... Troppe domande contemporaneamente, con qualche potenziale dibattito (trolling?). IMHO questo non si adatta bene allo scopo SO. –

+0

@Arnaud Bene, fammi provare a rispondere a questo. Perché apprezzo molto l'input. –

risposta

6

L'unica vera convention io sappia, è quello di anteporre loro con E. Non ci ho pensato molto in passato, ma ora ci penso, mi sembra che sia Error sia Exception siano comunemente usati come postfix. Se li mescoli, direi che Exception si riferisce a qualcosa che va storto inaspettatamente, come una connessione che è rotta, o un file che risulta illeggibile, mentre un errore si riferisce più a un input sbagliato, ad esempio un numero è stato previsto, ma qualcuno ha digitato il testo.

La VCL sembra seguire alcune convenzioni troppo, ma sembra di aggiungere un suffisso solo se non sarebbe chiaramente ed errori senza di essa, per esempio

EConvertError, EMathError, EVariantError

vs

EAccessViolation, EInvalidPointer, EZeroDivide

quest'ultimo descrivere l'errore stesso, dove il primo elenco bisogno il suffisso per indicare un errore in un determinato processo o entità.

Questi esempi si trovano in SysUtils, forse si può dare un'occhiata lì, perché contiene molte classi di eccezioni e classi di base per una quantità ancora più grande di eccezione. Pochissimi di questi finiscono in Exception, fatta eccezione per alcuni errori molto specifici che speri di non incontrare mai, come EHeapException e ESafecallException.

+0

Buon punto per saltare "Errore" quando il messaggio di errore stesso trasporta abbastanza bene la condizione di errore. Mescoli "Eccezione" e "Errore"? –

+1

Uso raramente "Errore", sebbene possa darsi da ora in poi, poiché questa domanda mi ha fatto riflettere. Ma di solito non introduco molti tipi di eccezioni. Tendo a creare poche eccezioni di livello applicativo di base e utilizzo (ri) molte eccezioni esistenti. Se non riesco a convertire qualche valore, sono felice di utilizzare EConvertError per questo, e la mia implementazione list/array/collection può facilmente riutilizzare EListIndexError di qualunque cosa venga chiamata. Non sto certamente creando eccezioni separate per ogni campo che non è stato trovato. – GolezTrol

1

Durante la creazione di una nuova eccezione, la rendono estesa all'applicazione. Comincio dall'errore più dettagliato alla classe più generale, ad esempio (Eccezione) e li chiamo di conseguenza.

Quindi, nel tuo esempio, utilizzerei EPersonIDNotFoundError, ENotFoundError, Exception.

in realtà dipende la quantità di dettagli che si desidera dai messaggi di errore e di ciò che si include nel log (se si mantiene un registro degli errori)

1

Normalmente per le applicazioni più semplici si può ottenere via con Exception.Create ('Messaggio di errore'). Dove le eccezioni diventano potenti è in grado di rilevare il tipo di risposta richiesta guardando alla classe. Delphi lo fa già con la procedura Abort, che solleva EAbort. EAbort è 'speciale' in quanto non innesca un 'errore' in quanto tale, cioè è un tipo di eccezione 'silenziosa'. È possibile utilizzare questa azione specifica della classe per esaminare un'eccezione e fare cose diverse. È possibile creare un errore EMyWarning, EMyVeryNastyError, ognuno dei quali discende dal tipo di eccezione di base.

Inoltre, è possibile definire una nuova classe di eccezioni per trasportare più informazioni nel punto in cui l'eccezione è intrappolata. Per esempio con il codice (non controllato):

EMyException = class(Exception) 
    constructor Create(const AErrorMessage : string; AErrorCode : integer); reintroduce; 
PUBLIC 
    ErrorCode : integer 
end; 

constructor EMyException.Create(const AErrorMessage : string; AErrorCode : integer); 
begin 
    inherited Create(AErrorMessage); 
    ErrorCode := AErrorCode; 
end; 

ora avete la possibilità di impostare 'CodiceErrore' quando si alza l'eccezione e si ha a disposizione quando l'eccezione e 'colto. Le eccezioni sono piuttosto potenti.

+0

Non proprio una risposta alla domanda, ma una buona dimostrazione del perché ereditare da Exception in primo luogo. E adoro EAbort. :) Puoi abortire così tante cose. Ad esempio, interrompi la pubblicazione di un record aumentando un EAbort in OnBeforePost e molte di tali interruzioni. Lo uso anche molto per abortire operazioni complesse. – GolezTrol

1

In che ambito organizzarli?

Utilizzare un'unità per l'intera applicazione in cui si tenta di adattarsi alle eccezioni più generali. Tutto il resto va nell'unità in cui viene lanciata l'eccezione. Se hai bisogno di queste eccezioni in altre unità, spostale su un'unità comune utilizzata dal sottosistema su cui stai lavorando.

Come nominare?

Provare a creare uno o due livelli di eccezioni "generali" come ENotFoundError. Metti questi nel file globale dell'applicazione. Non sforzarti troppo per generalizzare perché non puoi sapere quale eccezione verrà dopo, richiedendo di cambiare tutto. Crea eccezioni specializzate a livello di unità ereditandole da quelle globali.

E il suffisso "Errore"?

Smettila di pensarci. Add it. A meno che non suoni stupido.

+2

Nel caso in cui il codice utilizzi molto le interfacce, vorrei dichiarare le eccezioni nell'unità che dichiara le interfacce, non nel codice di implementazione che le lancia in modo assoluto. – mjn

+1

@mjn. In caso contrario, gli utenti dell'interfaccia non possono eseguire controlli specifici rispetto alle classi di eccezioni senza ottenere una dipendenza dagli implementatori ... –

Problemi correlati