Чтение онлайн

на главную - закладки

Жанры

Программист-прагматик. Путь от подмастерья к мастеру
Шрифт:

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

Подсказка 32: Пусть аварийное завершение работы программы произойдет как можно раньше

Аварийное завершение не означает "отправить в корзину для мусора"

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

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

То же самое можно реализовать и на других языках программирования. Если механизм исключения отсутствует или библиотеки не возбуждают исключения, то убедитесь в том, что можете обрабатывать ошибки самостоятельно. В языке С для этого весьма полезны макрокоманды:

#define CHECK(LINE, EXPECTED) \

 {int rc = LINE; \

if (rc!= EXPECTED) \

ut_abort(_FILE_, _LINE_, #LINE, rc, EXPECTED); }

void ut_abort(char *file, int In, char *line, int rc, int exp) {

fprintf(stderr, "%s line %d\n'%s': expected %d, got %d\n", file, In, line, exp, rc);

exit(1);

}

Тогда вы можете инкапсулировать вызовы, которые никогда подведут, с помощью строки:

CHECK(stat("/tmp", &stat_buff), 0);

Если бы это не удалось, то вы бы получили сообщение, записанное в stderr:

source.c line 19

"stat("/tmp", &stat_buff)' : expected 0, got -1

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

Другие разделы, относящиеся к данной теме:

• Проектирование по контракту

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

23

Программирование утверждений

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

Оскар Уайльд, Портрет Дориана Грея

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

"Этого никогда не случится…"

И далее: "Через 30 лет эта программа использоваться не будет, так что для обозначения года хватит и двух разрядов". "Нужна ли интернационализация, если это приложение не будет использоваться за рубежом?" "Счетчик не может принимать отрицательное значение". "Этот оператор printf не дает сбоев".

Не стоит заниматься подобного рода самообманом, особенно при написании программ.

Подсказка 33: Если что-либо не может произойти, воспользуйтесь утверждениями, которые гарантируют, что это не произойдет вовсе

Всякий раз, когда вы начинаете думать "Ну конечно, такого просто не может произойти", проверяйте это высказывание с помощью программы. Самый простой способ осуществить это – использовать утверждения. В большинстве реализаций языков С и С++ имеется некоторая разновидность макроса assert или _assert, который осуществляет проверку логического условия. Эти макрокоманды могут представлять огромную ценность. Если указатель, передаваемый к вашей процедуре, ни в коем случае не должен принимать значение NULL, то проверьте выполнение этого условия:

void writeString(char *string) {

assert(string != NULL);

...

Утверждения представляют собой весьма полезное средство проверки работы алгоритма. Например, вы написали умный алгоритм сортировки. Проверьте, работает ли он:

For (int i=0; i<num_entries-1; i++) {

assert(sorted[i] <= sorted[i+1]);

}

Конечно, условие, переданное утверждению, не должно оказывать побочного воздействия (см. врезку "Утверждения и побочные эффекты"). Необходимо также помнить, что утверждения могут отключаться во время компиляции – не помещайте в макрос assert программу, которая должна быть выполнена. Утверждения не должны использоваться вместо реальной обработки ошибок. Они лишь осуществляют проверку того, что никогда не должно произойти; вы же не хотите писать программу, подобную приведенной ниже:

printf("Enter 'Y' or 'N': ");

ch = getchar

assert((ch=='Y')||(ch=='N')); /* дурной тон! */

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

Не отключайте утверждения

Существует расхожее недопонимание утверждений, которое провозгласили те, кто разрабатывает компиляторы и языковые среды. Оно формулируется примерно так:

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

Поделиться:
Популярные книги

Возвращение

Кораблев Родион
5. Другая сторона
Фантастика:
боевая фантастика
6.23
рейтинг книги
Возвращение

Лейтенант. Назад в СССР. Книга 8. Часть 1

Гаусс Максим
8. Второй шанс
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Лейтенант. Назад в СССР. Книга 8. Часть 1

Лекарь Империи 5

Карелин Сергей Витальевич
5. Лекарь Империи
Фантастика:
городское фэнтези
аниме
героическая фантастика
попаданцы
5.00
рейтинг книги
Лекарь Империи 5

Последний Паладин. Том 13

Саваровский Роман
13. Путь Паладина
Фантастика:
городское фэнтези
попаданцы
аниме
5.00
рейтинг книги
Последний Паладин. Том 13

Черный Маг Императора 26

Герда Александр
26. Черный маг императора
Фантастика:
аниме
сказочная фантастика
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Черный Маг Императора 26

Ее андалузский друг

Содерберг Александр
1. София Бринкман
Детективы:
прочие детективы
5.00
рейтинг книги
Ее андалузский друг

Инженер Петра Великого 4

Гросов Виктор
4. Инженер Петра Великого
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Инженер Петра Великого 4

Печать Пожирателя

Соломенный Илья
1. Пожиратель
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Печать Пожирателя

Лондон

Резерфорд Эдвард
The Big Book
Проза:
историческая проза
6.67
рейтинг книги
Лондон

Кодекс Крови. Книга II

Борзых М.
2. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга II

Пески веков (сборник)

Уиндем Джон Паркс Лукас Бейнон Харрис
1970. Зарубежная фантастика
Фантастика:
научная фантастика
5.00
рейтинг книги
Пески веков (сборник)

Имперец. Том 1 и Том 2

Романов Михаил Яковлевич
1. Имперец
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Имперец. Том 1 и Том 2

Газлайтер. Том 20

Володин Григорий Григорьевич
20. История Телепата
Фантастика:
боевая фантастика
аниме
попаданцы
5.00
рейтинг книги
Газлайтер. Том 20

Хозяин Теней 5

Петров Максим Николаевич
5. Безбожник
Фантастика:
аниме
фэнтези
фантастика: прочее
попаданцы
5.00
рейтинг книги
Хозяин Теней 5