2013-05-16 11 views
6

Ho un'interfacciaimplementazione dell'interfaccia lancia diverse eccezioni

public interface DataDAO { 
    public void doSomething() throws Exception; 
} 

Consente di dire che ci sono due implementazioni, uno che utilizza database per ottenere i dati e un altro che utilizza un webservice.

public class DataDAOJdbc implements DataDAO { 
    public void doSomething() throws Exception { 
     //Implement 
    } 
} 

public class DataDAOWebService implements DataDAO { 
    public void doSomething() throws Exception { 
     //Implement 
    } 
} 

Come si può già vedere, il problema è l'eccezione super generica lanciata. Poiché entrambe le implementazioni devono sollevare lo stesso tipo di eccezione.

L'implementazione Jdbc si limita a dire SQLException mentre l'implementazione Webservice aumenta solo IOException.

La domanda è: come posso rendere l'interfaccia più elegante, quindi acquisisco un'eccezione corretta?

La prima cosa che ho pensato è stato creare il mio eccezioni, e dichiaro sul livello di interfaccia

public interface DataDAO { 
    public void doSomething() throws MyCoolException; 
} 

E poi, naturalmente, implementare accordinly.

La domanda è, ha senso? Non ho mai creato le mie eccezioni, quindi non sono sicuro se questo ha molto senso o meno. Inoltre, che cosa dovrei prendere in considerazione quando creo MyCoolException?

+0

Che ne dici di trarre ispirazione da Spring e includerli in RuntimeExceptions. –

+0

@AjayGeorge bene, voglio che quelle eccezioni siano trattate dal livello superiore, quindi renderle RuntimExceptions non è valido per me, correggimi se ho torto :) –

+0

Bene potresti sottoclasse RuntimeExceptions e quindi creare un [DataAccessException] (http : //static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/dao/DataAccessException.html) come in primavera. –

risposta

4

La prima cosa che ho creato è stata la mia eccezione e la dichiariamo a livello di interfaccia (...) ha senso?

Sì, ha senso e credo che sia il modo migliore per gestire queste situazioni.

vi fornirò un esempio di calcio d'inizio per questo (sulla base il codice corrente):

public class MyCoolException extends Exception { 
    public MyCoolException() { 
    } 
    public MyCoolException(String message) { 
     this.message = message; 
    } 
} 

public interface DataDAO { 
    public void doSomething() throws MyCoolException; 
} 

public class DataDAOJdbc implements DataDAO { 
    public void doSomething() throws MyCoolException { 
     //Implement 
     try { 
     } catch (SQLException e) { 
      //handle the exception 
      logger.error("Error!", e); 
      //throw your custom exception 
      throw new MyCoolException(e.getMessage()); 
     } 
    } 
} 

public class DataDAOWebService implements DataDAO { 
    public void doSomething() throws MyCoolException { 
     //Implement 
     try { 
     } catch (IOException e) { 
      //handle the exception 
      logger.error("Error!", e); 
      //throw your custom exception 
      throw new MyCoolException(e.getMessage()); 
     } 
    } 
} 
+1

Hmm, questo è un nitpick, ma ti consiglio di inserire l'eccezione di causa (piuttosto che la sua stringa di messaggio) con 'MyCoolException', e in attesa di registrare l'intera storia quando viene utilizzato' MyCoolException'. –

+1

Sono assolutamente d'accordo con Paul, e oserei dire che è la cosa più importante da considerare quando scrivi la tua eccezione (* specialmente * se è intesa per avvolgere un'altra eccezione): senza la causa originale, perdi * molte * informazioni che potrebbero essere assolutamente vitali per il debug di eventuali problemi. –

+0

@PaulBellora Sono d'accordo con voi persone, ecco perché ho detto che questo è un esempio di base e registrare l'eccezione prima di rilanciare l'eccezione personalizzata. –

2

È possibile utilizzare un tipo generico per definire l'interfaccia gettato:

public interface DataDAO<E extends Throwable> { 
    public void doSomething() throws E; 
} 

Poi implementazioni sarebbe simile a questa:

public class DataDAOJdbc implements DataDAO<JDBCException> { 
    public void doSomething() throws JDBCException { 
     //Implement 
    } 
} 

public class DataDAOWebService implements DataDAO<WebServiceException> { 
    public void doSomething() throws WebServiceException { 
     //Implement 
    } 
} 

Tuttavia, questo ha lo svantaggio che non è più possibile maneggiare tutte le eccezioni allo stesso modo, a meno che non si prenda appena lo Exception (che praticamente annulla l'intero punto).

+2

Ma supponendo che l'OP volesse codificare per interfacciare, non per implementare, questo non aiuterebbe affatto a chiamare i siti. –

+0

@PaulBellora buon punto, hai un'idea migliore? –

+0

Questo approccio rompe il polimorfismo. Dovrebbe essere usata un'eccezione personalizzata. – Mikhail

1

fa questo senso?

Sì, lo fa. Dichiarando che doSomething genera un'eccezione controllata specifica, stai segnalando ai chiamanti del metodo che devono solo catturare e gestire quell'eccezione specifica. Dichiarando semplicemente throws Exception, i chiamanti sarebbero incoraggiati a catturare e gestire tutti gli Exception s, che includono anche eccezioni di runtime come NullPointerException.

Cosa dovrei prendere in considerazione durante la creazione di MyCoolException?

Potrebbe essere semplice come il seguente:

public final class MyCoolException extends Exception { 

    public MyCoolException(Throwable cause) { 
     super(cause); 
    } 
} 

Così il vostro eccezione personalizzata sarebbe semplicemente agire come un wrapper per l'eccezione causa, qualunque essa sia. Se possibile, puoi aggiungere un messaggio con informazioni aggiuntive che potrebbero essere utili per il debug. Quando viene rilevato il numero MyCoolException, è possibile scartarlo chiamando lo getCause() oppure trasferirlo in una chiamata a un framework di registrazione (lo stacktrace includerà l'eccezione di causa).

Problemi correlati