Ошибка — недостаток программы, проявляющийся в том, что она работает не так, как задумал программист или как ожидают пользователи. То же: error.
Все ошибки можно разделить (условно) на 4 типа:
Это те ошибки, которые ловит компилятор и которые, таким образом, нарушают некоторые важные для компилятора принципы. Типичный пример — синтаксическая ошибка.
$ echo '-mmodule(hello).' > hello.erl && erlc hello.erl
hello.erl:1:2: no module definition
% 1| -mmodule(hello).
% | ^
Это ошибки, вызванные плохо проработанной моделью происходящего в программе. В частности, плохой организацией архитектуры программы или игнорированием всех возможных случаев. Некоторые логические ошибки бывают очень тонкими и можно буквально часами не понимать, почему ты нажимаешь на кнопку, а ожидаемый эффект не наступает.
Часто логические ошибки бывают просто следствием невнимательности программиста. Допустим, он разрабатывает игру, в которой выбрасываются два игральных кубика и в зависимости от суммы на кубиках наступает то или иное игровое действие. Программисту может показаться, что сумма будет в диапазоне от 1 до 12, и к числу 1 он привяжет какое-либо действие. Это действие, конечно, никогда не наступит. Скорее всего, программист рано или поздно заметит такую ошибку (по тому, что какое-то событие в принципе не наступает).
Но может быть и более тонкая, смысловая ошибка, связанная с тем, что программист не владеет даже азами комбинаторики и теории вероятности. Он, например, может подумать (продолжаем пример с кубиками), что все числа от 2 до 12 выпадают с одинаковой вероятностью. Это, конечно, не так, но бот в игре будет опираться на эту модель и поэтому будет систематически ошибаться.
Могут быть и другого рода “научные ошибки”, вызванные, например, непониманием математической статистики, законов физики, юридических законов — вплоть до орфографических ошибок. Некоторые такие ошибки наглядны и легко выявляются — следует лишь дождаться обратной связи от пользователей.
Но некоторые логические ошибки очень сложно отлавливать. Поэтому лучше сразу опираться на стройную, хорошо продуманную модель происходящего в программе и не ждать, что ошибки потом себя всё равно проявят.
В тот или иной момент происходит крушение программы, вызванное тем, что дальше невозможно выполняться в штатном режиме — возникает исключительная ситуация. Например, с помощью знака равно мы пытаемся сопоставить атом и число или вдруг делим на ноль. После этого программа выбрасывает исключения — она споткнулась и дальше не может исполняться штатно.
1> odin = 1.
** exception error: no match of right hand side value 1
2> 5 / 0.
** exception error: an error occurred when evaluating
an arithmetic expression
in operator '/'/2
called as 5 / 0
То, что программа столкнулась с исключительной ситуацией (“споткнулась”), не значит, что всё пропало, что теперь программу надо запускать заново. Во-первых, мы можем поддержать нашу программу тем, что заранее предусмотрительно выдадим ей “костыли” в виде обработки исключений. Во-вторых, раз мы программируем на Эрланге, у нас может быть много-много разных акторов, и то, что в одном из них вдруг возникла проблема, совсем не повод для того, чтобы ронять всю Систему.
Джо Армстронг написал и защитил диссертацию под названием “Создание надёжных распределённых систем при наличии программных ошибок”. Один из тезисов, который он в ней отстаивает, — для создания надёжной системы не надо обрабатывать ошибки локально. Надо дать актору рухнуть, а потом уже — в зависимости от ситуации — что-то уже делать с этим.
Ошибки времени исполнения возникают с надписью: exception error: ...
. Если мы желаем сами смоделировать такого рода ошибку — с произвольной причиной, — то можем вызвать error(Причина)
.
5> error("Too many candies").
** exception error: "Too many candies"
Те, которые вызываются преднамеренно. Если программист опасается, что что-то может пойти не так, он может добавить в код вызов throw/1 или exit/1.
1> throw("Bad").
** exception throw: "Bad"
2> exit("Very bad").
** exception exit: "Very bad"
Как мы видим, в одном случае в оболочке возникает сообщение exception throw...
, а в другом случае — exception exit...
.
© Алексей Карманов, 2024.