Сбои, Вызванные Исключениями

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

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

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

все время .

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

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

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

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

Рэймонд Чен описал проблему следующим образом: в 2004 году :

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

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

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

Другими словами, в модели возврата кода ошибки, когда кто-то пропускает обработку ошибок, это очевидно: он не проверяет код ошибки.

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

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

Это абсолютно верно.

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

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

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

Лучший пример, который я смог найти на сегодняшний день, находится в модуле пти Стандартная библиотека Python 3.3:

  
  
   

def spawn(argv, master_read=_read, stdin_read=_read): """Create a spawned process.""" if type(argv) == type(''): argv = (argv,) pid, master_fd = fork() if pid == CHILD: os.execlp(argv[0], *argv) (.

)

Каждый раз, когда кто-то вызывает этот код с неправильным именем исполняемого файла в argv, будет создаваться неиспользуемый, не подлежащий сборке мусора и неизвестный процесс для приложения Python, поскольку execlp завершится неудачно и разветвленный процесс будет проигнорирован.

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

Конечно, ошибку можно исправить, просто добавив try/Exception внутри самой функции spawn. Однако проблема в том, что эта логика казалась нормальной всем, кто когда-либо видел эту функцию с тех пор с 1994 года год, когда Гвидо ван Россум впервые совершил это .

Вот еще один интересный пример:

$ make clean Sorry, command-not-found has crashed! Please file a bug report at: https://bugs.launchpad.net/command-not-found/+filebug Please include the following information with the report: command-not-found version: 0.3 Python version: 3.2.3 final 0 Distributor ID: Ubuntu Description: Ubuntu 13.04 Release: 13.04 Codename: raring Exception information: unsupported locale setting Traceback (most recent call last): File "/.

/CommandNotFound/util.py", line 24, in crash_guard callback() File "/usr/lib/command-not-found", line 69, in main enable_i18n() File "/usr/lib/command-not-found", line 40, in enable_i18n locale.setlocale(locale.LC_ALL, '') File "/usr/lib/python3.2/locale.py", line 541, in setlocale return _setlocale(category, locale) locale.Error: unsupported locale setting

Это довольно серьезный сбой из-за отсутствия информации о локали в системном приложении, которое, по иронии судьбы, должно сообщать пользователям, какие пакеты устанавливать, если команда отсутствует. Обратите внимание, что вверху сетки находится ссылка на crash_guard .

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

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

Вместо настоящего защита приложений, это становится просто удобным способом аварийного завершения работы.

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

Это можно сделать, просто перенеся эту строку:

try: locale.setlocale(locale.LC_ALL, '') except Exception as e: print("Cannot change locale:", e)

Очевидно, это легко сделать.

Но, опять же, проблема в том, что было естественно сразу этого не сделать.

На самом деле это более чем естественно: действительно кажется лучше не считайте неверным путем.

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

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

Хотя более выразительный стиль возврата ошибок заставляет задуматься: вернет ли функция или метод в результате ошибку? Как это будет обрабатываться? Правда ли, что функция, взаимодействующая с системой, не вернет ошибку? Как решить проблему, которая может возникнуть? Результатом такой непроизвольной халатности является удивительное количество аварий и просто непредсказуемое поведение.

Оригинал Теги: #golang #перевод #исключения #Go

Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.