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

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

Более опытные коллеги не раз говорили мне не злоупотреблять исключениями.

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

Когда я спрашивал совета у старшего разработчика, я не помню, чтобы кто-то из них когда-либо призывал меня выбрать исключение. Ответ неизменно был примерно таким: «Нет, это не исключительная ситуация. Люди постоянно ошибаются в пароле. Не используйте исключение». Хорошо, хорошо. Никаких исключений.

При дальнейшем рассмотрении я обнаружил, что этот ответ отсутствует. Если неверный пароль не является исключительным, но, по крайней мере, в какой-то мере ожидаемым, то какая ситуация теперь была действительно исключительной? Удаленная служба возвращает ошибку внутреннего сервера HTTP 500? Наводнение раз в сто лет? Выиграть в лотерею?

В какой-то степени все эти сценарии правдоподобны и поэтому ожидаемы.

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

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

Иллюстрирующий пример

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

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

Возврат кода ошибки

  1. Метод проверки пароля возвращает вызывающему методу код успеха, если пароли совпадают, и код ошибки, если они не совпадают.
  2. Вызывающий метод должен будет проверить возвращаемое значение на наличие кода ошибки. Если это ошибка, например, «неверный пароль», снова рано возвращайтесь к вызывающему методу.
  3. И так далее вверх по стеку вызовов для всех методов, пока не
  4. Наконец, метод возьмет код ошибки и преобразует его в полезное сообщение для пользователя.

Проблемы с этим подходом:

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

Создание исключения

  1. Метод проверки пароля выдает исключение, которое сообщает об ошибке «неверный пароль».
  2. Другой метод, заинтересованный в этих исключениях, перехватывает их и преобразует исключение в полезное сообщение для конечного пользователя.

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

Вывод

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

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

Присоединяйтесь к сотням инженеров-программистов и получайте мои советы по программированию на Code Coach каждый будний день.