Это все еще антипаттерн, если мы регистрируем сообщение об исключении и генерируем другое исключение?

18

Наше веб-приложение использует ExceptionMapperдля сопоставления некоторых исключений Response. Мы регистрируем сообщения об исключениях перед тем, как выдавать новое исключение следующим образом:

catch (SomeException ex) {
  LOG.error(ex.getMessage());
  throw new MyException(ex.getMessage());
}

Мы не выкидываем одно и то же исключение , поэтому мой вопрос, будет ли это рассматриваться как антипаттерн Log and Throw . И, таким образом, было бы лучше удалить записи в аналогичных местах и ​​переместить их в несколько ExceptionMapperклассов следующим образом:

@Provider
public class MyExceptionMapper implements ExceptionMapper<MyException> {

  // bla bla 

  @Override
  public Response toResponse(final MyException ex) {
    LOG.error(ex.getMessage());
    return Response.status(400).entity("something").build();
  }
}
Диярбакыр
источник
3
Я остановлю тебя, как только ты войдешь ex.getMessage(), это уже неправильно.
Бизиклоп
ИМО не совсем справедливо вообще не упоминать, что это веб-сервис. Это действительно меняет правила игры, потому что, например, обычное использование исключений может быть угрозой безопасности; Вы не хотите, чтобы все и все исключения отправлялись обратно в ответе об ошибке 500, который необходимо проверить и отфильтровать. Агрессивная регистрация на месте также гораздо чаще встречается при работе с системами, у которых внешние клиенты напрямую ее вызывают. Ведение журналов стековых трасс в сервисных вызовах, которые вызываются неоднократно, может привести к неуправляемым размерам файлов журнала и проблемам с производительностью.
@ Gimby В этом случае OP не отправляет подробности об ошибке в ответе (возможно, содержание "ошибка произошла"). Кроме того, как вы диагностируете проблему без трассировки стека? Вращающиеся регистраторы обычно заботятся о размере хранилища, а данные журнала смущающе сжимаются.
Марко Топольник

Ответы:

36

Ваш код на самом деле содержит не один, а три антипаттерна:

  1. войти и отбросить;
  2. свергнуть, не оборачивая первоначальную причину;
  3. регистрировать только сообщение, а не трассировку стека (это худшее).

Если вы следовали передовой практике, чтобы:

  1. вообще не поймать (пусть исключение распространяется самостоятельно);
  2. если вам нужно поймать проверенное исключение, поместите его в unchecked и снова выбросьте;
  3. никогда не регистрируйте ничего, кроме как на верхнем уровне;
  4. протоколировать всю трассировку стека исключений log.error("Error occurred", e);

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

Марко Топольник
источник