Когда бросать исключение?

У меня есть исключения, созданные для каждого условия, которое мое приложение не ожидает. UserNameNotValidException , PasswordNotCorrectException и т. Д.

Однако мне сказали, что я не должен создавать исключения для этих условий. В моем UML эти исключения ARE для основного streamа, так почему это не должно быть исключением?

Любые рекомендации или рекомендации по созданию исключений?

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

Пример 1: скажем, у меня есть функция, которая должна проверять произвольный class и возвращать true, если этот class наследуется от List <>. Эта функция задает вопрос: «Является ли этот объект потомком списка?» Эта функция никогда не должна генерировать исключение, поскольку в ее работе нет серых областей – каждый отдельный класс либо выполняет, либо не наследует от List <>, поэтому ответ всегда «да» или «нет».

Пример 2: скажем, у меня есть другая функция, которая проверяет список <> и возвращает значение true, если его длина больше 50, а false, если длина меньше. Эта функция задает вопрос: «Имеет ли этот список более 50 элементов?» Но этот вопрос делает предположение – он предполагает, что заданный им объект является списком. Если я передам ему NULL, то это предположение неверно. В этом случае, если функция возвращает либо true, либо false, то она нарушает свои собственные правила. Функция не может вернуть ничего и утверждать, что она правильно ответила на вопрос. Поэтому он не возвращается – он выдает исключение.

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

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

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

Мои маленькие рекомендации сильно зависят от большой книги «Code complete»:

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

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

EDIT: Мне не нравятся исключения, потому что вы не можете определить, генерирует ли метод исключение, просто просмотрев вызов. Вот почему исключения следует использовать только в том случае, если вы не можете справиться с ситуацией достойным образом (подумайте «из памяти» или «компьютер горит»).

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

Другие предполагают, что исключения не должны использоваться, потому что плохой логин следует ожидать в нормальном streamе, если пользователь ошибается. Я не согласен, и я не могу рассуждать. Сравните это с открытием файла .. если файл не существует или недоступен по какой-либо причине, исключение будет выведено фреймворком. Использование логики выше было ошибкой Microsoft. Они должны были вернуть код ошибки. То же самое для парсинга, веб-запросов и т. Д. И т. Д.

Я не считаю плохую часть входа в обычный stream, это исключительный. Обычно пользователь вводит правильный пароль, и файл существует. Исключительные случаи являются исключительными, и отлично использовать исключения для них. Усложнение кода путем распространения возвращаемых значений через n уровней вверх по стеку – это пустая трата энергии и приведет к запутанному коду. Сделайте простейшую вещь, которая могла бы работать. Не досрочно оптимизируйте, используя коды ошибок, исключительные вещи по определению редко бывают, а исключения не стоят ничего, если вы их не выбросите.

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

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

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


Вы увидите много советов, в том числе в ответах на этот вопрос, что вы должны исключать исключения только в «исключительных» обстоятельствах. Это кажется поверхностно разумным, но является ошибочным советом, потому что он заменяет один вопрос («когда я должен делать исключение») с другим субъективным вопросом («что является исключительным»). Вместо этого следуйте советам Херба Саттера (для C ++, доступного в статье доктора Доббса « Когда и как использовать исключения» , а также в его книге с Андреем Александреску, « Стандарты кодирования на C ++» ): выдайте исключение, если и только если

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

Почему это лучше? Разве это не заменяет вопрос несколькими вопросами о предпосылках, постусловиях и инвариантах? Это лучше по нескольким причинам.

  • Предпосылки, постусловия и инварианты – это проектные характеристики нашей программы (ее внутренний API), тогда как решение throw – это деталь реализации. Это заставляет нас помнить, что мы должны рассматривать дизайн и его реализацию отдельно, а наша работа при внедрении метода заключается в создании чего-то, что удовлетворяет дизайнерским ограничениям.
  • Это заставляет нас думать в терминах предварительных условий, постусловий и инвариантов, которые являются единственными предположениями, которые вызывающие нашего метода должны делать и точно выражены, что позволяет свободно связываться между компонентами нашей программы.
  • Тогда эта свободная связь позволяет нам реорганизовать реализацию, если это необходимо.
  • Послесловия и инварианты проверяются; это приводит к тому, что код может быть легко протестирован модулем, потому что пост-условия являются предикатами, которые может проверять наш блок-тест (утверждать).
  • Мышление с точки зрения пост-условий, естественно, создает дизайн, который имеет успех в качестве пост-состояния , который является естественным стилем для использования исключений. Нормальный («счастливый») путь выполнения вашей программы выставляется линейно, при этом весь код обработки ошибок перемещается в предложения catch .

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

Причины использования исключений:

  • Кодовый stream для общего случая более ясен
  • Может возвращать сложную информацию об ошибке как объект (хотя это также может быть достигнуто с использованием параметра ошибки «out», переданного по ссылке)
  • Языки обычно предоставляют некоторую возможность для управления аккуратной очисткой в ​​случае исключения (try / finally на Java, используя в C #, RAII на C ++)
  • В случае, если исключение не выбрасывается, выполнение иногда может быть быстрее, чем проверка кодов возврата
  • В Java проверяемые исключения должны быть объявлены или пойманы (хотя это может быть причиной)

Причины не использовать исключения:

  • Иногда это слишком сложно, если обработка ошибок проста
  • Если исключения не задокументированы или не объявлены, они могут быть непроверены при вызове кода, что может быть хуже, чем если вызывающий код просто проигнорировал код возврата (выход приложения с тихим сбоем – что еще хуже может зависеть от сценария)
  • В C ++ код, который использует исключения, должен быть безопасным для исключений (даже если вы его не бросаете или не поймаете, а косвенным образом вызываете функцию throwing)
  • В C ++ трудно сказать, когда функция может быть брошена, поэтому вы должны быть параноидальными относительно безопасности исключений, если вы их используете
  • Бросание и улавливание исключений обычно значительно дороже по сравнению с проверкой флага возврата

В общем, я был бы более склонным использовать исключения на Java, чем в C ++ или C #, потому что я считаю, что исключение, объявленное или нет, является в основном частью формального интерфейса функции, поскольку изменение вашей гарантии исключения может перерыв код вызова. Самое большое преимущество использования их в Java IMO заключается в том, что вы знаете, что ваш вызывающий должен обрабатывать исключение, и это улучшает вероятность правильного поведения.

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

Обратите внимание: Java делает различие между общими и исключениями Runtime в том, что последнее не нужно объявлять. Я бы использовал только classы исключений Runtime, когда вы знаете, что ошибка является результатом ошибки в программе.

Классы исключений – это обычные classы. Вы создаете новый class, когда он «является» объектом другого типа, с разными полями и разными операциями.

Как правило, вы должны попробовать баланс между количеством исключений и детализацией исключений. Если ваш метод выбрасывает более 4-5 разных исключений, вы можете, вероятно, объединить некоторые из них в более «общие» исключения (например, в вашем случае «AuthenticationFailedException») и использовать сообщение об исключении, чтобы детализировать, что пошло не так. Если ваш код не обрабатывает каждый из них по-разному, вам не нужно создавать много classов исключений. И если это так, вы можете просто вернуть перечисление с произошедшей ошибкой. Это немного чище.

Если это код работает внутри цикла, который, вероятно, вызовет исключение снова и снова, то бросание исключений не очень хорошо, потому что они довольно медленны для больших N. Но нет ничего плохого в том, чтобы бросать пользовательские исключения, если производительность не вопрос. Просто убедитесь, что у вас есть базовое исключение, которое они все наследуют, называемое BaseException или что-то в этом роде. BaseException наследует System.Exception, но все ваши исключения наследуют BaseException. Вы можете даже иметь дерево типов исключений для группировки похожих типов, но это может быть или не быть чрезмерным.

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

Я согласен с japollock путь туда – бросать принятие, когда вы не уверены в результатах операции. Звонки на API, доступ к файловым системам, вызовы базы данных и т. Д. Каждый раз, когда вы переходите «границы» ваших языков программирования.

Я бы хотел добавить, не стесняйтесь бросать стандартное исключение. Если вы не собираетесь делать что-то «другое» (игнорировать, отправлять по электронной почте, регистрировать, показывать, что изображение китобойного кита и т. Д.), То не беспокойтесь о пользовательских исключениях.

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

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

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

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

Они являются «исключениями» для основного streamа вашего UML, но больше «ветвей» в обработке.

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

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

Поскольку часто невозможно узнать, что может быть полезно для ваших пользователей, лучший подход состоит в том, чтобы иметь конкретные исключения, но обеспечить их наследование из общего classа (например, std :: exception или его производных в C ++). Это позволяет вашему клиенту улавливать определенные исключения, если они выбирают, или более общее исключение, если им все равно.

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

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

Я бы сказал, что в целом каждый фундаментализм ведет к аду.

Вы, конечно же, не захотите, чтобы в конечном итоге был задействован stream, связанный с исключениями, но исключение исключений – тоже плохая идея. Вы должны найти баланс между обоими подходами. Я бы не стал создавать тип исключения для каждой исключительной ситуации. Это неэффективно.

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

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

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

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

Таким образом, в примере входа в систему может быть разумным создать нечто вроде исключения аутентификации и различать конкретные ситуации с помощью значений enums, таких как UsernameNotExisting , PasswordMismatch и т. Д. Тогда вы не станете иметь огромную иерархию исключений и не сможете блокировать блоки на поддерживаемом уровне , Вы также можете легко использовать какой-то общий механизм обработки исключений, поскольку у вас есть исключения, classифицированные и хорошо знающие, что нужно распространять до пользователя и как это сделать.

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

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

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

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

Неправильное имя пользователя не обязательно является программной ошибкой, но ошибкой пользователя …

Вот достойная отправная точка для исключений в .NET: http://msdn.microsoft.com/en-us/library/ms229030(VS.80).aspx

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

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

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

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

  2. AppException. Обычно это исключение, которое вы обнаруживаете и бросаете в своем коде. Другими словами, это те, которые вы ожидаете (файл не существует). Запишите его, установите сообщение и перейдите на страницу общей ошибки. На этой странице обычно немного информации о том, что произошло.

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

Надеюсь это поможет

Безопасность сочетается с вашим примером: вы не должны указывать злоумышленнику, что имя пользователя существует, но пароль неправильный. Это дополнительная информация, которую вам не нужно делиться. Просто скажите: «Имя пользователя или пароль неверны».

Простой ответ – всякий раз, когда операция невозможна (из-за какого-либо приложения или из-за нарушения бизнес-логики). Если вызывается метод и невозможно выполнить то, что было написано в этом методе, бросьте исключение. Хорошим примером является то, что конструкторы всегда бросают ArgumentExceptions, если экземпляр не может быть создан с использованием предоставленных параметров. Другим примером является InvalidOperationException, которое вызывается, когда операция не может быть выполнена из-за состояния другого члена или членов classа.

В вашем случае, если вы используете такой метод, как Login (имя пользователя, пароль), если имя пользователя недопустимо, то действительно правильно вызывать исключение UserNameNotValidException или PasswordNotCorrectException, если пароль неверен. Пользователь не может войти в систему, используя поставляемый параметр (ы) (т. Е. Это невозможно, потому что это будет нарушать аутентификацию), поэтому бросьте исключение. Хотя у меня могут быть два исключения наследования из ArgumentException.

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

 { // 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)) { } } 

Большинство разработчиков обучаются избегать исключений из-за накладных расходов, вызванных их броском. Это здорово быть ресурсоемким, но обычно не за счет дизайна вашего приложения. Вероятно, это причина, по которой вам сказали не бросать ваши два Исключения. Следует ли использовать Исключения или нет, обычно сводится к тому, как часто происходит Исключение. If it’s a fairly common or an fairly expectable result, this is when most developers will avoid Exceptions and instead create another method to indicate failure, because of the supposed consumption of resources.

Here’s an example of avoiding using Exceptions in a scenario like just described, using the Try() pattern:

 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; } } 

To my mind, the fundamental question should be whether one would expect that the caller would want to continue normal program flow if a condition occurs. If you don’t know, either have separate doSomething and trySomething methods, where the former returns an error and the latter does not, or have a routine that accepts a parameter to indicate whether an exception should be thrown if it fails). Consider a class to send commands to a remote system and report responses. Certain commands (eg restart) will cause the remote system to send a response but then be non-responsive for a certain length of time. It is thus useful to be able to send a “ping” command and find out whether the remote system responds in a reasonable length of time without having to throw an exception if it doesn’t (the caller would probably expect that the first few “ping” attempts would fail, but one would eventually work). On the other hand, if one has a sequence of commands like:

  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");

one would want failure of any operation to abort the whole sequence. While one could check each operation to ensure it succeeded, it’s more helpful to have the exchange_command() routine throw an exception if a command fails.

Actually, in the above scenario it may be helpful to have a parameter to select a number of failure-handling modes: never throw exceptions, throw exceptions for communication errors only, or throw exceptions in any cases where a command does not return a “success” indication.

for me Exception should be thrown when a required technical or business rule fails. for instance if a car entity is associated with array of 4 tires … if one tire or more are null … an exception should be Fired “NotEnoughTiresException” , cuz it can be caught at different level of the system and have a significant meaning through logging. besides if we just try to flow control the null and prevent the instanciation of the car . we might never never find the source of the problem , cuz the tire isn’t supposed to be null in the first place .

You may use a little bit generic exceptions for that conditions. For eg ArgumentException is meant to be used when anything goes wrong with the parameters to a method (with the exception of ArgumentNullException). Generally you would not need exceptions like LessThanZeroException, NotPrimeNumberException etc. Think of the user of your method. The number of the conditions that she will want to handle specifically is equal to the number of the type of the exceptions that your method needs to throw. This way, you can determine how detailed exceptions you will have.

By the way, always try to provide some ways for users of your libraries to avoid exceptions. TryParse is a good example, it exists so that you don’t have to use int.Parse and catch an exception. In your case, you may want to provide some methods to check if user name is valid or password is correct so your users (or you) will not have to do lots of exception handling. This will hopefully result in more readble code and better performance.

Ultimately the decision comes down to whether it is more helpful to deal with application-level errors like this using exception handling, or via your own home-rolled mechanism like returning status codes. I don’t think there’s a hard-and-fast rule about which is better, but I would consider:

  • Who’s calling your code? Is this a public API of some sort or an internal library?
  • What language are you using? If it’s Java, for example, then throwing a (checked) exception puts an explicit burden on your caller to handle this error condition in some way, as opposed to a return status which could be ignored. That could be good or bad.
  • How are other error conditions in the same application handled? Callers won’t want to deal with a module that handles errors in an idiosyncratic way unlike anything else in the system.
  • How many things can go wrong with the routine in question, and how would they be handled differently? Consider the difference between a series of catch blocks that handle different errors and a switch on an error code.
  • Do you have structured information about the error you need to return? Throwing an exception gives you a better place to put this information than just returning a status.

There are two main classes of exception:

1) System exception (eg Database connection lost) or 2) User exception. (eg User input validation, ‘password is incorrect’)

I found it helpful to create my own User Exception Class and when I want to throw a user error I want to be handled differently (ie resourced error displayed to the user) then all I need do in my main error handler is check the object type:

  If TypeName(ex) = "UserException" Then Display(ex.message) Else DisplayError("An unexpected error has occured, contact your help desk") LogError(ex) End If 

Some useful things to think about when deciding whether an exception is appropriate:

  1. what level of code you want to have run after the exception candidate occurs – that is, how many layers of the call stack should unwind. You generally want to handle an exception as close as possible to where it occurs. For username/password validation, you would normally handle failures in the same block of code, rather than letting an exception bubble up. So an exception is probably not appropriate. (OTOH, after three failed login attempts, control flow may shift elsewhere, and an exception may be appropriate here.)

  2. Is this event something you would want to see in an error log? Not every exception is written to an error log, but it’s useful to ask whether this entry in an error log would be useful – ie, you would try to do something about it, or would be the garbage you ignore.

“PasswordNotCorrectException” isn’t a good example for using exceptions. Users getting their passwords wrong is to be expected, so it’s hardly an exception IMHO. You probably even recover from it, showing a nice error message, so it’s just a validity check.

Unhandled exceptions will stop the execution eventually – which is good. If you’re returning false, null or error codes, you will have to deal with the program’s state all by yourself. If you forget to check conditions somewhere, your program may keep running with wrong data, and you may have a hard time figuring out what happened and where .

Of course, you could cause the same problem with empty catch statements, but at least spotting those is easier and doesn’t require you to understand the logic.

So as a rule of thumb:

Use them wherever you don’t want or simply can’t recover from an error.

  • Нужна помощь по mod 1000000007 вопросам
  • Как определить, является ли мой расчет pi точным?
  • Есть ли алгоритм для смешивания цветов, который работает как смешивание реальных цветов?
  • Асинхронный и multithreading. Есть ли разница?
  • Сколько параметров слишком много?
  • Получение ближайшего соответствия строк
  • Является ли GUID уникальным в 100% случаев?
  • Должен ли я тестировать частные методы или только публичные?
  • Что такое безопасный тип?
  • Структура данных, поддерживающая O (1) случайный доступ и наихудший вариант O (1)?
  • Почему переменные «i» и «j» используются для счетчиков?
  • Давайте будем гением компьютера.