Сведения о вопросе

Faridun

21:06, 1st October, 2020

Теги

c#   java   exception    

Пишете ли вы исключения для конкретных вопросов или общие исключения?

Просмотров: 396   Ответов: 11

У меня есть код, который дает идентификатор пользователя утилите, которая затем отправляет email этому пользователю.

emailUtil.sendEmail(userId, "foo");

public void sendEmail(String userId, String message) throws MailException {
    /* ... logic that could throw a MailException */
}

MailException может быть брошен по ряду причин, проблем с адресом email, проблем с шаблоном почты и т.д.

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

Edit: как уточнение, исключения не предназначены для журналов, а что-нет, это относится к тому, как код реагирует на них. Чтобы продолжить работу с примером mail, предположим, что когда мы отправляем почту, она может потерпеть неудачу, потому что у вас нет адреса email, или потому что у вас нет действительного адреса email, или она может потерпеть неудачу.. и т.д.

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

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



  Сведения об ответе

DAAA

21:06, 1st October, 2020

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

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

Поэтому, используя Ваш пример, если вы хотите запустить некоторую специальную логику, когда сервер email не настроен, вы можете добавить метод к объекту emailUtil, например:

public bool isEmailConfigured() ...

сначала вызовите это, вместо того, чтобы искать конкретное исключение.

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

Что касается иерархии исключений vs exceptions-with-error-codes-in-them, я обычно делаю последнее. Проще добавить новые исключения, если вам просто нужно определить новую константу ошибки вместо целого нового класса. Но, это не имеет большого значения, пока вы пытаетесь быть последовательным на протяжении всего вашего проекта.


  Сведения об ответе

lesha

22:21, 9th August, 2020

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

Примером из Java-API является IOException, который имеет подклассы, такие как FileNotFoundException или EOFException (и многое другое).

Таким образом, вы получаете преимущества обоих, у вас нет таких предложений, как throw:

throws SpecificException1, SpecificException2, SpecificException3 ...

генерал

throws GeneralException

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


  Сведения об ответе

LAST

02:21, 16th August, 2020

@Chris.Lively

Вы знаете, что можете передать сообщение в своем исключении или даже "status codes". Вы изобретаете колесо здесь.


  Сведения об ответе

lats

06:59, 26th August, 2020

Я обнаружил, что если вам нужно иметь CODE, решая, что делать на основе возвращенного исключения, создайте хорошо названное исключение, создающее подкласс общего базового типа. Переданное сообщение следует считать "human eyes only" и слишком хрупким для принятия решений. Пусть компилятор делает свою работу!

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


  Сведения об ответе

VERSUION

18:24, 17th August, 2020

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

  • Приложение имеет высокую доступность
  • Отправка электронной почты особенно важна
  • Объем приложения невелик и отправка электронной почты является большой его частью
  • Приложение будет развернуто на удаленном сайте, и вы получите только журналы для отладки
  • Вы можете восстановить некоторые подмножества исключений, инкапсулированных в mailException, но не другие

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


  Сведения об ответе

repe

15:46, 1st August, 2020

Вместо использования исключений я обычно возвращаю список объектов состояния из методов, которые могут иметь проблемы с выполнением. Объекты состояния содержат перечисление серьезности (информация, предупреждение, ошибка, ...) имя объекта состояния типа "Email Address" и читаемое пользователем сообщение типа "Badly formatted Email Address"

Затем вызывающий код решит, какой фильтр следует фильтровать до UI, а какой обрабатывать самостоятельно.

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

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

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

UPDATE: объединение ответов

@Jonathan: моя точка зрения заключалась в том, что я могу оценить действие, в данном случае отправив email, и отправить обратно несколько причин сбоя. Например, "плохой адрес email", "пустой заголовок сообщения" и т. д..

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

Изобретение колеса.. возможно. Однако большинство приложений должны анализировать всю транзакцию, чтобы предоставить пользователю максимально возможную информацию. Представьте, что ваш компилятор остановился при первой ошибке. Затем вы исправляете ошибку и снова нажимаете компиляцию, чтобы она снова остановилась для другой ошибки. Какая боль в заднице. Для меня это именно проблема с выбрасыванием исключений и, следовательно, причина, по которой я сказал использовать другой механизм.


  Сведения об ответе

fo_I_K

16:27, 24th August, 2020

Я думаю, что сочетание вышеперечисленного даст вам лучший результат.

Вы можете создавать различные исключения в зависимости от проблемы. например, отсутствует email адрес = ArgumentException.

Но затем в слое UI вы можете проверить тип исключения и, если нужно, сообщение, а затем отобразить соответствующее сообщение пользователю. Я лично склонен показывать пользователю только информационное сообщение, если возникает определенный тип исключения (UserException в моем приложении). Конечно, вы должны очистить и проверить пользовательский ввод как можно дальше вверх по стеку, чтобы убедиться, что любые исключения генерируются действительно маловероятными сценариями, а не в качестве фильтра для искаженных писем, которые можно легко проверить с помощью regex.

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


  Сведения об ответе

lourence

05:00, 4th August, 2020

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

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


  Сведения об ответе

SILA

21:00, 22nd August, 2020

Хотя вы можете различать выполнение кода, исключение не имеет значения, выполняется ли оно с помощью "catch exceptionType hierarchy mode" или "if(...) else...exception кодовый режим"

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

Когда я использую библиотеку и их методы просто запускаю 'Exception', я всегда задаюсь вопросом: Что может вызвать это исключение?, как должна реагировать моя программа?, если есть javadoc, возможно, причина будет объяснена, но mustly раз нет javadoc или исключение не объясняется. Слишком много накладных расходов можно избежать с помощью WellChossenExceptionTypeName


  Сведения об ответе

DINO

07:58, 14th August, 2020

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


  Сведения об ответе

PIRLO

21:06, 1st October, 2020

Я бы просто прошел мимо

throw new exception("WhatCausedIt")

если вы хотите обрабатывать свои исключения, вы можете передать код вместо "WhatCausedIt", а затем реагировать на разные ответы с помощью оператора switch.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться