2013-05-16 16 views
6

Mam interfejsimplementacja interfejsu uruchamia różne wyjątki

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

Powiedzmy, że istnieją dwie implementacje, który korzysta z bazy danych, aby uzyskać dane i jeszcze jeden, który używa WebService.

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

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

Jak widać, problemem jest uruchamiany wyjątek super generyczny. Ponieważ obie implementacje wymagają podniesienia tego samego rodzaju wyjątku.

Implementacja Jdbc naprawdę tylko podnosi, powiedzmy, SQLException, podczas gdy implementacja Webservice tylko podnosi wyjątek IOException.

Pytanie brzmi, w jaki sposób mogę uczynić interfejs bardziej eleganckim, tak aby uchwycić właściwy wyjątek?

Pierwszą rzeczą, że chociaż było stworzenie własne wyjątek i zadeklarować go na poziomie interfejsu

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

A potem, oczywiście wdrożyć accordinly.

Pytanie brzmi, czy to ma sens? Nigdy nie stworzyłem własnych wyjątków, więc nie jestem pewien, czy ma to sens, czy nie. Co powinienem wziąć pod uwagę przy tworzeniu MyCoolException?

+0

Co powiesz na czerpanie inspiracji ze Springa i owijanie ich w RuntimeExceptions. –

+0

@AjayGeorge cóż, chcę, aby te wyjątki były traktowane przez górny poziom, więc czyniąc je RuntimExceptions nie jest prawidłowy dla mnie, popraw mnie, jeśli się mylę :) –

+0

Można również podklasy RuntimeExceptions, a następnie utworzyć [DataAccessException] (http : //static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/dao/DataAccessException.html) jak na wiosnę. –

Odpowiedz

4

Pierwszą rzeczą, która stworzyłem własny wyjątek i zadeklarować go na poziomie interfejsu (...) ma to sens?

Tak, to ma sens i uważam, że jest to najlepszy sposób na radzenie sobie w takich sytuacjach.

będę stanowić przykład KickOff na to (na podstawie aktualnego kodu):

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, to jest dziurkacz, ale poleciłbym zawijanie wyjątku przyczyny (zamiast jego łańcucha wiadomości) za pomocą 'MyCoolException' i czekanie na zalogowanie całej historii, kiedy' MyCoolException' jest traktowany. –

+1

Całkowicie zgadzam się z Paulem, a nawet posunąłbym się do stwierdzenia, że ​​jest to najważniejsza rzecz, którą należy wziąć pod uwagę podczas pisania własnego wyjątku (* szczególnie * jeśli ma to oznaczać inny wyjątek): bez pierwotnej przyczyny, przegrywasz * wiele * informacji, które mogą być absolutnie niezbędne przy debugowaniu jakichkolwiek problemów. –

+0

@PaulBellora Zgadzam się z Wami ludźmi, dlatego powiedziałem, że jest to podstawowy przykład i zarejestruj wyjątek przed ponownym wysłaniem niestandardowego wyjątku. –

2

Można używać typu rodzajowego do zdefiniowania interfejsu rzucone:

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

Zmodyfikowane Wdrożenia będzie wyglądać następująco:

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

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

to jednak ma tę wadę, że nie może już uchwyt wszystkie wyjątki w ten sam sposób, chyba że po prostu złapać Exception (co prawie neguje cały punkt).

+2

Ale zakładając, że OP chce kodować interfejs, a nie implementację, to w ogóle nie pomoże w wywołaniu stron. –

+0

@PaulBellora dobry punkt, masz lepszy pomysł? –

+0

To podejście przełamuje polimorfizm. Należy użyć niestandardowego wyjątku. – Mikhail

1

Czy to ma sens?

Tak, robi. Zgłaszając, że doSomething rzuca określony sprawdzony wyjątek, sygnalizujesz wywołującym metodę, że muszą tylko złapać i zająć się tym konkretnym wyjątkiem. Zgłaszając zwykły numer throws Exception, osoby dzwoniące będą zachęcane do przechwytywania i radzenia sobie ze wszystkimi Exception s, które zawierają nawet wyjątki czasu wykonywania, takie jak NullPointerException.

Co powinienem wziąć pod uwagę przy tworzeniu MyCoolException?

To może być tak proste, jak następuje:

public final class MyCoolException extends Exception { 

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

Więc zwyczaj wyjątek po prostu działać jako otoczka do wyjątku, niezależnie od przyczyny może być. Jeśli to możliwe, możesz dodać wiadomość z dodatkowymi informacjami, które mogą być pomocne przy debugowaniu. Po przechwyceniu MyCoolException można go rozwinąć, wywołując getCause() lub przekazać go do wywołania w ramce logowania (jego stacktrace będzie zawierać wyjątek przyczyny).

Powiązane problemy