Вопрос

Когда вы должны создать пользовательское исключение?

например ,У меня есть некоторый код, который подключается к серверу.Код, который подключается к серверу, выдает исключение IOException, когда ему не удается подключиться.В контексте метода, который он вызывается, это нормально.Это также прекрасно в сетевом коде.

Но поскольку это означает отсутствие соединения (и, следовательно, не работает), исключение распространяется вплоть до пользовательского интерфейса.На данном этапе исключение IOException очень неоднозначно.Что-то вроде NoConnectionException было бы лучше.

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

Это было полезно?

Решение

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

read -> ReadException
connect -> ConnectException
buildPortfolio -> FailedToBuildPortfolioException

и т.д.Это абстрагирует от того, что происходит под одеялом (т.е.вы подключаетесь через сокеты и т.д.).Как правило, когда я создаю интерфейс для компонента, я часто создаю соответствующее исключение или набор исключений.Мой интерфейс будет вызываться Component, и моими исключениями обычно являются ComponentException (например, RateSource и RateSourceException).Это согласованный и простой экспорт в различные проекты в виде полного набора компонентов.

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

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

Другие советы

Я знаю, что это помечено как "не зависящее от языка", но я не думаю, что это действительно так.Исходя из перспективы C ++, я ожидаю, что очень немногие базовые операции вызовут исключение - стандартная библиотека C ++ использует исключения только в очень немногих местах.Таким образом, мой собственный код часто является первым местом, где могут быть сгенерированы исключения.В этом коде мне нравится очень плоская иерархия - я не хочу возиться с сотнями предложений catch() позже в коде и никогда не понимал очевидной одержимости Java и C # созданием барочных иерархий классов и пространств имен.

Итак, для моего кода на C ++ - один тип исключения, содержащий значимое сообщение об ошибке, для каждой библиотеки.И один для окончательного исполняемого файла.

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

а) Я бы сказал:когда когда-либо исключение пересекает границу двух слоев в приложении, оно должно быть скрыто за исключением, которое более подходит для нового слоя.Пример:поскольку вы выполняете какие-то удаленные действия, вы получаете исключение ConnectionWhatEverException.

Но вызывающий абонент не должен знать о проблемах с подключением.Поскольку он просто хочет выполнить какую-то услугу, он получает исключение ServiceOutOfOrderException .Причиной этого является:Внутри слоя, выполняя удаленное взаимодействие, вы могли бы сделать что-то полезное с помощью ConnectionException (повторить попытку, записать в очередь возврата ..).Как только вы покинули этот слой, никто не знает, как обработать исключение ConnectionException .Но они должны иметь возможность решать, что делать, когда Сервис не работает.

б) Когда нет соответствующего существующего исключения.Например, в Java есть пара полезных исключений.Я довольно часто использую IllegalState и IllegalArgument.Сильным аргументом в пользу нового класса исключений является, если у вас есть какой-то полезный контекст для предоставления.Например, имя службы, которая завершилась с ошибкой, может быть аргументом ServiceFailedException .Просто не создавайте класс для каждого вызова метода или что-то в этом роде.100 Классов исключений не являются проблемой, если они имеют различное поведение (т.е.по крайней мере, в разных полях).Если они отличаются только именем и находятся на одном уровне абстракции, сделайте их одним исключением и поместите разные имена в сообщение или одно поле этого класса исключений.

c) По крайней мере, в java есть обсуждение проверяемых исключений.Я заворачиваю их непосредственно в непроверенный, потому что ненавижу проверенный вид.Но это скорее мнение, чем совет.

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

Когда вы должны создать пользовательское исключение?

Я.Когда вы сможете предоставить больше (диагностической) информации.

Примечание:эта дополнительная информация может быть недоступна в том месте, где было сгенерировано исходное исключение (IOException).Прогрессивные уровни абстракций могут содержать дополнительную информацию для добавления, например, что вы пытались сделать, что привело к этому исключению?

II.Когда вы не должны раскрывать детали реализации:т. е.вы хотите, чтобы (иллюзия?) абстракции продолжалась.

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

III.Как I , так и II

ПРИМЕЧАНИЕ:Кроме того, ваши клиенты должны быть в состоянии настроиться именно на тот уровень информации, который им интересен, или, скорее, они должны быть в состоянии отключить все, что им неинтересно.Так что это хорошая идея - вывести ваши пользовательские исключения из IOException.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top