Сейбел: Получается, беспристрастный анализ незнакомого кода и его отладка — особые навыки, присущие не всякому хорошему программисту?
Козелл: Конечно. И здесь есть два аспекта. Был еще один парень, Стив Баттерфилд. Он тоже был хорошим отладчиком, но представлял собой полную мою противоположность. В жизни не встречал другого человека, настолько хорошо исправлявшего программы и при этом совершенно в них не разбиравшегося. Он мог взять программу и исправить маленький кусочек где-то у нее в середине, изменив ее работу. В больших, сложных программах Стив мог исправлять какие-то мелочи, заставляя их работать лучше в некотором отношении, но, по-моему, только ухудшая общую картину.
Я же всегда стремился улучшить программу в целом и старался понять ее всю, даже если в исправлении нуждался лишь маленький кусочек. Я всегда разберу все с самого начала, вместо того чтобы сказать себе: «Вот это не работает. Исправь здесь». Так что порой я трачу слишком много времени на то, чтобы загрузить весь код себе в голову, хотя хватило бы быстрого локального вмешательства.
Но когда Стив уходил из проекта, как правило, выяснялось, что править код после него чрезвычайно трудно. Я старался поддерживать все в хорошем состоянии, но если программа была огромной и ужасной, мне приходилось долго работать впустую, прежде чем приняться за реальную работу. Впрочем, такое случалось нечасто, потому что я, как правило, отлаживал программу иначе.
Как уже сказано, я зачастую не имел ни малейшего понятия где именно находится баг. В какой-то момент я говорил себе: «Этот участок кода должен делать то-то и то-то, но не похоже, что он действительно это делает. Зачем вообще было писать такой сложный код для такой простой операции?» Так что я просто выкидывал этот кусок и заменял его подпрограммой, которая делала то, что он должен был делать. И программа сразу, как по волшебству, начинала работать. Если разобраться, то дело, как правило, было в том, что программа развивалась и ее части должны были развиваться вместе с ней. А автор предпочитал исправить старую подпрограмму, вместо того чтобы заменить ее новой, и где-то ошибался.
Я такое никогда не отлаживал. День или два я набирал новый код, никто толком не понимал, что я делаю, но в итоге все начинало работать. Да он же гениальный наладчик! На самом деле, это очень опасно: Уилл, в общем, прав, и переписывая сто строк кода, рискуешь, исправив один баг, добавить шесть новых. Причем о первом ты хотя бы уже знал в то время, а новые шесть надо было еще найти. Но у меня все получалось: год за годом я переписывал код, и в итоге почти всегда все работало.
Сейбел: Значит, у вас должны быть какие-то стратегии чтения кода. Допустим, исправлять ничего не надо, просто перед вами большой кусок кода, который нужно разобрать. Как вы с этим справлялись?
Козелл: Как показывает опыт, не слишком хорошо. Одна из причин, по которой я скорее перепишу фрагмент кода, чем стану его исправлять, заключается в том, что после какого-то момента я уже не могу его разбирать. Я не читаю код, как книгу. Я пытаюсь понять, что программа делает, и затем ищу подсказки в коде, двигаясь от общего к частному.
Читая программу, я одновременно думаю, как бы я решил связанную с ней задачу. То есть ищу те места, в которых смогу сказать: «О, вот тут программа делает то-то». Нередко после этого я со свойственной мне самоуверенностью могу сказать, что автор написал эту часть неправильно. Или, по крайней мере, понимаю, что было сделано не так, как сделал бы я.
Итак, я двигаюсь от общего к частному. Но я знал и тех, кто поступал наоборот, добиваясь отличных результатов. Они начинали читать мелкие подпрограммы и наконец находили среди них нужную. Но я, повторюсь, делал иначе. А именно, смотрел на программу и стремился понять, что ее авторы
В обоих случаях нормальная реакция — исправить этот участок кода в соответствии со своими представлениями о том, как он должен работать в программе. Очевидно, что это опасная затея, потому что всегда есть много способов организовать работу программы, и мой выбор может не совпадать с выбором автора. В итоге я рискую разрушить структуру программы и похоронить себя под лавиной багов. Но мне необычайно везло. Обычно, когда я говорил: «Тут ошибка и я ее исправлю», — мне действительно это удавалось. Причем с самого начала моей карьеры.