Progettazione di eccezioni per errori di conversione

5

Supponiamo che ci siano alcuni metodi per convertire da "X" a "Y" e viceversa; in alcuni casi la conversione potrebbe non riuscire e vengono utilizzate eccezioni per segnalare errori di conversione in questi casi.

Quale sarebbe l'opzione migliore per definire le classi di eccezioni in questo contesto?

  1. Una singola classe XYConversionException , con un attributo (ad es enum ) specificando la direzione della conversione (ad es. ConversionFromXToY , ConversionFromYToX ).
  2. Una classe XYConversionException , con due classi derivate ConversionFromXToYException e ConversionFromYToXException .
  3. ConversionFromXToYException e ConversionFromYToXException classi senza una comune classe base.
posta Mr.C64 31.10.2012 - 12:05
fonte

3 risposte

9

Il motivo principale per avere diversi tipi di eccezioni è di essere in grado di catturarli in modo selettivo.

Quindi la domanda che dovresti porci è: avrai mai un pezzo di codice in cui la conversione potrebbe fallire e vuoi solo catturare gli errori di conversione in una direzione e non nell'altra? Se è così, avere due classi di eccezione distinte è il modo migliore per andare. Se vuoi essere in grado di catturare entrambi nella stessa clausola, allora hai bisogno anche di una super classe comune.

Se hai difficoltà a prevedere in che modo vengono rilevate le eccezioni, passa a YAGNI e vai con la prima opzione. Puoi sempre aggiungere le sottoclassi in seguito se ne hai effettivamente bisogno.

A parte questo, penso che dovresti chiedersi se le eccezioni sono il modo giusto per segnalare un errore di conversione, perché in realtà l'errore è un'opzione prevista. Infatti molte API utilizzano semplicemente valori sentinella per questo.

Un altro bel modo per propagare gli errori sarebbe quello di avvolgere le informazioni di ritorno di ogni chiamata che può fallire in questo modo (in pseudo-codice):

 class Outcome<Result, Error> {
      const Bool success;
      const Result result;
      const Error error;
      Result sure() {
           if (success) return result;
           else throw error;
      }
 }

 Outcome<X, { value: Y, message: String }> convertYToX(Y y) {
     if (suitable(y)) return Outcome{ success: true, result: convert(y) };
     else return Outcome{ success: false, error: { }};
 }

E poi lo fai:

 handleX(convertXToY(myY).sure());//will throw an exception if an error occurred

Oppure controlla da solo il risultato:

 var o = convertXToY(myY);
 if (o.success)
     handleX(o.result);
 else {
     log('error occured during conversion:');
     log(o.error.message);
     log('using default');
     handleX(defaultX);
 }
    
risposta data 31.10.2012 - 12:43
fonte
1

Non pensarci troppo,

I miei suggerimenti:

Per quanto riguarda la firma del costruttore , in tutta l'API Java, le classi che estendono Exception utilizzano uno o più dei seguenti costruttori:

1. PrintException()  // Construct a print exception with no detail message.
2. PrintException(Exception e) // Construct a print exception chaining the supplied exception.
3. PrintException(String s) // Construct a print exception with the given detail message.
4. PrintException(String s, Exception e) // Construct a print exception with the given detail message and chained exception.

Penso davvero che uno o due di questi costruttori saranno sufficienti per te, probabilmente 1 e 3.

Per quanto riguarda la necessità o meno di eccezioni separate per X- > Y e Y- > X, consiglio vivamente di non farlo , perché finiscono per scrivere eccezioni per Z- > X, X- > Z, P- > Q, Q- > P, Q- > X, Q- > Y e molte permutazioni. Ti chiedi quale sia il valore aggiunto di questo.

    
risposta data 31.10.2012 - 13:35
fonte
0

Quale lingua? Molte lingue hanno già classi di eccezioni ben definite. Dovresti solo derivare da quelli e aggiungere i dettagli.

Per qualcosa di banale come questo, una sola ConversionException dovrebbe essere sufficiente, i dettagli possono andare in classe.

Come programmatore Ruby, prenderei in considerazione l'uso della classe di eccezioni predefinita e inserirò i dettagli nella parte del messaggio che fornisce in determinate circostanze.

    
risposta data 31.10.2012 - 12:18
fonte

Leggi altre domande sui tag