нибудь электрической штуки, и они должны ответить наизусть: “Похоже, изначально отказало вот это, а остальные сообщения идут из-за каскадного отключения”. Почему не передоверить все это программе? Но в НАСА не пытаются - не хотят связываться с этим.
Сейбел: Сменим тему. Какие методы и инструменты отладки вы предпочитаете? Операторы печати? Формальные доказательства? Символические отладчики?
Норвиг: Все вместе, по ситуации. Иногда я использую IDE, которая хорошо умеет трассировать, а иногда Emacs, в котором всего этого нет. Конечно, я трассирую и распечатываю. И думаю. Пишу небольшие тесты, слежу за их выполнением, разбиваю функциональность на части, чтобы понять, где тест не прошел. Честно признаюсь: я часто переписываю код, порой даже когда не нахожу ошибок. Я просто чувствую, что вот в этой части она есть. Что-то меня в этой части беспокоит. Она слишком запутанная. Так не должно быть. Вместо того чтобы внести несколько мелких изменений, я переписываю несколько сотен строк за один раз, и ошибка уходит.
Иногда после этого я чувствую себя виноватым. Ведь я не понял, что это за ошибка, не нашел ее. Я просто разбомбил дом и выстроил новый. В каком-то смысле ошибка ускользнула от меня. Но если решение эффективно - что ж. Это быстрее, чем отыскивать ошибку.
Сейбел: Как насчет утверждений или инвариантов? Насколько формально вы подходите к ним при написании кода?
Норвиг: Скорее неформально. Я не пользуюсь языками со сложными формальными механизмами сверх описания типов, вроде инвариантов цикла. Мне всегда казалось, что хлопот от них больше, чем выгод. Иногда бывает, что цикл не завершается, но это редко, а формальная часть сильно все тормозит. Если же возникла проблема, отладчик сообщит, в каком вы сейчас цикле. Если вы пишете код, от которого зависит много другого кода, и он во что-то встроен, то, конечно, следует доказывать все. Но если встает выбор - выпускать первую версию программы или отлаживать ее, я стою за скорость. Формальная спецификация может подождать.
Сейбел: Вы делали что-нибудь специально, чтобы научиться на собственных ошибках?
Норвиг: Да, это очень интересно, и я хотел бы делать больше в этом смысле. Сейчас я веду переговоры об эксперименте, в масштабах компании или даже всего мира, который облегчил бы понимание таких вопросов. Как классифицировать ошибки и какие факторы надо учитывать в плане продуктивности? Возможно, тип личности программиста? Какие именно программисты более продуктивны? Интересно, какие поддающиеся учету факторы помогают одним программистам работать лучше других? Если это зависит от размера монитора, может, надо дать всем мониторы покрупнее?
Сейбел: Если выяснится, что чем меньше монитор, тем выше эффективность, вас возненавидят.
Норвиг: Верно. Если важна тишина, давайте ее добьемся, но если также важно взаимодействие между членами команды - как увязать одно с другим?
Я только недавно начал думать в этом направлении. Как поставить эксперимент? Что отслеживать? Есть ли пригодные для использования количественные данные, к которым надо только приложить опросник? Надо ли вообще ставить такой опыт?
Сейбел: Часто утверждают, что эффективность работы разных программистов может отличаться на порядок. Но это утверждение и критикуют, говоря, что соответствующие исследования проводились давно, что в программировании многое изменилось, что одни программисты использовали пакетную обработку данных, а другие - программные среды с разделением времени.
Норвиг: Наверное, дело не только в этом - думаю, отличались и программисты одной организации, которые пользовались одинаковыми инструментами. Критиковали и за использование корреляций при непонимании причин и следствий. Почему программисты в больших угловых кабинетах работают эффективнее? Потому что просторный кабинет дают лучшему программисту или в нем лучше работает и обычный программист? Такое заключение сделать невозможно.
Сейбел: Сейчас вы получаете такое же удовольствие от программирования, как и вначале?
Норвиг: Да. Но тревожит то, что я знаю не все. Сегодня я программирую не так много и кое-что подзабыл. И столько нового! Обязательно надо переделать мой сайт и на клиентской стороне использовать JavaScript. Он должен быть на РНР или чем-то подобном, но я все не соберусь освоить их.
Сейбел: Как вы полагаете, программирование - удел молодых?
Норвиг: Молодость в некоторых отношениях - плюс. Конечно, у нас есть люди, прекрасно работающие на любом уровне и в любом возрасте. Дело в том, что надо держать в голове всю программу целиком, всю задачу, надо уметь концентрироваться. А это проще делать в молодости - лучше работают мозги или просто меньше отвлекаешься. Если есть семья, дети и так далее, просто нет возможности посвятить этому столько времени подряд, сколько нужно. Это да. С другой стороны, годы приносят опыт, и он отчасти уравнивает шансы: просто знаешь, что нужно делать.
Сейбел: Одна из особенностей нового стиля программирования, как вы подметили, в том, что программист должен впитывать все новое быстро. Что вы делаете, когда нужно прочесть и понять большой фрагмент совершенно незнакомого кода?
Норвиг: Надо применять и статические, и динамическое методы. Начните читать код, постарайтесь понять, что откуда вызывается, где тратится большая часть времени, какие данные передаются. Потом попробуйте что-нибудь сделать - внесите хотя бы самое мелкое изменение. Или зайдите в базу данных возникающих проблем и выберите одну. Для этого надо изучить небольшой участок кода. А изучив его, можно двигаться дальше.
Сейбел: Вы занимались литературным программированием в духе Кнута?
Норвиг: Как таковым - нет. Конечно, я писал макросы и тому подобное, использовал документы Java. Программирование на Лиспе побуждает к созданию собственной системы по мере написания кода, в конце концов это выливается в литературное программирование. Вырабатываешь собственные макросы для программирования в контексте своего приложения - тут и документация, и данные, и код. Так что в принципе я занимался этим. Уже позднее, работая с Java, или Python, или другим языком, я внимательно относился к созданию тестов и документации для них.
На самом деле, в своей книге Кнут пытался рассказать, в каком порядке лучше всего писать книгу, полагая, что кто-то собирается читать книгу целиком и хочет, чтобы это происходило в определенном порядке. Но так уже никто не делает. Человек заглядывает в содержание и выясняет, какой наименьший по объему кусок ему нужно прочесть. Оказывается, ему нужно всего три абзаца. Он находит их и читает. Думаю, это серьезная перемена.
Сейбел: А нельзя ли писать литературные программы в более современном стиле? То, что есть у Кнута, позволяет создать указатель и прекрасную систему перекрестных ссылок. Может быть, если осовременить этот подход, мы получим книгу, построенную по-другому? Она будет читаться и как целая программа, и по кускам.
Норвиг: Не знаю. По-моему, он решал проблему, которой уже почти нет. Отчасти из-за того, что Кнут расположил все линейно, а не в веб-стиле или в порядке, удобном для поиска. Отчасти из-за ограничений - изначально он использовал Паскаль, а этот язык очень строг в отношении порядка определений, и он не всегда такой, как вам нужно. Современные языки более гибкие в этом смысле. Думаю, проблема сегодня не столь актуальна.
Сейбел: Вы говорили о том, как читали в “Scientific American” код программы для шашек. В книге “Как самому научиться программировать за десять лет” вы подчеркиваете важность чтения кода. Какой код вы еще читали, кроме кода Стрейчи?
Норвиг: Много кода Symbolics - он был под рукой, когда я работал в Беркли.
Сейбел: Из-за того, что он был под рукой и был интересным? Или вы пытались разобраться в том, что наблюдали?
Норвиг: И то и другое. Иногда я просто пытался понять, как все устроено, а иногда решал конкретную задачу.
Сейбел: Если вы читаете просто для самообразования, то что именно?