Читаем Программист-прагматик полностью

Приходилось ли вам замечать, что иногда, еще до того как вы осознаете проблему, ее признаки обнаруживают посторонние люди? То же самое применимо и к программам других разработчиков. Если в одной из наших программ что-то начинает идти не так, как надо, в ряде случаев первой это «заметит» библиотечная подпрограмма. Возможно, паразитный указатель заставил нас записать в дескриптор файла какие-то бессмысленные символы. При следующем обращении к read это будет обнаружено. Возможно, что переполнение буфера привело к уничтожению счетчика, который мы собирались использовать для определения объема назначаемой памяти. Возможно, причиной сбоя окажется malloc. Логическая ошибка в одном из нескольких миллионов операторов, находящихся в тексте перед оператором выбора, означает, что его селектор больше не примет значение 1, 2 или 3. Мы берем случай default (который является одной из причин того, почему любой оператор выбора должен иметь значение по умолчанию), мы хотим знать, в какой момент произошло невозможное).

Легко поддаться умонастроению «этого не может быть, потому что не может быть никогда». Большинство из нас создавало программы, которые не проверяют, успешно ли завершилась операция закрытия файла и правильно ли записан оператор трассировки. И все сводилось к одному (к тому, что мы и так знали) – рассматриваемая программа не откажет, если будет работать в нормальных условиях. Но мы пишем программы с осторожностью. Мы ищем инородные указатели в других частях нашей программы, очищая стек. Мы выясняем, какие версии библиотек совместного пользования загружались в действительности.

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


Подсказка 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

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

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

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

Все книги серии Библиотека программиста

Программист-фанатик
Программист-фанатик

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

Чед Фаулер

Программирование, программы, базы данных / Программирование / Книги по IT

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C++: базовый курс
C++: базовый курс

В этой книге описаны все основные средства языка С++ - от элементарных понятий до супервозможностей. После рассмотрения основ программирования на C++ (переменных, операторов, инструкций управления, функций, классов и объектов) читатель освоит такие более сложные средства языка, как механизм обработки исключительных ситуаций (исключений), шаблоны, пространства имен, динамическая идентификация типов, стандартная библиотека шаблонов (STL), а также познакомится с расширенным набором ключевых слов, используемым в .NET-программировании. Автор справочника - общепризнанный авторитет в области программирования на языках C и C++, Java и C# - включил в текст своей книги и советы программистам, которые позволят повысить эффективность их работы. Книга рассчитана на широкий круг читателей, желающих изучить язык программирования С++.

Герберт Шилдт

Программирование, программы, базы данных
Programming with POSIX® Threads
Programming with POSIX® Threads

With this practical book, you will attain a solid understanding of threads and will discover how to put this powerful mode of programming to work in real-world applications. The primary advantage of threaded programming is that it enables your applications to accomplish more than one task at the same time by using the number-crunching power of multiprocessor parallelism and by automatically exploiting I/O concurrency in your code, even on a single processor machine. The result: applications that are faster, more responsive to users, and often easier to maintain. Threaded programming is particularly well suited to network programming where it helps alleviate the bottleneck of slow network I/O. This book offers an in-depth description of the IEEE operating system interface standard, POSIX (Portable Operating System Interface) threads, commonly called Pthreads. Written for experienced C programmers, but assuming no previous knowledge of threads, the book explains basic concepts such as asynchronous programming, the lifecycle of a thread, and synchronization. You then move to more advanced topics such as attributes objects, thread-specific data, and realtime scheduling. An entire chapter is devoted to "real code," with a look at barriers, read/write locks, the work queue manager, and how to utilize existing libraries. In addition, the book tackles one of the thorniest problems faced by thread programmers-debugging-with valuable suggestions on how to avoid code errors and performance problems from the outset. Numerous annotated examples are used to illustrate real-world concepts. A Pthreads mini-reference and a look at future standardization are also included.

David Butenhof

Программирование, программы, базы данных