Должен ли я исключить сообщения об ошибках в операторах catch, перебрасывая ошибки? - PullRequest
0 голосов
/ 07 июня 2011

У меня ошибка / исключение, которое выбрасывается определенным методом.Каждый раз, когда возникает эта ошибка, я хочу зарегистрировать ее.Будет ли хорошей практикой регистрировать ошибку в исходном методе, а затем повторно выдавать ее?Таким образом, мне не нужно было бы регистрировать его в операторах catch любой функции, вызывающей этот метод.

Это выглядело бы примерно так:

public void doSomething() throws Exception{
    try{
        someFunction(); // throws Exception
    } catch (Exception e){
        logger.fatal(e.getMessage()); // always log this Excpetion
        throw e;            
    }
}

Моя проблема была в перебрасыванииточно такой же ошибки.Я не видел, чтобы это было сделано, и мне было интересно, если это будет считаться плохой практикой.

РЕДАКТИРОВАТЬ: Я должен добавить, что это исключение никогда не должно произойти.Это может помочь понять эту ситуацию.

Ответы [ 6 ]

1 голос
/ 07 июня 2011

Я бы регистрировал информацию, описывающую, почему ваш метод собирается генерировать исключение, а не само исключение.Позвольте клиентам решить, хотят ли они регистрировать исключение самостоятельно или обработать его.

1 голос
/ 07 июня 2011

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

Таким образом, моя рекомендация, если метод выдает исключение, позволить клиенту позаботитьсяобработки, даже если это чаще всего означает запись в журнал.(Если, конечно, вы не хотите, чтобы регистрация была задокументированным побочным эффектом метода.)

0 голосов
/ 07 июня 2011

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

Это как метод именования, с первого раза сложно разобраться, но меняйте его, пока не достигнете совершенства.

0 голосов
/ 07 июня 2011

Может быть, вы могли бы использовать аспектный подход. Таким образом, после каждого бизнес-метода вы проверяете тип исключения, которое было сгенерировано, и проверяете, соответствует ли он критериям исключения, которые должны быть зарегистрированы. Если это так, вы регистрируете его и выбрасываете исключение, иначе вы просто перебрасываете исключение без регистрации. Это позволяет централизовать регистрацию ошибок и отключать / включать ее при необходимости, помимо бизнес-логики - это типичная сквозная задача, а не основная проблема.

public class MyLoggerInterceptor ... {

   @AroundInvoke
   public Object invoke(InvocationContext ic){
     try{
         ic.proceed();
     }catch(Exception e){
         if(exceptionShouldBeLogged(e)){
            logger.fatal(e);
         }
         throw e;
     }
   }
}       
0 голосов
/ 07 июня 2011

Это действительно зависит от ваших предпочтений регистрации. Например, у вашего уровня доступа к базе данных может быть метод, который принимает SQL запрос в качестве String в качестве аргумента и выполняет его в БД. Теперь вы можете записать любой SQLException в этом слое, а затем обернуть SQLException пользовательским исключением [например, DatabaseException], а затем повторно выбросить его в родительский слой. Вы также можете инкапсулировать некоторые дополнительные действия, такие как boolean shouldRetry, в ваш DatabaseException объект, чтобы родительский уровень мог повторить операцию снова. Регистрация SQLException сразу же позволит вам легче отладить проблему позже.

EDIT:

Этот подход имеет больше смысла, когда ваш родительский слой выполняет операцию, которая может вызвать более одного вида исключений. Например, в приведенном выше сценарии метод, который принимает запрос SQL, может также выдать InvalidHostException, если менеджер базы данных недоступен, или ConnectionRefusedException, если менеджер базы данных отклонил соединение из-за перегрузки. В таком случае вы можете записать исключение, а затем обернуть его более общим DatabaseException. Также, если метод выдает ConnectionRefusedException, вы можете установить для переменной shouldRetry значение true; в то время как то же самое будет ложным для InvalidHostException. Это позволяет API вызывающей программы через некоторое время снова попытаться вызвать метод, если для shouldRetry установлено значение true.

ПРИМЕЧАНИЕ: кроме SQLException, все остальное - творение моего воображения. : -)

0 голосов
/ 07 июня 2011

Я бы регистрировал ошибку в исходном методе, только если там была соответствующая информация, которая не была бы доступна в клиентском коде.

...