Шаг 44.
Принципы исправления и анализа допущенных ошибок
На этом шаге мы укажем принципы исправления ошибок.
Ясно, что процесс отладки складывается из двух этапов: определения местонахождения ошибки
и последующего ее исправления.
Поговорим о принципах исправления ошибок по Майерсу[1]
- Там, где есть одна ошибка, вероятно, есть и другие. Другими словами,
ошибки имеют тенденцию группироваться. При исправлении ошибки проверьте ее непосредственное окружение:
нет ли здесь каких-нибудь подозрительных симптомов.
- Находите ошибку, а не ее симптом. Другим общим недостатком является устранение симптомов
ошибки, а не ее самой. Если предполагаемое изменение устраняет не все симптомы ошибки,
то она не может быть полностью выявлена.
- Вероятность правильного нахождения ошибки не равна 100%! С этим, безусловно,
соглашаются, но в процессе исправления ошибки часто наблюдается иная реакция (например "да, в большинстве
случаев это справедливо, но данная корректировка столь незначительна, что она правильна").
Можно утверждать, что корректировки более склонны к ошибкам, чем исходный текст программы. Подразумевается, что корректирующая программа должна тестироваться, возможно, даже более тщательно, чем исходная.
- Вероятность правильного нахождения ошибки уменьшается с увеличением объема программы. Это утверждение
формулируется по-разному. Эксперименты показали, что отношение числа неправильно найденных ошибок
к числу первоначально выявленных увеличивается для больших программ. В большой программе,
рассчитанной на широкое применение, каждая шестая вновь обнаруженная ошибка может быть
допущена при предшествующем внесении изменений в программу.
- Остерегайтесь внесения новой ошибки при корректировке. Необходимо рассматривать не
только неверные корректировки, но и те, которые кажутся верными, однако имеют нежелательный побочный
эффект и таким образом приводят к новым ошибкам. Другими словами, существует вероятность не
только того, что ошибка будет обнаружена неверно, но и того, что ее исправление приведет к
новой ошибке. Поэтому после проведения корректировки должно быть выполнено повторное тестирование,
позволяющее установить, не внесена ли новая ошибка.
Укажем один старый прием исправления ошибок, заключающийся в использовании так называемых заплат (Patch - заплата, вставка в программу).
Необходимость в "заплате" возникает, когда Вы хотите вставить последовательность новых операторов между двумя
операторами, которые мы обозначим О1 и О2. Организация заплаты происходит при помощи оператора
GOTO (тут мы отступаем от одного из основных принципов структурного программирования!):
О1;
Goto abc; {Переход на операторы "заплаты"}
abd:
О2;
. . . .
abc:
{Операторы "заплаты"}
Goto abd;
Удалить "заплату" - это значит включить операторы заплаты в основной текст программы,
расположив их там, где им надлежит находиться.
Интересная невыдуманная история с "заплатой" произошла на корабле "Аполлон", облетающем Луну.
Бортовая ЭВМ выдала сигнал тревоги и отказалась выполнять дальнейшие вычисления. Космонавты быстро
обнаружили, что неисправен аварийный датчик, дающий неправильный отсчет. Программист на Земле написал
текст "заплаты" для программы обработки аварийных сигналов, изменяющий ее так, чтобы конкретный
аварийный сигнал не считался аварийным. Эта "заплата" была написана прямо в кодах,
и необходимые изменения текста бортовой программы на машинном языке были продиктованы космонавтам по радио.
Программа с "заплатой" благополучно довела космонавтов до Земли.
Однако учтите, что система, состоящая из "заплаток", возникших при исправлении ошибок, редко
оказывается понятнее системы, которая с самого начала не имела ошибок (Дж.Фокс).
Качество работы каждого отдельного программиста существенно повышается, если выполняется детальный анализ
обнаруженных ошибок или, по крайней мере, их подмножества. Эта задача трудная и требующая
больших временных затрат, поскольку она подразумевает нечто большее, чем просто
поверхностную классификацию, такую, как "X% ошибок являются ошибками в логике" или "Y% ошибок встречается
в операторах IF". Тщательный анализ может включать в себя рассмотрение следующих вопросов.
- Когда была сделана ошибка? Данный вопрос является наиболее трудным, так как
ответ на него требует исследования документации. Однако это и наиболее интересный вопрос. Необходимо
точно определить первоначальную причину и время возникновения ошибки. Такой причиной
может быть, например, неясная формулировка в постановке задачи или коррекция предшествующей ошибки.
- Кто сделал ошибку?
- Какова причина ошибки? Недостаточно определить, когда и кем была сделана ошибка,
нужно также выяснить, почему она произошла. Была ли она вызвана чьей-то неспособностью писать ясно,
непониманием отдельных конструкций языка программирования, ошибкой при печатании на машинке, неверным предположением,
отсутствием рассмотрения недопустимых входных данных?
- Как ошибка могла быть предотвращена? Ответ на этот вопрос наиболее ценен, так
как позволяет осмыслить и количественно обосновать накапливаемый опыт проектирования.
- Почему ошибка не была обнаружена ранее?
- Как ошибка могла быть определена ранее? Ответ на этот вопрос является другим примером
полезной обратной связи. Как могут быть улучшены процессы обзора и тестирования для более раннего
нахождения этого типа ошибок в будущих проектах?
- Как была найдена ошибка? При условии, что мы рассматриваем только ошибки,
которые обнаружены с помощью теста, необходимо выяснить, как был написан удачный тест. Почему
этот тест был удачным? Можем ли мы что-нибудь почерпнуть из него для написания других удачных тестов с
целью проверки данной программы или будущих программ?
Такой анализ, конечно, является сложным процессом, но его результаты могут оказаться полезными для дальнейшего
улучшения работы программиста. Поэтому вызывает опасения тот факт, что подавляющее большинство программистов
его не используют!
(1) Майерс Г. Искусство тестирования программ. - М.: Финансы и статистика, 1982.
Со следующего шага мы начнем рассматривать основные понятия структурного программирования.
Предыдущий шаг
Содержание
Следующий шаг