Файл: Руководство по стилю программирования и конструированию по.pdf
ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 30.11.2023
Просмотров: 837
Скачиваний: 2
ВНИМАНИЕ! Если данный файл нарушает Ваши авторские права, то обязательно сообщите нам.
СОДЕРЖАНИЕ
какой код был изменен недавно. Если это невозможно, используйте для сравне- ния старого работоспособного и нового дефектного кода другой инструмент.
Расширьте подозрительный фрагмент кода Сосредоточиться на небольшом фрагменте кода легко, но это принесет пользу, только если дефект
наверняка
содержится в этом фрагменте. Если дефект не удается найти в конкретной обла- сти кода, рассмотрите вероятность того, что его в ней нет. Расширьте подозри- тельную область кода и проанализируйте ее, применив описанную выше методи- ку двоичного поиска.
Перекрестная ссылка О коде,
подверженном ошибкам, см.
также подраздел «Выполняйте рефакторинг модулей, подвер- женных ошибкам» раздела 24.5.
536
ЧАСТЬ V Усовершенствование кода
Выполняйте интеграцию инкрементно Отладка будет легкой, если вы будете добавлять элементы в систему по од- ному за раз. Если после добавления нового элемента возникла новая ошибка, удалите его и протестируйте отдельно.
Проверяйте наличие распространенных дефектов Размышляя о возможных дефектах, используйте контрольные списки качества кода. Следуя методикам ин- спекций (см. раздел 21.3), вы создадите улучшенные контрольные списки проблем,
характерных для вашей среды. Вы также можете использовать контрольные спис- ки, приведенные в этой книге. Все они перечислены после содержания книги.
Обсудите проблему с кем-то другим Некоторые про- граммисты называют это «отладочной исповедью». Довольно часто дефект в своем коде можно найти при объяснении его другому человеку. Так, объясняя проблему с неверной сорти- ровкой фамилий, вы могли бы сказать что-нибудь подобное:
Привет, Дженифер, у тебя есть свободная минутка? У меня
проблема. Вот этот список сотрудников должен быть отсортирован, но не-
которые фамилии выводятся в неверном порядке. Однако во второй раз они
сортируются правильно. Чтобы узнать, не связана ли проблема с вводом но-
вых фамилий, я добавил несколько новых записей, но все они были выведены
правильно. Я знаю, что список должен быть отсортирован уже при первом
запуске программы, потому что фамилии сортируются дважды: при вводе и
при сохранении… подожди… нет, при вводе они не сортируются. Все верно. При
вводе их место в списке определяется лишь приблизительно. Спасибо, Джени-
фер, ты мне очень помогла.
Дженифер не сказала ни слова, но вы нашли решение проблемы!
Отдохните от проблемы Иногда чрезмерная концентрация на проблеме ме- шает думать. Помните, как вы решили сделать перерыв на чашку кофе и нашли ре- шение проблемы на пути к кофейному автомату? Или во время обеда? Или по пути домой? Или принимая душ следующим утром? Если, попробовав все варианты, вы не получили никаких результатов, отдохните. Прогуляйтесь. Поработайте над чем- то другим. Возьмите выходной. Пусть проблемой займется ваше подсознание.
Дополнительная выгода временного отдыха от проблемы состоит в том, что он снижает связанную с отладкой тревогу. Приступ беспокойства — явный признак того, что пора сделать перерыв.
Отладка методом грубой силы
При отладке этот способ часто игнорируют. Под «методом грубой силы» я пони- маю подход, который может оказаться нудным, трудным и длительным, но
непре-
менно приведет к решению проблемы. Какие именно подходы непременно при- ведут к решению проблемы? Это зависит от ситуации, но некоторые типичные варианты назвать можно:
쐽
полный обзор проекта и/или кода дефектного фрагмента;
쐽
выбрасывание фрагмента кода и его повторное проектирование/кодирование с нуля;
Перекрестная ссылка Обраще- ние за помощью к коллегам иногда помогает рассмотреть проблему под другим углом зрения (см. раздел 21.1).
Перекрестная ссылка Об инте- грации см. главу 29.
ГЛАВА 23 Отладка
537
쐽
выбрасывание всей программы и ее повторное проектирование/кодирование с нуля;
쐽
компиляция кода с полной отладочной информацией;
쐽
компиляция кода на самом строгом уровне диагностики и исправление всех предупреждений компилятора;
쐽
блочное тестирование нового кода в изоляции от других фрагментов;
쐽
создание и выполнение набора автоматизированных тестов;
쐽
пошаговое выполнение крупного цикла в отладчике вплоть до возникновения ошибки;
쐽
включение в код команд печати, вывода информации на экран или других команд регистрации данных об ошибке;
쐽
компиляция кода с использованием другого компилятора;
쐽
компиляция и выполнение программы в другой среде;
쐽
компоновка кода со специальными библиотеками или выполнение кода в сре- дах, генерирующих предупреждения в подозрительных ситуациях;
쐽
полное воспроизведение конфигурации компьютера конечного пользователя;
쐽
интеграция нового кода в систему небольшими фрагментами с полным тес- тированием каждого фрагмента.
Установите лимит времени для быстрой и грязной отладки Рассматри- вая тот или иной метод грубой силы, вы вполне можете решить «Я не могу пойти на это — слишком много работы!» Однако слишком большим можно считать только тот объем работы, который требует больше времени, чем то, что я называю «бы- строй и грязной отладкой». Мало кому хочется методично анализировать весь код до тех пор, пока дефекту больше негде будет деться, — всегда есть соблазн быст- ро угадать причину проблемы. Игрок, живущий в каждом из нас, скорее выбрал бы рискованный подход, позволяющий обнаружить дефект за пять минут, а не надежную методику, непременно приводящую к нахождению дефекта за полчаса.
Однако это рискованное дело: если пятиминутный подход не работает, вы начи- наете упрямиться. Обнаружение дефекта «легким» способом становится делом принципа, и вы впустую тратите часы, а потом дни, недели, месяцы… Как часто вы тратили два часа на отладку кода, на написание которого уходило только 30
минут? Такое распределение времени трудно признать разумным, и вам следова- ло бы не отлаживать плохой код, а вообще переписать его.
Если вы все же решаете попробовать быстрый способ отладки, ограничьте его применение определенным интервалом времени. По истечении этого срока сми- ритесь с тем, что дефект не так прост, как вам казалось сначала, и используйте трудный путь. Так вы сможете быстро избавляться от простых дефектов, а исправ- ление сложных будет чуть более долгим.
Составьте список методик грубой силы До начала отладки сложной ошибки спросите себя: «Есть ли какой-нибудь способ, который
непременно приведет к решению этой проблемы, если при ее отладке я зайду в тупик?» Если вы опреде- лите хотя бы один такой способ (пусть даже переписывание дефектного кода!),
вероятность того, что вы впустую потратите лишние часы или дни, уменьшится.
538
ЧАСТЬ V Усовершенствование кода
Синтаксические ошибки
Синтаксические ошибки ждет судьба мамонтов и саблезубых тигров. Диагности- ческие модули компиляторов постоянно улучшаются, и времена, когда поиск не- правильно расположенной точки с запятой иногда занимал несколько часов, по- чти ушли. Соблюдение следующих принципов поможет вам ускорить вымирание подобных ошибок.
Не полагайтесь на номера строк в сообщениях компилятора Если ком- пилятор сообщил о загадочной синтаксической ошибке, изучите фрагменты, рас- положенные прямо перед ошибкой и сразу после нее: возможно, компилятор неправильно понял проблему или просто включает плохой диагностический модуль. Обнаружив истинный дефект, попробуйте определить, почему компиля- тор указал не на ту команду. Понимание особенностей компилятора поможет находить дефекты в будущем.
Не доверяйте сообщениям компилятора Компиляторы пытаются сообщить вам точную причину ошибки, но они сами нередко ошибаются, и, чтобы понять смысл их сообщений, иногда приходится читать между строк. Так, при целочис- ленном делении на 0 компилятор UNIX C может вывести сообщение «floating exception» (исключение при выполнении операции над числом с плавающей точ- кой). Используя Standard Template Library C++, можно получить пару сообщений об ошибке: первое — о действительной ошибке в использовании STL, а второе —
«Error message too long for printer to print; message truncated» («Сообщение об ошибке сокращено, так как оно слишком велико для печати»). Наверное, вы и сами може- те привести массу примеров неверных сообщений об ошибках.
Не доверяйте второму сообщению компилятора Одни компиляторы нахо- дят множественные ошибки лучше, а другие хуже. Обнаружив первую ошибку,
некоторые компиляторы приходят в такое возбуждение, что выдают десятки бес- смысленных сообщений о других ошибках. Другим компиляторам, более рассу- дительным, тоже нравится находить ошибки, но они воздерживаются от вывода неверных сообщений. Если ваш компилятор сгенерировал ряд сообщений об ошибках и вы не можете быстро найти причину второго или третьего сообще- ния, не волнуйтесь — исправьте первую ошибку и перекомпилируйте программу.
Разделяй и властвуй Разделение программы на части особенно эффективно при поиске синтаксических ошибок. Если вы столкнулись с неуловимой синтаксичес- кой ошибкой, удалите часть кода и перекомпилируйте программу. Ошибка или ис- чезнет (следовательно, она содержится в удаленном коде), или снова появится во всей своей красе (в этом случае удалите другую часть кода). Кроме того, вы можете получить другое сообщение об ошибке (это значит, что вы перехитрили компиля- тор и заставили его сгенерировать более разумное сообщение).
Грамотно ищите неверно размещенные комментарии
и кавычки Многие текстовые редакторы для программи- рования автоматически форматируют комментарии, стро- ковые литералы и другие синтаксические элементы. В бо- лее примитивных средах неправильное размещение симво- лов комментария или кавычек может запутать компилятор.
Перекрестная ссылка Наличие редакторов с проверкой синтак- сиса зависит от зрелости сре- ды программирования (см. раз- дел 4.3).
ГЛАВА 23 Отладка
539
Для нахождения лишних символов комментария или кавычек в коде C, C++ или
Java вставьте в него последовательность:
/*”/**/
Этот фрагмент завершит комментарий или строку, что поможет сузить область, в которой скрываются лишние символы.
23.3. Устранение дефекта
Сложной частью отладки является поиск дефекта. Устранить его легко. Однако, как часто бывает, из-за этой самой легкости устранение одних дефектов создает бла- гоприятные условия для внесения других. По крайней мере в одном исследова- нии было обнаружено, что первые варианты исправления дефектов в половине случаев оказывались некорректными (Yourdon, 1986b). Ниже я привел несколько советов по снижению вероятности ошибок этого рода.
Прежде чем браться за решение проблемы, поймите ее «Руковод- ство Дьявола по отладке» не врет: нет более эффективного способа усложнить себе жизнь и ухудшить качество программы, чем исправле- ние дефектов без их настоящего понимания. Приступайте к устранению пробле- мы, только разобравшись в ней до конца. Триангулируйте источник ошибки с при- менением двух видов тестов: тех, что должны привести к ошибке, и тех, которые должны выполниться безошибочно. Выполняйте тесты, пока не поймете пробле- му достаточно хорошо, чтобы правильно предсказывать появление ошибки в каж- дом случае.
Не ограничивайтесь пониманием проблемы — поймите программу Если вы понимаете контекст проблемы, у вас больше шансов решить ее полностью, а не частично. Исследование, проведенное с использованием короткой программы,
показало, что программисты, стремящиеся полностью понять поведение програм- мы, чаще изменяли ее правильно, чем программисты, концентрировавшиеся на локальном поведении и изучавшие программу только по мере надобности (Littman et al., 1986). Так как программа в этом исследовании была небольшой (280 строк),
я не могу утверждать, что вам следует пытаться полностью понять программу из
50 000 строк перед исправлением дефекта. Но вы должны понять хотя бы код,
расположенный по соседству с дефектом — под «соседством» я понимаю не
не-
сколько, а несколько сотен строк.
Подтвердите диагноз проблемы Перед исправлением дефекта убедитесь, что вы диагностировали проблему правильно. Выполните тесты, которые доказыва- ют вашу гипотезу и опровергают конкурирующие гипотезы. Если вы установили только то, что ошибка может быть результатом одной из нескольких причин, к устранению проблемы приступать рано — исключите сначала другие причины.
Расслабьтесь Один программист собирался в лыжный поход. Программа была почти готова к выпуску, он опазды- вал, и ему оставалось исправить только один дефект. Он из- менил исходный файл и зарегистрировал его в системе управления версиями. Он не выполнил перекомпиляцию программы и не проверил правильность изменения.
Никогда не отлаживайте про- грамму стоя.
Джеральд Вайнберг
(Gerald Weinberg)
540
ЧАСТЬ V Усовершенствование кода
А изменение оказалось неверным, что привело начальника программиста в ярость.
Как можно изменять код приложения, готового к выпуску, не проверив его? Что может быть хуже? Разве это не верх некомпетентности?
Если такой поступок и не является вершиной некомпетентности, он очень к ней близок, но это нисколько не сказывается на его распространенности. Решение проблемы второпях — один из самых неэффективных в плане времени подходов.
Он подталкивает к необоснованным суждениям, неполной диагностике дефектов и внесению неполных исправлений. Принимая желаемое за действительное, вы можете увидеть решение там, где его нет. Давление — часто самовнушенное — скло- няет к принятию случайных и непроверенных решений методом проб и ошибок.
А вот другой подход. В самом конце разработки ОС Microsoft Windows 2000 одно- му из программистов нужно было исправить последний дефект, после чего уже мож- но было бы создать коммерческую версию. Он изменил код, проверил исправле- ние и протестировал его на своей локальной сборке. Но сразу регистрировать ис- правление в системе управления версиями он не стал. Вместо этого он пошел иг- рать в баскетбол, сказав: «Я сейчас чувствую слишком большое напряжение и по- этому не могу быть уверен в том, что рассмотрел все, что следовало. Часок отдох- ну, приведу мысли в порядок, а потом вернусь и зарегистрирую код, как только увижу,
что мое исправление на самом деле корректно».
Отдыхайте, пока правильность решения не станет очевидной. Не поддавайтесь соблазну сэкономить время: обычно это приводит к обратному результату. Сле- дуя этим советам, вы всегда будете вносить правильные исправления, и руково- дителю не придется вызывать вас из лыжного похода.
Сохраняйте первоначальный исходный код Перед на- чалом исправления дефекта обязательно заархивируйте имеющийся код, чтобы в случае чего к нему можно было вернуться. Имея дело с несколькими изменениями, вы мо- жете забыть, какое из них важно в текущий момент. Сохра- нение первоначального исходного кода позволит хотя бы сравнить старый и но- вый файлы и определить измененные фрагменты.
Устраняйте проблему, а не ее симптомы Конечно, симптомы также нужно устранять, но главной целью должно быть устранение причин проблемы. До кон- ца не разобравшись в проблеме, кода не исправить. Вы устраните симптомы и сделаете код еще хуже. Рассмотрим, например, фрагмент:
Пример кода, требующего исправления (Java)
for ( claimNumber = 0; claimNumber < numClaims[ client ]; claimNumber++ ) {
sum[ client ] = sum[ client ] + claimAmount[ claimNumber ];
}
Предположим, величина
sum для клиента 45 отличается от правильного значения на 3,45 доллара. Вот неверный способ решения этой проблемы:
Перекрестная ссылка Общие вопросы, связанные с измене- нием кода, подробно обсужда- ются в главе 24.