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