Должен ли я использовать try catch в Erlang или я должен вернуть токен ошибки? - PullRequest
3 голосов
/ 16 февраля 2010

Я пишу на Erlang, и я немного не уверен, как подойти к обработке ошибок, особенно после того, как Эрланг всегда видит ужасные ошибки.

Должен ли я использовать try catch в Erlang или передать обратно токен ошибки?

Ответы [ 4 ]

6 голосов
/ 17 февраля 2010

Существует три основных способа обработки исключений в последовательном Erlang:

  1. броска (throw(Term))
  2. ошибок (erlang:error(Reason))
  3. выходов (exit(Reason))

Броски должны использоваться для нелокальных возвратов и некоторых типов исключений, которые вы ожидаете иметь возможность обрабатывать (возможно, потому что они происходят часто). Когда он поднимется, вы должны попытаться остановить его, прежде чем он выйдет за пределы вашего модуля. Обычный способ, которым он используется в stdlib, - бросить кортеж вида {error, Reason}, который будет перехвачен функцией верхнего уровня в try...catch перед возвратом кортежа пользователю. Пользователь может затем решить, что делать на основе этого возвращаемого значения.

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

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

Ошибки и выходы редко должны обнаруживаться и обрабатываться последовательно (вы действительно должны быть уверены, что знаете, как все исправить!), Так как для этого существует другой процесс. Пусть это рухнет.

(подробнее: http://learnyousomeerlang.com/errors-and-exceptions)


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

Вы получаете новую функцию исключения для нескольких процессов: exit(Pid, Reason). Это позволяет вам вызывать «выход» в другом процессе. В этом случае обработка ошибок должна быть сделана путем установки process_flag(trap_exit, true) в процессе мониторинга, после чего вы можете получать сигналы выхода через стандартное выражение receive.

Обратите внимание, что специальный вид выхода, а именно exit(Pid, kill), завершит процесс без какой-либо возможности его перехватить. Другие процессы, связанные с Pid, должны получать сигнал вида {'EXIT', killed}.

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

6 голосов
/ 16 февраля 2010

Основной принцип в Erlang таков:

Сделайте его аварийным!

Я нашел весьма полезным избежать так называемого защитного программирования .Эта концепция более подробно объясняется на странице правил программирования Erlang:

http://www.erlang.se/doc/programming_rules.shtml#HDR11

Более того, даже если некоторые ошибки Erlang могут быть немного загадочными, хороший способиметь дело с след их!Трассировка в Эрланге довольно проста.Посмотрите этот краткий справочник:

http://aloiroberto.wordpress.com/2009/02/23/tracing-erlang-functions/

или просто обратитесь к официальной документации.

При этом я полностью согласен с @ jdupont.

3 голосов
/ 16 февраля 2010

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

API более высокого уровня - file:consult/1, где вы передаете имя файла и ожидаете, что содержимое будет снова проанализировано как термины Эрланга. Срединной точкой будет функция with-open-file, как это обычно бывает в lisp, когда вы передаете функцию, которая вызывается с дескриптором открытого файла в качестве аргумента.

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

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

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

3 голосов
/ 16 февраля 2010

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

Если вы знаете, что ничего не может быть сделано с конкретным исключением, то «fast fail».

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