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