Когда бросать исключение?
У меня есть исключения, созданные для каждого условия, которое мое приложение не ожидает. UserNameNotValidException
, PasswordNotCorrectException
и т.д.
Однако мне сказали, что я не должен создавать исключения для этих условий. В моем UML эти исключения ARE для основного потока, так почему это не должно быть исключением?
Любые рекомендации или рекомендации по созданию исключений?
Ответы
Ответ 1
Мое личное правило: исключение возникает, когда фундаментальное предположение о текущем кодовом блоке оказывается ложным.
Пример 1: скажем, у меня есть функция, которая должна проверять произвольный класс и возвращать значение true, если этот класс наследуется от List < > . Эта функция задает вопрос: "Является ли этот объект потомком списка?" Эта функция никогда не должна генерировать исключение, поскольку в ее работе нет серых областей - каждый отдельный класс либо выполняет, либо не наследует от List < > , поэтому ответ всегда "да" или "нет".
Пример 2: скажем, у меня есть другая функция, которая проверяет List < > и возвращает true, если ее длина больше 50, а false, если длина меньше. Эта функция задает вопрос: "Имеет ли этот список более 50 элементов?" Но этот вопрос делает предположение - он предполагает, что заданный им объект является списком. Если я передам ему NULL, то это предположение неверно. В этом случае, если функция возвращает либо true или false, то она нарушает свои собственные правила. Функция не может вернуть ничего и утверждать, что она правильно ответила на вопрос. Поэтому он не возвращается - он выдает исключение.
Это сопоставимо с "загруженным вопросом" логической ошибкой. Каждая функция задает вопрос. Если введенный ввод делает этот вопрос ошибочным, то генерирует исключение. Эта строка сложнее рисовать с функциями, возвращающими void, но нижняя строка: если функция допущений о ее входах нарушена, она должна генерировать исключение вместо обычного возврата.
Другая сторона этого уравнения: если вы часто обнаруживаете, что ваши функции часто выбрасывают исключения, вам, вероятно, необходимо уточнить свои предположения.
Ответ 2
Потому что это вещи, которые обычно происходят. Исключения не являются механизмами управления потоком. Пользователи часто получают пароли неправильно, это не исключительный случай. Исключения должны быть по-настоящему редкой ситуацией типа UserHasDiedAtKeyboard
.
Ответ 3
Мои маленькие рекомендации сильно зависят от большой книги "Code complete":
- Используйте исключения, чтобы уведомлять о вещах, которые нельзя игнорировать.
- Не используйте исключения, если ошибка может быть обработана локально
- Убедитесь, что исключения находятся на том же уровне абстракции, что и остальная часть вашей процедуры.
- Исключения должны быть зарезервированы для того, что действительно исключительное.
Ответ 4
Это НЕ исключение, если имя пользователя недействительно или пароль неверен. Это то, что вы должны ожидать в нормальном режиме работы. Исключения - это вещи, которые не являются частью нормальной работы программы и довольно редки.
EDIT: Мне не нравятся исключения, потому что вы не можете определить, генерирует ли метод исключение, просто просматривая вызов. Вот почему исключения следует использовать только в том случае, если вы не можете справиться с ситуацией достойным образом (подумайте "из памяти" или "компьютер горит" ).
Ответ 5
Одно эмпирическое правило - использовать исключения в случае чего-то, чего вы обычно не могли предсказать. Примерами являются подключение к базе данных, отсутствие файла на диске и т.д. В сценариях, которые вы можете предсказать, то есть пользователи, пытающиеся войти в систему с неправильным паролем, вы должны использовать функции, которые возвращают логические значения и умеют корректно обрабатывать ситуацию. Вы не хотите резко прекратить выполнение, выбросив исключение только потому, что кто-то ошибся в пароле.
Ответ 6
Другие предполагают, что исключения не должны использоваться, потому что плохой логин следует ожидать в обычном потоке, если пользователь ошибается. Я не согласен, и я не могу рассуждать. Сравните это с открытием файла.. если файл не существует или недоступен по какой-либо причине, исключение будет выведено фреймворком. Использование логики выше было ошибкой Microsoft. Они должны были вернуть код ошибки. То же самое для парсинга, веб-запросов и т.д. И т.д.
Я не считаю плохую часть входа в обычный поток, это исключительный. Обычно пользователь вводит правильный пароль, и файл существует. Исключительные случаи являются исключительными, и отлично использовать исключения для них. Усложнение кода путем распространения возвращаемых значений через n уровней вверх по стеку - это пустая трата энергии и приведет к запутанному коду. Сделайте простейшую вещь, которая могла бы работать. Не досрочно оптимизируйте с помощью кодов ошибок, исключительные вещи по определению редко случаются, а исключения не стоят ничего, если вы не выбросите их.
Ответ 7
Исключения являются несколько дорогостоящим эффектом, если, например, у вас есть пользователь, который предоставляет неверный пароль, обычно лучше передать флаг сбоя или какой-либо другой индикатор, что он недействителен.
Это связано с тем, как обрабатываются исключения, истинный неверный ввод и уникальные элементы критической остановки должны быть исключениями, но не сбойными данными входа.
Ответ 8
Я думаю, вы должны просто выбросить исключение, если вы ничего не сможете сделать, чтобы выбраться из своего текущего состояния. Например, если вы выделяете память и ее не выделяете. В случаях, о которых вы упоминаете, вы можете четко оправиться от этих состояний и, соответственно, вернуть код ошибки обратно своему вызывающему.
Вы увидите много советов, в том числе в ответах на этот вопрос, что вы должны исключать исключения только в "исключительных" обстоятельствах. Это кажется поверхностно разумным, но является ошибочным советом, потому что он заменяет один вопрос ("когда я должен делать исключение") с другим субъективным вопросом ("что является исключительным"). Вместо этого следуйте советам Herb Sutter (для C++, доступным в статье доктора Доббса "Когда и как использовать исключения", а также в его книге с Андреем Александреску C++ "Стандарты кодирования"): выведите исключение, если и только если
- предварительное условие не выполняется (что обычно делает невозможным одно из следующих) или
- альтернатива не соответствовала бы постобработкам или
- альтернатива не сможет поддерживать инвариант.
Почему это лучше? Разве это не заменяет вопрос несколькими вопросами о предпосылках, постусловиях и инвариантах? Это лучше по нескольким причинам.
- Предпосылки, постусловия и инварианты - это проектные характеристики нашей программы (ее внутренний API), тогда как решение
throw
- это деталь реализации. Это заставляет нас помнить, что мы должны рассматривать дизайн и его реализацию отдельно, а наша работа при внедрении метода заключается в создании чего-то, что удовлетворяет дизайнерским ограничениям. - Это заставляет нас думать в терминах предварительных условий, постусловий и инвариантов, которые являются единственными предположениями, которые вызывающие нашего метода должны делать и точно выражены, что позволяет свободно связываться между компонентами нашей программы.
- Тогда эта свободная связь позволяет нам реорганизовать реализацию, если это необходимо.
- Послесловия и инварианты проверяются; это приводит к тому, что код может быть легко протестирован модулем, потому что пост-условия являются предикатами, которые может проверять наш блок-тест (утверждать).
- Мышление с точки зрения пост-условий, естественно, создает дизайн, который имеет успех в качестве пост-состояния, который является естественным стилем для использования исключений. Нормальный ("счастливый") путь выполнения вашей программы выставляется линейно, при этом весь код обработки ошибок перемещается в предложения
catch
.
Ответ 9
Я бы сказал, что нет жестких и быстрых правил о том, когда использовать исключения. Однако есть веские причины использовать или не использовать их:
Причины использования исключений:
- Кодовый поток для обычного случая более ясен
- Может возвращать сложную информацию об ошибке как объект (хотя это также может быть достигнуто с использованием параметра ошибки "out", переданного по ссылке)
- Языки обычно предоставляют некоторую возможность для управления аккуратной очисткой в случае исключения (try/finally в Java, используя в С#, RAII на С++)
- В случае, если исключение не выбрасывается, выполнение иногда может быть быстрее, чем проверка кодов возврата
- В Java проверяемые исключения должны быть объявлены или пойманы (хотя это может быть причиной)
Причины не использовать исключения:
- Иногда это излишне, если обработка ошибок проста
- Если исключения не задокументированы или не объявлены, они могут быть неотображаемы при вызове кода, что может быть хуже, чем если вызывающий код просто проигнорировал код возврата (выход приложения с тихим сбоем - что еще хуже может зависеть от сценария)
- В С++ код, который использует исключения, должен быть безопасным для исключений (даже если вы не бросаете или не поймаете их, а вызываете функцию throwing косвенно)
- В С++ трудно сказать, когда функция может быть брошена, поэтому вы должны быть параноиком по безопасности исключений, если вы используете их
- Отбрасывание и улавливание исключений обычно значительно дороже по сравнению с проверкой флага возврата
В общем, я был бы более склонным использовать исключения в Java, чем в С++ или С#, потому что я считаю, что исключение, объявленное или нет, в корне является частью формального интерфейса функции, поскольку изменение вашего исключение может нарушить код вызова. Самое большое преимущество использования их в Java IMO заключается в том, что вы знаете, что ваш вызывающий должен обрабатывать исключение, и это улучшает вероятность правильного поведения.
Из-за этого на любом языке я всегда получал бы все исключения в слое кода или API из общего класса, так что код вызова всегда может гарантировать, что все исключения будут обнаружены. Кроме того, я бы счел нецелесообразным бросать классы исключений, специфичные для реализации, при написании API или библиотеки (т.е. Исключить исключения из более низких уровней, чтобы исключение, которое получает ваш вызывающий абонент, понятно в контексте вашего интерфейса).
Обратите внимание, что Java делает различие между общими и исключениями Runtime в том, что последнее не нужно объявлять. Я бы использовал только классы исключений Runtime, когда вы знаете, что ошибка является результатом ошибки в программе.
Ответ 10
Классы исключений - это как обычные классы. Вы создаете новый класс, когда он "является" объектом другого типа, с разными полями и разными операциями.
Как правило, вы должны попробовать баланс между количеством исключений и детализацией исключений. Если ваш метод выбрасывает более 4-5 различных исключений, вы, вероятно, можете объединить некоторые из них в более "общие" исключения (например, в вашем случае "AuthenticationFailedException" ) и использовать сообщение об исключении для подробного описания того, что пошло не так. Если ваш код не обрабатывает каждый из них по-разному, вам не нужно создавать много классов исключений. И если это так, вы можете просто вернуть перечисление с произошедшей ошибкой. Это немного чище.
Ответ 11
Если этот код работает внутри цикла, который, вероятно, вызовет исключение снова и снова, то бросание исключений не очень хорошо, потому что они довольно медленны для больших N. Но нет ничего плохого в том, чтобы бросать пользовательские исключения, если производительность не является проблемой. Просто убедитесь, что у вас есть базовое исключение, которое они все наследуют, называемое BaseException или что-то в этом роде. BaseException наследует System.Exception, но все ваши исключения наследуют BaseException. Вы можете даже иметь дерево типов исключений для группировки похожих типов, но это может быть или не быть чрезмерным.
Итак, короткий ответ заключается в том, что если это не приведет к значительному снижению производительности (что не должно быть, если вы не выбрасываете много исключений), то продолжайте.
Ответ 12
Я согласен с курсом japollock там - бросьте принятие, когда вы не уверены в результатах операции. Звонки на API, доступ к файловым системам, вызовы базы данных и т.д. В любое время, когда вы проходите "границы" ваших языков программирования.
Я бы хотел добавить, не стесняйтесь бросать стандартное исключение. Если вы не собираетесь делать что-то "другое" (игнорировать, отправлять по электронной почте, регистрировать, показывать, что изображение китобойного кита и т.д.), Тогда не беспокойтесь о пользовательских исключениях.
Ответ 13
эмпирическое правило для исключения исключений довольно просто. вы делаете это, когда ваш код вошел в состояние UNRECOVERABLE INVALID. если данные скомпрометированы или вы не можете отложить обработку, которая произошла до точки, то вы должны ее закончить. действительно, что еще вы можете сделать? ваша логика обработки в конечном итоге не удастся в другом месте. если вы можете как-то восстановить, тогда сделайте это и не бросайте исключение.
в вашем конкретном случае, если вы были вынуждены делать что-то глупое, как принимать деньги, и только затем проверять пользователь/пароль, вы должны прекратить процесс, выбросив исключение, чтобы сообщить, что произошло что-то плохое и предотвратить дальнейшее повреждение.
Ответ 14
В общем, вы хотите выбросить исключение для всего, что может произойти в вашем приложении, которое является "Исключительным"
В вашем примере оба этих исключения выглядят так, как будто вы вызываете их с помощью проверки пароля/имени пользователя. В этом случае можно утверждать, что это не исключает того, что кто-то будет ошибочно использовать имя пользователя/пароль.
Они являются "исключениями" для основного потока вашего UML, но больше "ветвей" в обработке.
Если вы попытались получить доступ к файлу или базе данных passwd и не могли, это было бы исключительным случаем и потребовало бы исключения исключений.
Ответ 15
Во-первых, если пользователи вашего API не заинтересованы в конкретных мелкомасштабных сбоях, то наличие определенных исключений для них не имеет никакого значения.
Поскольку часто невозможно узнать, что может быть полезно для ваших пользователей, лучше использовать специальные исключения, но обеспечить их наследование из общего класса (например, std:: exception или его производных в С++). Это позволяет вашему клиенту улавливать определенные исключения, если они выбирают, или более общее исключение, если им все равно.
Ответ 16
Исключения предназначены для событий, которые являются ненормальным поведением, ошибками, сбоями и т.д. Функциональное поведение, пользовательская ошибка и т.д. Должны обрабатываться программной логикой. Поскольку неправильная учетная запись или пароль являются ожидаемой частью логического потока в процедуре входа в систему, она должна иметь возможность обрабатывать эти ситуации без исключений.
Ответ 17
Я бы сказал, что в целом каждый фундаментализм ведет к аду.
Вы, конечно же, не захотите в конечном итоге с потоком, управляемым исключениями, но избегать исключений вообще также плохой идеей. Вы должны найти баланс между обоими подходами. Я бы не стал создавать тип исключения для каждой исключительной ситуации. Это неэффективно.
Обычно я предпочитаю создавать два основных типа исключений, которые используются во всей системе: LogicalException и TechnicalException. Они могут быть дополнительно выделены подтипами, если это необходимо, но обычно это не требуется.
Техническое исключение означает, что действительно неожиданное исключение, такое как сервер базы данных, отсутствует, подключение к веб-службе бросило IOException и так далее.
С другой стороны, логические исключения используются для распространения менее серьезной ошибочной ситуации на верхние уровни (как правило, на некоторый результат проверки).
Обратите внимание, что даже логическое исключение не предназначено для регулярного использования для управления потоком программы, а скорее для выделения ситуации, когда поток действительно должен заканчиваться. При использовании в Java оба типа исключений представляют собой подклассы RuntimeException, а обработка ошибок ориентирована на аспект.
Таким образом, в примере для входа может быть разумным создать что-то вроде AuthenticationException и отличить конкретные ситуации от значений перечисления, таких как UsernameNotExisting, PasswordMismatch и т.д. Тогда вы не станете иметь огромную иерархию исключений и можете хранить блоки catch на поддерживаемом уровне. Вы также можете легко использовать какой-то общий механизм обработки исключений, поскольку у вас есть исключения, классифицированные и хорошо знающие, что нужно распространять до пользователя и как.
Наше типичное использование заключается в том, чтобы вызывать логическое исключение во время вызова веб-службы, когда вход пользователя был недействительным. Exception получает сортировку в детали SOAPFault, а затем снова отменяется на исключение на клиенте, что приводит к отображению ошибки проверки в одном определенном поле ввода веб-страницы, поскольку исключение имеет правильное сопоставление с этим полем.
Это, конечно, не единственная ситуация: вам не нужно ударять веб-службу, чтобы выбросить исключение. Вы можете сделать это в любой исключительной ситуации (например, в случае, если вам нужно быстро) - это все на ваше усмотрение.
Ответ 18
У меня есть философские проблемы с использованием исключений. В принципе, вы ожидаете, что возникнет конкретный сценарий, но вместо того, чтобы обрабатывать его явно, вы отталкиваете проблему, чтобы ее обрабатывали "в другом месте". И где это "в другом месте" может быть кто-то догадаться.
Ответ 19
Основной причиной отказа от исключения исключения является то, что при создании исключения возникает много накладных расходов.
В статье ниже говорится, что исключение - это исключительные условия и ошибки.
Неправильное имя пользователя не обязательно является программной ошибкой, но пользовательской ошибкой...
Вот достойная отправная точка для исключений в .NET:
http://msdn.microsoft.com/en-us/library/ms229030(VS.80).aspx
Ответ 20
Отбрасывание исключений заставляет стек разматываться, что имеет некоторые последствия для производительности (признано, современные управляемые среды улучшились). Еще много раз бросать и ловить исключения во вложенной ситуации было бы плохой идеей.
Вероятно, что более важно, исключения предназначены для исключительных условий. Они не должны использоваться для обычного потока управления, потому что это повредит вашей читаемости кода.
Ответ 21
У меня есть три типа условий, которые я поймаю.
-
Неправильный или отсутствующий ввод не должен быть исключением. Используйте как jQ сервера, так и серверное регулярное выражение для обнаружения, установки атрибутов и пересылки на одну страницу с сообщениями.
-
AppException. Обычно это исключение, которое вы обнаруживаете и бросаете в своем коде. Другими словами, это те, которые вы ожидаете (файл не существует). Запишите его, установите сообщение и перейдите на страницу общей ошибки. На этой странице обычно немного информации о том, что произошло.
-
Неожиданное исключение. Это те, о которых вы не знаете. Запишите его с подробной информацией и перейдите на общую страницу с ошибкой.
Надеюсь, что это поможет
Ответ 22
Безопасность сочетается с вашим примером: вы не должны указывать злоумышленнику, что имя пользователя существует, но пароль неверен. Эта дополнительная информация вам не нужна. Просто скажите: "имя пользователя или пароль неверны".
Ответ 23
Простой ответ - всякий раз, когда операция невозможна (из-за какого-либо приложения или потому, что это нарушит бизнес-логику). Если вызывается метод и невозможно выполнить то, что было написано в этом методе, бросьте исключение. Хорошим примером является то, что конструкторы всегда бросают ArgumentExceptions, если экземпляр не может быть создан с использованием предоставленных параметров. Другим примером является InvalidOperationException, которое вызывается, когда операция не может быть выполнена из-за состояния другого члена или членов класса.
В вашем случае, если вы используете такой метод, как Login (имя пользователя, пароль), если имя пользователя недопустимо, действительно правильно вызывать исключение UserNameNotValidException или PasswordNotCorrectException, если пароль неверен. Пользователь не может войти в систему, используя поставляемый параметр (т.е. Это невозможно, потому что это будет нарушать аутентификацию), поэтому бросьте исключение. Хотя у меня могут быть два исключения наследования от ArgumentException.
Сказав это, если вы хотите НЕ бросить исключение, потому что неудача входа может быть очень распространенной, одна стратегия заключается в том, чтобы вместо этого создать метод, который возвращает типы, которые представляют разные сбои. Вот пример:
{ // class
...
public LoginResult Login(string user, string password)
{
if (IsInvalidUser(user))
{
return new UserInvalidLoginResult(user);
}
else if (IsInvalidPassword(user, password))
{
return new PasswordInvalidLoginResult(user, password);
}
else
{
return new SuccessfulLoginResult();
}
}
...
}
public abstract class LoginResult
{
public readonly string Message;
protected LoginResult(string message)
{
this.Message = message;
}
}
public class SuccessfulLoginResult : LoginResult
{
public SucccessfulLogin(string user)
: base(string.Format("Login for user '{0}' was successful.", user))
{ }
}
public class UserInvalidLoginResult : LoginResult
{
public UserInvalidLoginResult(string user)
: base(string.Format("The username '{0}' is invalid.", user))
{ }
}
public class PasswordInvalidLoginResult : LoginResult
{
public PasswordInvalidLoginResult(string password, string user)
: base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
{ }
}
Большинство разработчиков учат избегать исключений из-за накладных расходов, вызванных их броском. Это здорово быть ресурсоемким, но обычно не за счет дизайна вашего приложения. Вероятно, это причина, по которой вам сказали не бросать ваши два Исключения. Следует ли использовать Исключения или нет, обычно сводится к тому, как часто происходит Исключение. Если это довольно общий или довольно ожидаемый результат, то это происходит, когда большинство разработчиков избегают исключений и вместо этого создают другой метод для указания отказа, из-за предполагаемого потребления ресурсов.
Здесь приведен пример исключения использования исключений в сценарии, как описано выше, с использованием шаблона Try():
public class ValidatedLogin
{
public readonly string User;
public readonly string Password;
public ValidatedLogin(string user, string password)
{
if (IsInvalidUser(user))
{
throw new UserInvalidException(user);
}
else if (IsInvalidPassword(user, password))
{
throw new PasswordInvalidException(password);
}
this.User = user;
this.Password = password;
}
public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
{
if (IsInvalidUser(user) ||
IsInvalidPassword(user, password))
{
return false;
}
validatedLogin = new ValidatedLogin(user, password);
return true;
}
}
Ответ 24
На мой взгляд, основной вопрос заключается в том, следует ли ожидать, что вызывающий абонент захочет продолжить нормальный поток программы, если возникает условие. Если вы не знаете, у вас есть отдельные методы doSomething и trySomething, где первая возвращает ошибку, а вторая - нет, или имеет подпрограмму, которая принимает параметр, указывающий, следует ли исключать исключение, если оно не работает). Рассмотрим класс для отправки команд удаленной системе и отправки ответов. Некоторые команды (например, перезагрузка) заставят удаленную систему отправлять ответ, но затем не реагируют на определенный период времени. Поэтому полезно иметь возможность отправить команду "ping" и выяснить, отвечает ли удаленная система за разумный промежуток времени, не вызывая исключения, если это не так (вызывающий может ожидать, что первые несколько "ping" провалится, но в конечном итоге будет работать). С другой стороны, если у вас есть последовательность команд вроде:
exchange_command("open tempfile");
exchange_command("write tempfile data {whatever}");
exchange_command("write tempfile data {whatever}");
exchange_command("write tempfile data {whatever}");
exchange_command("write tempfile data {whatever}");
exchange_command("close tempfile");
exchange_command("copy tempfile to realfile");
нужно было бы, чтобы любая операция прерывала всю последовательность. Хотя можно проверить каждую операцию, чтобы убедиться, что она преуспела, более полезно, чтобы процедура exchange_command() выдавала исключение, если команда терпит неудачу.
На самом деле, в приведенном выше сценарии может быть полезно иметь параметр для выбора нескольких режимов обработки отказа: никогда не бросать исключения, исключать исключения только для коммуникационных ошибок или бросать исключения в любых случаях, когда команда не возвращается индикация "успех".
Ответ 25
для меня Исключение должно быть брошено, когда требуемое техническое или бизнес-правило выходит из строя.
например, если автомобильный объект связан с массивом из 4 шин... если одна шина или более равна нулю... исключение должно быть уволено "NotEnoughTiresException", поскольку его можно поймать на разном уровне системы и иметь значительный что означает использование журнала.
кроме того, если мы просто попробуем контролировать поток нуль и предотвратить инсталляцию автомобиля.
мы никогда не сможем найти источник проблемы, потому что шина не должна быть нулевой в первую очередь.
Ответ 26
Вы можете использовать несколько условных исключений для этих условий. Напр. ArgumentException предполагается использовать, когда что-то пойдет не так с параметрами метода (за исключением ArgumentNullException). Как правило, вам не нужны исключения, такие как LessThanZeroException, NotPrimeNumberException и т.д. Подумайте о пользователе вашего метода. Количество условий, которые она хочет обработать конкретно, равно числу тех исключений, которые ваш метод должен бросить. Таким образом, вы можете определить, какие подробные исключения вы будете иметь.
Кстати, всегда старайтесь предоставить некоторым пользователям библиотеки возможность избежать исключений. TryParse - хороший пример, он существует, так что вам не нужно использовать int.Parse и вызывать исключение. В вашем случае вы можете указать некоторые методы проверки правильности имени пользователя или пароля, поэтому вашим пользователям (или вам) не придется выполнять много обработки исключений. Это, как мы надеемся, приведет к более быстрому считыванию кода и повышению производительности.
Ответ 27
В конечном итоге решение сводится к тому, полезно ли справляться с такими ошибками на уровне приложений, как это, используя обработку исключений, или через собственный механизм, который запускается на дому, например, возвращать коды состояния. Я не думаю, что существует жесткое правило, о котором лучше, но я бы подумал:
- Кто звонит ваш код? Является ли это общедоступным API какой-либо или внутренней библиотеки?
- На каком языке вы используете? Если он, например, Java, то бросание (отмеченное) исключение ставит явное бремя для вашего вызывающего лица каким-то образом обрабатывать это условие ошибки, а не статус возврата, который можно игнорировать. Это может быть хорошо или плохо.
- Как другие условия ошибки в одном приложении обрабатываются? Звонящие не захотят иметь дело с модулем, который обрабатывает ошибки с особым образом, в отличие от всего остального в системе.
- Сколько вещей может пойти не так с рутиной, о которой идет речь, и как они будут обрабатываться по-другому? Рассмотрим разницу между рядом блоков catch, которые обрабатывают разные ошибки и включают код ошибки.
- Есть ли у вас структурированная информация об ошибке, которую нужно вернуть? Выбрасывание исключения дает вам лучшее место для размещения этой информации, чем просто возврат статуса.
Ответ 28
Существует два основных класса исключения:
1) Исключение системы (например, соединение с базой данных потеряно) или
2) Исключение пользователя. (например, проверка правильности ввода пользователя, "неверный пароль" )
Мне было сочтено создание собственного класса исключения пользователя, и когда я хочу выбросить ошибку пользователя, я хочу, чтобы меня обрабатывали по-разному (т.е. отображалась сгенерированная ошибка пользователю), тогда все, что мне нужно сделать в моем основном обработчике ошибок, - это проверить тип объекта:
If TypeName(ex) = "UserException" Then
Display(ex.message)
Else
DisplayError("An unexpected error has occured, contact your help desk")
LogError(ex)
End If
Ответ 29
Некоторые полезные вещи, о которых нужно подумать при принятии решения о целесообразности исключения:
-
какой уровень кода вы хотите запустить после появления кандидата-кандидата - то есть, сколько слоев стека вызовов должно быть восстановлено. Обычно вы хотите обрабатывать исключение как можно ближе к тому месту, где оно происходит. Для проверки имени пользователя и пароля вы обычно обрабатываете отказы в одном блоке кода, а не позволяете исключению пузыря. Поэтому исключение, вероятно, не подходит. (OTOH, после трех неудачных попыток входа в систему, поток управления может меняться в другом месте, и здесь может быть полезно исключение.)
-
Является ли это событие тем, что вы хотели бы увидеть в журнале ошибок? Не каждое исключение записывается в журнал ошибок, но полезно спросить, будет ли эта запись в журнале ошибок полезной, т.е. Вы попытаетесь что-то сделать с ней или будете игнорировать мусор.
/li >
Ответ 30
"PasswordNotCorrectException" не является хорошим примером использования исключений. Пользователей, получающих свои пароли неправильно, следует ожидать, так что это вряд ли исключение ИМХО. Вы, вероятно, даже оправились от него, показывая хорошее сообщение об ошибке, так что это просто проверка действительности.
Необработанные исключения прекратят выполнение в конечном итоге - это хорошо. Если вы возвращаете ложные, нулевые или коды ошибок, вам придется иметь дело с состоянием программы самостоятельно. Если вы забыли проверить условия где-то, ваша программа может продолжать работать с неправильными данными, и вам может быть трудно узнать, что произошло и где.
Конечно, вы можете вызвать ту же проблему с пустым операциями catch, но, по крайней мере, определить их проще и не требует понимания логики.
Итак, как правило:
Используйте их везде, где вы не хотите, или просто не можете восстановить из-за ошибки.