обернутое исключение из компонента - PullRequest
0 голосов
/ 16 октября 2008

Существует такой стиль системы исключений, когда компонент генерирует исключение, специфичное для компонента. Например, все классы доступа к данным выбрасывают DataAccessException.

В этом стиле мне часто приходится ловить и перебрасывать исключение, специфичное для компонента, потому что вызываемые методы обнуляются как throws Exception:

try {
    int foo = foo();
    if (foo != expectedValue) {
        throw new ComponentException("bad result from foo(): " + foo);
    }
    bar();
}
catch (ComponentException e) { 
    throw e; 
}
catch (Exception e) { 
    throw new ComponentException(e); 
}

Вы делаете то же самое? Вы находите это уродливым?

Этот вопрос не о валидности этого стиля, а о его пределах.

Ответы [ 2 ]

3 голосов
/ 16 октября 2008

Это ужасно ужасно. Думаю, больше нечего комментировать в этом уродливом стиле. Если у вас уже есть весь код для решения различных проблем с использованием причины, это сработает. Просто с помощью

try {
  componentCall();
} catch (ComponentException e) {
  Throwable t = e.getCause();
  //Handle each possible cause
}

менее удобен в обслуживании и более запутан, чем другие способы, и главное, что я не вижу преимуществ в его использовании.

Учитывая, что вы ограничены в его использовании, я бы по крайней мере старался не создавать исключение ComponentException как с причиной, так и без нее, что делает его более запутанным, чем нужно, в вашем примере я бы добавил исключение InvalidFooException и добавьте его в качестве причины для общего исключения ComponentException.

try {
    int foo = foo();
    if (foo != expectedValue) {
        throw new InvalidFooException("bad result from foo(): " + foo);
    }
    bar();
}
catch (Exception e) { 
    throw new ComponentException(e); 
}

getCause () предназначен для цепочек исключений , которые только причинно, а не семантически связаны.

Если вам нужно, чтобы они различали разные исключения (например, исключение SQLExecutionException должно быть исправлено действием, отличным от AccessDeniedException), тогда ваш метод неприменим (потому что принудительное использование getCause () в каждом улове, чтобы увидеть, что нужно сделать, это ужасно и не приносит никакой пользы, кроме как ловить правильное исключение).

Если все, что нужно сделать вызывающим классам, это сообщить об ошибке и отменить, тогда перенос может быть в порядке, но я бы не стал этого делать, так как это добавляет мало пользы, и если позже вам понадобится разграничить, вы будете переписывать много вещей.

Что полезно, так это создать иерархию исключений для исключений того же типа в строках:

Если DataAccessException будет корневым, то вы можете, например, иметь DataSourceUnavailableException, InvalidDataSourceException, InvalidDataException, а затем вы можете решить перехватить только одного из родителей (если действие одинаковое) или перехватить каждое исключение отдельно.

Зачем вам, кстати, так себя вести?

0 голосов
/ 16 октября 2008

Возможно, это будет менее уродливо (если объявлена ​​функция foo (), выдающая исключение):

int foo;
try {
    foo = foo();
}
catch (Exception e) { 
    throw new ComponentException(e); 
}
if (foo != expectedValue) {
    throw new ComponentException("bad result from foo(): " + foo);
}
bar();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...