Пособие по практике программирования


         

Пример 6.4








Что будет делать эта функция, если n будет равно 0? Массив, не содержащий элементов, — вполне осмысленный элемент программы, а вот среднее значение его элементов не имеет никакого смысла. Должна ли функция позволять системе отлавливать деление на 0? Прерывать функцию? Сообщать об ошибке? Без предупреждения возвращать какое-нибудь нейтральное значение? А что если n вообще отрицательно, что абсолютно бессмысленно, но не невозможно? Как мы уже говорили в главе 4, нам представляется правильным в случае, если n меньше либо равно нулю, возвращать 0 в качестве среднего значения:

return n <= 0 ? 0.0

но однозначно правильного ответа здесь не*существует.

Имеется, правда, гарантированно неверное мнение — игнорировать проблему. В ноябре 1998 в журнале Scientific American был описан инцидент, произошедший на борту американского ракетного крейсера Yorktown. Член команды по ошибке вместо значимого числа ввел 0, что привело к ошибке деления на нуль; ошибка разрослась и в конце концов силовая установка корабля оказалась выведена из строя. Несколько часов Yorktown дрейфовал по воле волн — а все из-за того, что в программе не была осуществлена проверка диапазона вводимых значений.

Используйте утверждения. В С и C++ существует возможность использования специального щ механизма утверждений (assertions) (в <assert. h>), который позволяет включать в программу проверку пред- и постусловий. Поскольку невыполненное утверждение прерывает работу программы, используют их, как правило, в ситуациях, когда сбой на самом деле не ожидается, а при его возникновении нет возможности продолжить работу нормально. Только что рассмотренный пример можно было бы дополнить утверждением, вставленным перед началом цикла:

assert(n > 0);

Если утверждение не выполнено, программа прерывается; сопровождается это выдачей стандартного сообщения:

Assertion failed: n > О,
file avgtest.с, line 7
Abort(crash)

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

Используйте подход защитного программирования. Полезно вставлять некоторый код для обработки (хотя бы просто предупреждения пользователю) случаев, которых "не может быть никогда", то есть ситуаций, которые теоретически не должны случиться, но все же имеют место (например, из-за сбоя где-то в другом участке программы). Хороший пример — добавление проверки на нулевой или отрицательный размер массива в функцию avg. Еще одним примером может стать программа, выставляющая оценки по американской системе; очевидно, что отрицательных или очень больших значений появиться в ней не может, но лучше все же это проверить:




Содержание  Назад  Вперед