Почему "log and throw" считается анти-шаблоном? [закрытый]


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

почему регистрация вашего исключения, а затем его повторное создание (сохранение исходной трассировки стека, конечно) - плохая идея, если вы не можете справиться с этим иначе?

4 55

4 ответа:

Я предполагаю, что ответ во многом потому, что почему вы ловите его, если вы не можете справиться с этим? Почему бы не позволить тому, кто может справиться с этим (или у кого нет другого выбора, кроме как справиться с этим), записать его, если они чувствуют, что он достоин журнала?

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

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

Log-and-throw-хороший шаблон, если сущность ловит и перестраивает исключение, имеет основания полагать, что она содержит информацию, которая не будет регистрироваться дальше в стеке вызовов-по крайней мере, не самым желательным образом. Это может произойти по нескольким причинам:

  1. исключение может быть перехвачено и повторно создано на границе уровня приложения и может содержать привилегированную информацию. Было бы плохо для уровня базы данных разрешить исключение, например: "Попытайтесь добавить дубликат ключа "fnord" в поле "пользователи", чтобы достичь внешнего уровня приложения (который, в свою очередь, может предоставить его пользователю), но для внутренних частей базы данных может быть полезно создать такое исключение и интерфейс приложения, чтобы поймать его, безопасно зарегистрировать его и повторно создать несколько менее описательное исключение.
  2. исключение может быть тем, что внешний слой, вероятно, будет ожидать обработки без регистрации, но внутренний слой может знать что-то, что внешний слой не предполагает, что ведение журнала может быть полезно. В качестве грубого примера, средний уровень приложения может быть запрограммирован на попытку подключения к одному серверу, а если это не сработает, попробуйте другой. Заполнение журнала приложения сообщениями "ошибка подключения", когда сервер не работает для обслуживания, может быть бесполезным, тем более что-с точки зрения приложения, все работало нормально. Может быть полезно переслать информацию о сбое соединения в журнал ресурс, связанный с серверами, который затем может фильтровать журналы, чтобы создать отчет о том, когда сервер пошел вверх и вниз, в отличие от журнала каждой попытки подключения.

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

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

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

IMO log and throw-это явное нарушение принципа наименьшего удивления.

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