Raccomandare un modello / approccio di progettazione per esporre / tollerare / recuperare da errori di sistema, gestione delle eccezioni (ad es. In Java, C ++, Perl, PHP)


13

Puoi consigliare un modello / approccio di progettazione per esporre / tollerare / ripristinare da errori di sistema, gestione delle eccezioni (Java, C ++, Perl, PHP)?

Alcuni errori devono essere segnalati.

Alcuni errori possono essere gestiti internamente (da un nuovo tentativo o sono insignificanti (possono essere ignorati).

Come strutturi il codice per catturarli?

Ma tutti gli errori devono essere registrati.

Quali sono le migliori pratiche?

E per simularli per essere in grado di testare completamente i componenti che ne sono interessati?

Domanda generale specifica per un linguaggio non di programmazione applicabile a diversi linguaggi di programmazione moderni, ma darebbe il benvenuto ad esempi di modelli, approcci e filosofie in Java, C ++, PHP e Perl.

(Richiesto anche in StackOverflow: /programming/7432596/recommend-a-design-pattern-approach-to-exposing-tolerating-recovering-from-system ma ho pensato che dovrebbe essere chiesto anche ai programmatori perché Penso che le domande e risposte dei programmatori coprano più ampi problemi software / di programmazione, mentre lo stackoverflow riguarda maggiormente l'implementazione tecnica IMHO).


2
A me la tua domanda sembra troppo generica e aperta per avere una risposta efficace. Prova a limitarlo ad alcuni casi più specifici e anche a tipi / ambienti specifici dell'applicazione (ad es. App / server GUI / ...).
Péter Török,


@Péter Török, mikera fornisce una buona risposta, che probabilmente accetterà la loro.
therobyouknow,

Risposte:


16

Fail fast è un ottimo approccio progettuale e forse può essere contato come modello: http://en.wikipedia.org/wiki/Fail-fast

Ho anche trovato utili alcuni principi:

  • Considera le eccezioni come parte dell'interfaccia per ogni funzione / modulo , ovvero documentale e, se del caso, se la tua lingua lo supporta, usa le eccezioni selezionate.
  • Non confondere mai un fallimento - se fallito, non provare a continuare con qualche tentativo di "supporre" come procedere. Ad esempio, la gestione speciale per casi nulli è spesso un odore del codice per me: se il tuo metodo ha bisogno di un valore non nullo, dovrebbe generare immediatamente un'eccezione se incontra un valore nullo (NullPointerException o idealmente un IllegalArgumentException più descrittivo).
  • Scrivi test unitari sia per casi eccezionali che normali - a volte tali test possono essere difficili da configurare ma ne vale la pena quando vuoi essere sicuro che il tuo sistema sia robusto per guasti
  • Accedere al punto in cui l'errore è stato rilevato e gestito (presupponendo che l'errore fosse di gravità sufficiente per essere registrato). La ragione di ciò è che implica la comprensione della causa e un approccio per gestire l'errore, in modo da poter rendere significativo il messaggio di registro .....
  • Utilizzare le eccezioni solo per condizioni / guasti veramente imprevisti. Se la tua funzione "fallisce" nel modo effettivamente previsto (ad es. Il polling per vedere se sono disponibili più input e non ne trova nessuno), dovrebbe restituire una risposta normale ("nessun input disponibile"), non generare un'eccezione
  • Fallisci con garbo (merito a Steven Lowe!) - pulisci prima di terminare, se possibile, in genere annullando le modifiche, annullando la transazione o liberando risorse in una dichiarazione "finalmente" o equivalente. La pulizia dovrebbe idealmente avvenire allo stesso livello in cui le risorse sono state impegnate per motivi di chiarezza e coerenza logica.
  • Se devi fallire, fallisci ad alta voce - un'eccezione che nessuna parte del tuo codice è stata in grado di gestire (cioè percolata al livello superiore senza essere catturata + gestita) dovrebbe causare un errore immediato, forte e visibile che dirige la tua attenzione su di esso. In genere, interrompo il programma o l'attività e scrivo un rapporto di eccezione completo su System.out.

1
anche fallire con garbo - ripulire prima di terminare se possibile
Steven A. Lowe,

+1 @mikera per punti chiari su cosa considerare. Probabilmente accettata risposta, lascerò aperto ancora un po 'per consentire agli altri di contribuire.
therobyouknow,

+1 @Steve A. Lowe - per un design centrato sull'utente. ad es. come salvare i file, non lasciare in giro i file temporanei. Vedi la mia domanda su "igiene dei dati" come argomento correlato nel mio elenco di domande.
therobyouknow,

5

Avendo lavorato con le eccezioni in Java e .NET E dopo aver letto molti articoli su come / quando / perché catturare le eccezioni, ho finalmente escogitato i seguenti passaggi che mi vengono in mente ogni volta che vedo accadere una potenziale eccezione, o un eccezione devo catturare (Java) ... anche se non succede mai (sospiro ...). E sembra funzionare, almeno per me:

  1. C'è qualcosa di utile che posso fare con quell'eccezione (tranne la registrazione)? Se la risposta è sì, scrivi il codice di soluzione alternativa e se la soluzione alternativa può generare eccezioni, vai a 2:
  2. Avvolgi l'eccezione attorno a un'eccezione di runtime, lanciala, vai a 3.
  3. Nella classe di livello superiore in cui è stata avviata una possibile transazione di database / processo, intercettare l'eccezione, ripristinare la transazione, ripetere l'eccezione.
  4. Nella classe di livello superiore (che potrebbe essere quella in cui è stata avviata la transazione), registra l'eccezione utilizzando un framework di registrazione come slf4j (accoppiato ad esempio con log4j ) o log4net . Se possibile, inviare un'e-mail direttamente all'eccezione a una lista di distribuzione composta da sviluppatori dell'applicazione.
  5. Se è presente una GUI, visualizzare un messaggio di errore che indica nel modo più intuitivo che cosa ha causato il problema; non visualizza l'eccezione / stacktrace, l'utente non si preoccupa e non ha bisogno di sapere che era una NullPointerException.

Dovrei anche aggiungere il passaggio 0 , in cui lancio di proposito quella che chiamo un'eccezione "aziendale" (una nuova eccezione che creo estendendo la classe "Eccezione") quando un trattamento complesso non può essere eseguito a causa di errori di dati, MA che sono noti per accadere poiché sono stati identificati come casi di eccezione durante l'analisi.

Fatta eccezione per la parte di registrazione, sono pienamente d'accordo con i punti scritti da "Mikera"; Aggiungerò solo che l'eccezione dovrebbe essere registrata una sola volta .

Inoltre, i passaggi che ho elencato potrebbero essere diversi se quello che stai scrivendo è un'API / Framework . Lì, lanciare eccezioni ben progettate è obbligatorio per aiutare gli sviluppatori a capire i loro errori.

Per quanto riguarda il test delle eccezioni, usando oggetti finti dovresti essere in grado di testare quasi tutto, sia esso eccezionalmente o meno, a condizione che le tue classi rispettino la best practice "una classe per fare una cosa". Personalmente mi assicuro di contrassegnare i metodi più importanti ma nascosti come "protetti" anziché "privati" in modo da poterli testare senza troppi problemi. A parte questo, testare le eccezioni è semplice, basta provocare l'eccezione e "aspettarsi" che si verifichi un'eccezione catturandola. Se non si ottiene un'eccezione, si verifica un errore del case test unitario.


+1 @Jalayn per la menzione di log4j come approccio, questo è quello che uso, quindi lo rinforza per sapere che lo è anche qualcun altro.
therobyouknow,

0

Costruisci i tuoi oggetti nel modo giusto, non preoccuparti di fattori esterni. Se scegli di sfruttare le eccezioni, fai in modo che i tuoi oggetti generino eccezioni se falliscono in qualcosa.

Una volta che tutti i tuoi oggetti funzionano correttamente, dovrebbe essere abbastanza facile trovare una gerarchia di responsabilità per la gestione degli errori nella progettazione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.