Кодеры за работой. Размышления о ремесле программиста - Питер Сейбел 2 стр.


Завински: Пожалуй, да. Какое-то время мы дурачились с языком XLISP, который использовался на Маках. Хотя, думаю, это было позже. Я там по-настоящему научился программировать (на рабочих станциях PERQ, установленных для проекта Spice) на языке Spice Lisp, который затем стал языком CMU Common Lisp. Странное это было место. Мы узнавали, что такое разработка программного обеспечения, на ежедневных собраниях - просто слушали и все. Но встречались и действительно забавные персонажи, например парень, который был кем-то вроде нашего менеджера - присматривал за нами. Звали его Скеф Хоу-ли - этакий белобрысый детина довольно дикого вида. Выглядел просто устрашающе. Говорил он мало. Сколько раз, бывало, сижу я в своем отсеке - работаю, что-то делаю, пишу программу на Лиспе. И тут, шаркая, подходит босой Скеф с кружкой пива и становится позади меня. Я ему: "Привет", - а он в ответ буркнет что-то или вообще промолчит. Просто стоит и смотрит, как я жму на клавиши. Я что-то делаю, и тут он вдруг: "Пффф, ошибка", - и уходит. А я остаюсь в полном недоумении. Такой дзэнский подход: учитель стукнул меня палкой - значит, надо помедитировать.

Сейбел: Я связался по электронной почте с Фальманом, и он написал, что вы были талантливы и быстро всему учились. Но он также припомнил вашу недисциплинированность. "Мы потихоньку пытались научить его работать в команде, научить писать такой код, чтобы вы или кто угодно еще мог его понять и через месяц". Вы помните эти уроки?

Завински: Не помню, чтобы я учился чему-то такому. Конечно, очень важно писать код, к которому потом сможешь вернуться. Но мне сейчас 39, а тогда было 15, и кое-что уже забылось.

Сейбел: В каком году это началось?

Завински: В 1984 или 1985. Думаю, летом, когда я из 10 класса перешел в 11. Занятия в школе заканчивались часа в четыре или около того, я отправлялся туда и оставался там до восьми-девяти вечера, хотя и не каждый день. Так или иначе, я проводил там немало времени.

Сейбел: И после школы вы ненадолго пришли в Университет Карнеги-Меллона?

Завински: Да. Дело в том, что я ненавидел учиться в старших классах. Это было самое жуткое время в моей жизни. И перед выпуском я спросил Фальмана, не возьмет ли он меня на полный день. Он ответил: "Нет, но у меня есть друзья, которые начинают новое дело. Поговори с ними". Это была фирма Expert Technologies (ETI). Кажется, Фальман был в деле. Они разрабатывали систему автоматической пагинации "желтых страниц" на Лисп, и я уже знал там кое-кого, кто работал с Фальманом. Они взяли меня, и все было хорошо, но через год я запаниковал: "Господи, я же устроился на эти две работы совершенно случайно, такое больше не повторится. Что будет, когда я уйду отсюда?" Без диплома колледжа мне светил разве что Макдональдс. Значит, надо было добывать диплом.

План был такой: я работаю на полставки в ETI, а остальное время учусь, тоже в половинном режиме. На деле же вышло, что работать и учиться пришлось по полной. Так продолжалось недель шесть, может, даже девять. Знаю только, что успел пропустить выбор курсов на семестр, так что деньги было уже не вернуть. Но не успел получить какие-нибудь оценки. В общем, учусь я или нет, непонятно.

Это было ужасно. В школе тебе говорят: мол, у нас тут один отстой и тесты, но в колледже все будет лучше. Поступаешь в колледж, и первый год там все то же самое. И тебе говорят: в магистратуре будет лучше. Все тот же отстой, только в другом месте - не для меня. Вставать в восемь, зубрить. Мне не разрешили пропустить курс "Введение в вычислительную технику", где объясняли, как пользоваться мышью. "Я полтора года работаю в этом университете, - говорил я, - и знаю, как пользоваться мышью". "Нет, мы не можем позволить вам, - отвечали мне. - У нас такой порядок". И все в таком же духе. Я не выдержал и бросил колледж. И рад, что сделал это.

Потом я работал в ETI года четыре или около того, пока компания не стала разваливаться. Мы работали на Лисп-машинах серии TI Explorer, и я - кроме того, что работал над экспертными системами, - тратил массу времени на возню с пользовательским интерфейсом и на понимание того, как они вообще работают, сверху донизу. Я любил их, любил копаться в операционной системе и понемногу осознавать, как это все устроено.

Я написал кучу кода и разместил в нескольких группах новостей объявление о том, что ищу работу, предлагая при этом взглянуть на фрагмент моего кода. Питер Норвиг увидел его и назначил мне собеседование. Моя тогдашняя подружка переехала сюда, в Калифорнию, чтобы учиться в Университете Беркли, и я переехал вместе с ней.

Сейбел: Норвиг тогда был в Беркли?

Завински: Да. Это была очень странная работа. Там был целый выводок практикантов, которые исследовали понимание людьми естественных языков: это были лингвисты по образованию, которые слегка занимались программированием. И нужен был тот, кто собрал бы написанные ими куски и обрывки кода и сляпал бы из них что-то работающее.

Это было невероятно трудно, потому что у меня не хватало подготовки, чтобы понять, что, черт возьми, они там делают. То и дело получалось так: я остолбенело смотрю на что-то и не знаю, что это значит и в каком направлении двигаться, что читать, чтобы понять это. И я спросил Питера. Он внимательно выслушал меня и сказал: "В общем ясно, что пока это для тебя непонятно. Во вторник сядем, и я тебе все объясню". Значит, делать мне было пока нечего. Я углубился в работу с оконными системами, скринсейверами и другими штуками, связанными с пользовательским интерфейсом, которыми раньше занимался для забавы.

После шести-семи месяцев я почувствовал, что трачу свое время впустую. Я не делал для них ничего серьезного, это было похоже на каникулы. Позже не раз, действительно много работая, я оглядывался и спрашивал себя: "Зачем ты оставил эту работу, похожую на каникулы? Что тебе не нравилось? Тебе платили за разработку скринсейверов!"

В конце концов я устроился в компанию Lucid - одну из двух оставшихся Лисп-компаний. По-настоящему меня заставило уволиться чувство, что в Беркли я ничего не достигну. Вокруг меня были сплошь лингвисты, кое с кем я до сих пор дружу, они хорошие ребята - но не программисты. Абстрактные понятия им намного интереснее решения реальных задач. Я хотел делать что-то такое, чтобы можно было ткнуть пальцем и сказать: "Смотри, какую классную штуку я сделал".

Сейбел: Именно работая в Lucid, вы начали заниматься графическим редактором XEmacs. А когда вы туда пришли, вы что-нибудь писали на Лиспе?

Завински: Да, в одном из первых проектов, над которым я работал. Я, правда, не помню, что это был за компьютер, но это точно был 16-про-цессорный компьютер с поддержкой параллельных вычислений, на котором мы использовали собственную реализацию языка Common Lisp с управляющими структурами, позволяющими распараллеливать задачи на разные процессоры.

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

А до этого я поднимал Лисп на новых типах машин. Обычно это означало, что кто-то уже написал компилятор под новую архитектуру железа и скомпилировал загрузчик Лиспа. Затем я брал бинарный, вроде бы работающий код и расшифровывал формат загрузчика новой машины, чтобы затем написать небольшую программу на Си, которая бы загрузила бинарные файлы на страницу памяти, сделала ее исполняемой и передала ей управление. После чего, вполне возможно, вы получали командную строку Лиспа и могли вручную загружать другие программы.

Из-за отсутствия нормальной документации этот процесс для каждой новой архитектуры был непростым делом. Приходилось компилировать код на Си, а затем просматривать и редактировать его в Emacs байт за байтом. Давайте-ка посмотрим, что же произойдет, если вот этот бит установить в ноль... Рухнет или нет?

Сейбел: Когда вы говорите, что не было нормальной документации, это значит, что документация была неточной или что ее не было вовсе?

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

Сейбел: Ну, такое случается сплошь и рядом, начиная от низкоуровневого системного программирования и заканчивая высокоуровневым API, когда всё начинает работать совсем не так, как ты ожидаешь, или не так, как написано в документации. Как вы справлялись с этим?

Завински: Да просто начинаешь ожидать этого. Чем раньше поймешь, что сбился с пути, тем раньше сможешь выяснить, где именно. Лично я пытался создать исполняемый файл. Я знал, что компилятор Си может создавать исполняемые файлы. Поэтому алгоритм работы был такой: берешь хороший исполняемый файл и начинаешь его ковырять, пока он не превратится в плохой. Это основной механизм обратной разработки (reverse engineering).

Думаю, именно в компании Lucid я исправил самый сложный компьютерный баг. Я дошел до момента выполнения исполняемого файла, когда тот пытался загрузить интерпретатор Лиспа, но после выполнения 500 инструкций процесс загрузки падал. Тогда я начал выполнять процесс загрузки пошагово, чтобы выяснить, где же он падает. Хотя это было бессмысленно, создавалось впечатление, что процесс падал каждый раз в другом месте. Я стал исследовать ассемблерный код компьютерной архитектуры, о которой имел лишь смутное представление. Наконец до меня дошло. "Господи, при пошаговом выполнении он делает что-то не то. Возможно проблема связана с временными задержками". В итоге я понял, что происходило: дело в том, что это была одна из первых машин с упреждающим исполнением команд. В этом случае выполнялись обе ветви кода. Но GDB при пошаговой отладке выполнял только одну из ветвей. Так что баг был в GDB.

Сейбел: Здорово.

Завински: Точно. Но это меня подкосило. "Господи! Мне придется отлаживать GDB, который я первый раз вижу". Чтобы обойти ошибку отладчика, нужно остановить выполнение процесса перед инструкцией ветвления, задать точки останова в обеих ветвях и продолжить выполнение. Именно таким способом мне удалось воспроизвести ситуацию и понять, что же происходит на самом деле. Затем я потратил около недели на исправление GDB, но так и не смог понять, в чем же дело. Я предполагал, что из-за проблем с одним из регистров отладчик считал, что всегда выполняется одна из ветвей условия или что-то в этом роде. Поэтому я изменил команду пошагового выполнения инструкций, чтобы определить, когда оно дойдет до инструкции ветвления, и там сказать: "Стоп, это не делай". Теперь я мог просто пошагово выполнять программу. Выполнение в конце концов останавливалось, я вручную задавал точку останова и продолжал выполнение. Когда что-то отлаживаешь, понимая, что не только путь выбран неверный, так еще и инструмент никуда не годится, - что может быть хуже.

Разработка систем на Лиспе была особенно запутанной, поскольку GDB был совершенно неприменим к Лисп-коду, который не содержал никакой отладочной информации. Причина была в том, что интерпретатор Лиспа был разработан с помощью компилятора, о котором GDB не имел ни малейшего понятия. Думаю, для некоторых платформ создавались стековые фреймы, которых отладчик GDB просто не понимал. На этом этапе GDB был способен лишь на пошаговый прогон ассемблерного кода. Поэтому мы хотели избавиться от него как можно скорее.

Сейбел: А потом у вас появился отладчик Лиспа, и вы оказались во всеоружии.

Завински: Ага.

Сейбел: И примерно в то же время компания Lucid сменила курс, решив создавать интегрированную среду разработки для C++.

Завински: Это началось еще до меня: когда я пришел туда, интегрированная среда разработки уже создавалась. Люди начали переходить с Лиспа на Energize - так называлась эта среда разработки. Это был отличный продукт, но он появился на два-три года раньше, чем нужно. Никто - по крайней мере, никто среди пользователей UNIX - не думал, что им вообще это нужно. Сейчас все используют такие возможности, но тогда мы тратили кучу времени, объясняя, почему эта штука лучше, чем vi и GCC. Еще я делал кое-что для Emacs. Кажется, тогда я уже переписал компилятор байт-кода. Зачем мне это было нужно? Правильно, потому что я делал что-то вроде адресной книги.

Сейбел: Базу данных для Большого Брата?

Завински: Ага. Но работала она ужасно медленно. Я стал выяснять, почему, и понял, что компилятор ни к черту не годится. Я переписал компилятор, что и привело к моей первой ссоре с непримиримым Стеллменом. Тогда я много чего узнал о Emacs.

Сейбел: А изменения в компиляторе коснулись формата байт-кода или только процесса компиляции?

Завински: Я сделал несколько изменений: внес исправления в интерпретатор байт-кода, написанного на Си, а также добавил несколько новых инструкций для повышения производительности. Но компилятор мог быть сконфигурирован, чтобы генерировать байт-код в старом формате или использовать преимущества нового.

Так вот, я написал новый компилятор, а Стеллмен заявил: "Не вижу необходимости в этих изменениях". А я ему в ответ: "Да что вы? Теперь генерируется более быстрый код". А он: "О'кей, тогда пришли мне все изменения исходников и объясни каждую измененную строку". Тогда я ответил: "Нет, я не буду этого делать. Я полностью переписал старый компилятор, потому что он был дерьмовым". Это ему не понравилось. Мой компилятор был добавлен только потому, что я выпустил его, тысячи людей начали им пользоваться, компилятор им понравился, и они надоедали Стеллмену два года. Вот он и добавил мой компилятор, чтобы его больше не доставали.

Сейбел: Вы подписали передачу авторских прав на этот компилятор компании Free Software Foundation?

Завински: Да, я сделал это сразу же. По-моему, это было первое, о чем говорилось в том электронном письме. Там было что-то вроде: "Пришли мне изменения и подпиши это". Я подписал и сказал: "Остальное я выполнить не могу. Я не могу прислать вам изменения. Это просто смешно. Тут все описано, взгляните сами". Вряд ли он смотрел на это хоть раз.

Толкуют, будто были какие-то судебные разборки между Lucid и FSF. Это полная ерунда. Мы подписывали бумаги о передаче авторских прав на все, что делали для FSF. Им было зачем-то нужно утверждать, будто мы делали это не всегда. Бывало, мы подписывали одни и те же бумаги несколько раз, потому что они говорили, будто потеряли их. Кажется, подобная шумиха была с подписыванием бумаг по XEmacs, но это было позже, когда я уже ушел.

Сейбел: Итак, вы начали с Лиспа, но явно не зациклились на нем на всю жизнь. Что было потом?

Завински: Следующим языком, на котором я создавал что-то серьезное, был Си. Казалось, будто вернулись времена программирования на ассемблере под Apple II: это был ассемблер PDP-11, который считал себя настоящим языком. Программирование на Си, как вы наверное знаете, малоприятное занятие, поэтому я старался как можно дольше держаться подальше от всего этого. А C++ - просто гадость. С ним все не так. Так что я старался как можно дольше держаться от него подальше и в Netscape писал на Си. Это было просто - ведь мы были нацелены на небольшие компьютеры, на которых нельзя было нормально использовать программы на C++, потому что код распухал до безумия, как только были задействованы библиотеки. И потом компиляторы для C++ постоянно менялись, что приводило к массе проблем с несовместимостью. Поэтому мы с самого начала выбрали для себя ANSI С, и он хорошо служил нам. После всего этого Java отчасти воспринимался как возврат к Лиспу - в том смысле, что этот язык не лезет из кожи вон, желая отпугнуть вас. Им удобно пользоваться.

Сейбел: В каком смысле?

Завински: Автоматическое управление памятью. Функции выглядят именно как функции, а не как подпрограммы. Очень много сделано для обеспечения модульности. В коде на Си всегда есть искушение применить оператор goto только потому, что это просто.

Сейбел: Значит, сейчас вы в основном используете языки Си и Perl?

Назад Дальше