Поймать исключение высоко в стеке вызовов - при работе с n уровнями? - PullRequest
1 голос
/ 04 января 2011

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

try {

} finally {// очищает}

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

Ответы [ 4 ]

1 голос
/ 04 января 2011

Множество хороших отзывов, я покажу вам свое мнение.

Правило № 1.ТОЛЬКО ловить исключения, которые вы собираетесь обрабатывать.Под дескриптором я имею в виду дескриптор таким образом, что запрос клиента может продолжаться.Вы можете ловить вещи достаточно долго, чтобы регистрировать информацию (не злоупотребляйте этим, как правило, стека достаточно информации) или конвертировать в другую ошибку, которая распространяется легче (например, на основе среды выполнения).Но, если вы не можете справиться с этим, не беспокойтесь об этом.Это просто дополнительный код, который бесполезен и запутан.Даже когда вы входите в систему или конвертируете, вы в конечном итоге выбрасываете.

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

Правило № 2.Когда вы получаете исключение, которое вы не можете обработать, единственное, что вы можете сделать, это попытаться потерпеть неудачу таким образом, чтобы это было полезно для пользователя.Это означает, что зарегистрируйте его для последующего анализа (включая исходный стек / причину), а затем сообщите пользователю что-нибудь как можно более полезное.Очистите все, что нужно, чтобы система оставалась в согласованном состоянии.

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

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

0 голосов
/ 04 января 2011

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

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

0 голосов
/ 04 января 2011

Здесь есть три проблемы блокировки.

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

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

В-третьих, блок try / finally.Они полезны, когда исключение может привести к зависанию ресурсов в открытом или выделенном состоянии.Я всегда использую try / finally, чтобы очистить ресурсы, которые могут остаться открытыми (мой фаворит - Statement / ResultSet из java.sql, огромная проблема с памятью).Действительно хороший программист имеет в своем коде много такого, как способ изящного восстановления без огромных утечек памяти или ограничений ресурсов.

0 голосов
/ 04 января 2011

Я не думаю, что расслоение - это настолько чистая идея, что это нарушает ее.

Упаковка и повторная броска также не увеличивают ценность.

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

...