Баннер мобильный (1) Пройти тест

Исключения

Глоссарий

27 марта 2023

Поделиться

Скопировано

Содержание

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

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

    Механизм обработки исключений существует в большинстве языков программирования. Он может быть реализован немного по-разному, но общая суть схожа: это всегда какие-то особые случаи, которые надо обработать отдельно. Мы при описании будем отталкиваться от особенностей исключений в Java, но встретить их можно и в других языках: JavaScript, PHP, Python, C++ и так далее.

    Зачем нужны исключения

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

    Работа без исключений

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

    Работа с исключениями

    Какими бывают исключения

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

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

    Как происходит работа с исключениями

    • Разработчик пишет код и понимает, что в какой-то момент в том или ином месте может возникнуть нештатная ситуация. Бывает, что исключения добавляют в уже написанный код — например, нештатную ситуацию обнаружили при тестировании.
    • В этом месте пишется особый блок кода — обработчик. Он говорит программе: здесь может возникнуть особая ситуация, если она случится, выполни вот это.
    • Внутри обработчика — функция, которая выполнится, если программа столкнется с описанной ситуацией. Она или исправит ситуацию, или скорректирует дальнейшее выполнение программы.

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

    Как устроена обработка исключений

    Существуют разные виды обработки: структурная и неструктурная, с возвратом и без возврата. Они различаются механизмом действия, но общая суть одна: это функция, которая запускается, если в коде случилась та или иная исключительная ситуация. Тут можно использовать условный оператор if или специальные синтаксические конструкции.

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

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

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

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

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

    Обычно асинхронные исключения обрабатывают неструктурно, а синхронные — структурно.

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

    Исключения и ошибки: разница

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

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

    Это действительно похожие понятия. В Java, например, сущности исключений и ошибок наследуются от общего предка — интерфейса Throwable. Но ошибка — это явление, когда что-то сделать принципиально не получается. А исключение — ситуация, когда программа просто не знает, что делать, если не указать на это дополнительно.

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

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

    Когда пользоваться исключениями, а когда — ошибками

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

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

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

    Как начать пользоваться исключениями

    В большинстве языков механизм обработки исключений есть по умолчанию — это популярная функция. Но приступать к работе с ними рекомендуют после изучения базовых возможностей языка. Мы советуем идти от простого к сложному: начать с основ и затем переходить к комплексным темам. Конкретно обработка исключений обычно изучается перед тем, как человек переходит к практическим проектам, потому что любая более-менее сложная программа может столкнуться с исключениями в ходе работы.

    Поделиться

    Скопировано

    0 комментариев

    Комментарии