Следуйте этому руководству и берегите нервы.

Моя философия отладки

Я верю в три вещи:

1. Ничего личного

Забудьте об авторстве кода. Вы можете считать себя художником, но даже великие художники делали много ерунды. У всех код ерундовый, то есть мой код — ерунда, и ваш тоже. Смиритесь с этим. Если есть проблема, то первой мыслью должно быть «с моим ерундовым кодом что-то не так». Так вы не будете считать виновным Perl. Ничего личного.

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

2. Личная ответственность

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

3. Подход нужно менять

Исправьте всё, чтобы не встретиться снова с такой же проблемой. Возможно, она в том, как вы программируете, а не в том, что. Поменяйте подход, чтобы облегчить свою жизнь. Не заставляйте Perl подстроиться под вас, потому что он этого не сделает. Подстройтесь под Perl. Это просто язык, а не образ жизни.

Мой метод

Компилируется ли ваш скрипт в строгом режиме?

Если вы не используете строгий режим, включите его. Perl-гуру являются гуру оттого, что используют strict, это позволяет решать другие задачи, изучать новые штуки и загружать работающие модули на CPAN.

Строгий режим включается прагмой strict:

use strict;

Из командной строки это можно сделать, используя опцию -M:

perl -Mstrict script.pl

После этого perl может докучать вам, но спустя пару недель программирования в строгом режиме ваш код станет лучше, меньше времени уйдет на отлавливание простых ошибок, а, быть может, отпадет надобность в этом руководстве.

Что за предупреждение?

Perl предупредит о многих подозрительных конструкциях. Включите предупреждения и помогите Perl помочь вам.

Используйте параметр -w в строке с интерпретатором:

#!/usr/bin/perl -w

Вы можете включить предупреждения из командной строки:

perl -w script.pl

Вы можете использовать лексические предупреждения со всякими интересными возможностями (подробности — в perldoc warnings).

use warnings;

Если предупреждения непонятны, посмотрите подробную версию в perldoc perldiag или используйте прагму diagnostics:

use diagnostics;

Решите сперва первую проблему!

Как только perl выдал вам сообщения об ошибках или предупреждения, устраните первое, а потом посмотрите, выдаются ли остальные сообщения — первая проблема и может быть их причиной.

Посмотрите на код перед строкой, на которую ссылается сообщение об ошибке!

Perl выдает предупреждения после того, как ощутит беспокойство, но не до этого. К тому времени, как perl обеспокоен, проблема уже возникла, и perl, на самом деле, находится уже после проблемы. Взгляните на пару выражений до строки под номером, указанным в предупреждении.

То ли здесь значение, какое вы думаете?

Не гадайте! Проверьте значение до того, как использовать его в выражении. Лучший отладчик в мире — print.

print STDERR "Значение --- [$value]\n";

Я заключаю $value в скобки, чтобы видеть все пробелы или переводы строк в начале или в конце.

Если я имею дело с чем-то помимо скаляра, я использую для вывода структур Data::Dumper.

require Data::Dumper;
print STDERR "Хеш --- ", Data::Dumper::Dumper( %hash ), "\n";

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

Также можете использовать встроенный отладчик perl, запустив perl с опцией -d. Детали — в perldoc perldebug.

perl -d script.pl

Еще есть другие отладчики или среды разработки вроде ptkdb (графический отладчик, основанный на Tk) или Komodo (IDE ActiveState, основанная на Mozilla).

Верно ли используете функции?

Я программирую на Perl довольно давно, но всё еще заглядываю в perldoc perlfunc чуть ли не каждый день. Что-то я просто не могу упомнить, а иногда по недосыпу силы меня покидают, и непонятно, почему sprintf() не печатает на экране.

Отыскать отдельную функцию с командой perldoc можно при помощи опции -f:

perldoc -f имя_функции

Если используете модуль, загляните в документацию, чтобы убедиться, что используете его правильно. Это делается с perldoc:

perldoc Имя::Модуля

Используете ли верные специальные переменные?

Опять же, я всё время обращаюсь к perldoc perlvar. Нет, не так часто, с тех пор как нашел более удобной книжку «Perl Pocket Reference».

У вас нужная версия модуля?

Некоторые модули меняют поведение от версии к версии. У вас та версия модуля, о которой вы думаете? Вы можете узнать последнюю версию таким однострочником perl:

perl -MИмя::Модуля -le 'print Имя::Модуля->VERSION';

Если вы смотрите большинство документации не на локальной машине, а на http://www.perldoc.com/ или http://search.cpan.org/, то, вероятнее всего, вы найдете различия в версиях текстов.

Вы сделали небольшой тестовый пример?

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

Проверили переменные окружения?

Некоторые вещи зависят от переменных окружения. Вы уверены, что они заданы верно? Ваша среда совпадает с той, в которой работает программа? Помните, что CGI-программы или задачи cron могут видеть среды, отличающиеся (особенно на различных машинах) от той, что доступна из интерактивной оболочки.

Perl хранит переменные окружения в %ENV. Если вам нужна одна из этих переменных, будьте готовы указать значение по умолчанию, если переменная не существует, даже на время тестирования.

Если проблема еще есть, проверьте переменные окружения:

require Data::Dumper;
print STDERR Data::Dumper::Dumper( \%ENV );

Смотрели в Google?

Если у вас есть проблема, то, возможно, у кого-то возникала такая же. Посмотрите в Google Groups, писал ли кто нибудь об этом в comp.lang.perl.misc. Разница между людьми, задающими вопросы в USENET и отвечающими на них — в умении эффективно искать по Google Groups.

Профайлер использовали?

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

Какой тест не работает?

Если у вас есть набор тестов, то какой тест не срабатывает? Вы должны быть способны очень быстро найти ошибку, так как каждый тест исполняет лишь малую часть кода.

Если набора тестов нет, почему бы его не сделать? Я не прошу вас писать пару тестов, если скрипт по-настоящему маленький или одноразовый. Но всё прочее реально выиграет от нескольких тестовых скриптов. Test::Harness делает это столь простым, что у вас нет оправданий не использовать тесты. Если нет времени, возможно, вы тратите слишком много на отладку скриптов без тестов. MakeMaker, в конце-концов, нужен не только для модулей.

С медведем поговорили?

Опишите проблему вслух. По-настоящему проговорите слова.

Пару лет я имел счастье работать с очень хорошим программистом, который мог справиться практически со всем. Когда я застревал на чем-то, я шел к его столу и начинал объяснять проблему. Обычно не проходило и трех предложений, как я прерывался: «забудь, я всё понял» (но и он почти всегда находил решение).

Так как вам это, видимо, придется делать очень часто, советую выбрать в качестве Perl-терапевта нечто вроде плюшевой игрушки и не досаждать коллегам. У меня на столе сидит маленький мишка, и я объясняю проблемы ему. Моя подруга даже уже не обращает внимания, когда я разговариваю сам с собой.

Выглядит ли проблема иначе на бумаге?

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

Смотрели сегодня ТВ-шоу?

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

Вы уменьшили свое самомнение?

Если вы еще не покончили, проблема может быть психологической. Вы можете быть эмоционально привязанными к отдельной части кода, поэтому не менять ее. Вы также можете думать, что всё неверно, кроме вас. Тогда вы не считаетесь всерьез с самым вероятным источником ошибок — самим собой. Ничего не упускайте. Проверьте всё.

© brian d foy, <bdfoy@cpan.org>.

© 2002, Perl Documentation Project, все права защищены.