Кодеры за работой. Размышления о ремесле программиста - Сейбел Питер
Сейбел: Здорово.
Завински: Точно. Но это меня подкосило. «Господи! Мне придется отлаживать GDB, который я первый раз вижу». Чтобы обойти ошибку отладчика, нужно остановить выполнение процесса перед инструкцией ветвления, задать точки останова в обеих ветвях и продолжить выполнение. Именно таким способом мне удалось воспроизвести ситуацию и понять, что же происходит на самом деле. Затем я потратил около недели на исправление GDB, но так и не смог понять, в чем же дело. Я предполагал, что из-за проблем с одним из регистров отладчик считал, что всегда выполняется одна из ветвей условия или что-то в этом роде. Поэтому я изменил команду пошагового выполнения инструкций, чтобы определить, когда оно дойдет до инструкции ветвления, и там сказать: «Стоп, это не делай». Теперь я мог просто пошагово выполнять программу. Выполнение в конце концов останавливалось, я вручную задавал точку останова и продолжал выполнение. Когда что-то отлаживаешь, понимая, что не только путь выбран неверный, так еще и инструмент никуда не годится, — что может быть хуже.
Разработка систем на Лиспе была особенно запутанной, поскольку GDB был совершенно неприменим к Лисп-коду, который не содержал никакой отладочной информации. Причина была в том, что интерпретатор Лиспа был разработан с помощью компилятора, о котором GDB не имел ни малейшего понятия. Думаю, для некоторых платформ создавались стековые фреймы, которых отладчик GDB просто не понимал. На этом этапе GDB был способен лишь на пошаговый прогон ассемблерного кода. Поэтому мы хотели избавиться от него как можно скорее.
Сейбел: А потом у вас появился отладчик Лиспа, и вы оказались во всеоружии.
Завински: Ага.
Сейбел: И примерно в то же время компания Lucid сменила курс, решив создавать интегрированную среду разработки для C++.
Завински: Это началось еще до меня: когда я пришел туда, интегрированная среда разработки уже создавалась. Люди начали переходить с Лиспа на Energize — так называлась эта среда разработки. Это был отличный продукт, но он появился на два-три года раньше, чем нужно. Никто — по крайней мере, никто среди пользователей UNIX — не думал, что им вообще это нужно. Сейчас все используют такие возможности, но тогда мы тратили кучу времени, объясняя, почему эта штука лучше, чем vi[9] и GCC. Еще я делал кое-что для Emacs. Кажется, тогда я уже переписал компилятор байт-кода[10]. Зачем мне это было нужно? Правильно, потому что я делал что-то вроде адресной книги.
Сейбел: Базу данных для Большого Брата?
Завински: Ага. Но работала она ужасно медленно. Я стал выяснять, почему, и понял, что компилятор ни к черту не годится. Я переписал компилятор, что и привело к моей первой ссоре с непримиримым Стеллменом. Тогда я много чего узнал о Emacs.
Сейбел: А изменения в компиляторе коснулись формата байт-кода или только процесса компиляции?
Завински: Я сделал несколько изменений: внес исправления в интерпретатор байт-кода, написанного на Си, а также добавил несколько новых инструкций для повышения производительности. Но компилятор мог быть сконфигурирован, чтобы генерировать байт-код в старом формате или использовать преимущества нового.
Так вот, я написал новый компилятор, а Стеллмен заявил: «Не вижу необходимости в этих изменениях». А я ему в ответ: «Да что вы? Теперь генерируется более быстрый код». А он: «О'кей, тогда пришли мне все изменения исходников и объясни каждую измененную строку». Тогда я ответил: «Нет, я не буду этого делать. Я полностью переписал старый компилятор, потому что он был дерьмовым». Это ему не понравилось. Мой компилятор был добавлен только потому, что я выпустил его, тысячи людей начали им пользоваться, компилятор им понравился, и они надоедали Стеллмену два года. Вот он и добавил мой компилятор, чтобы его больше не доставали.
Сейбел: Вы подписали передачу авторских прав на этот компилятор компании Free Software Foundation?
Завински: Да, я сделал это сразу же. По-моему, это было первое, о чем говорилось в том электронном письме. Там было что-то вроде: «Пришли мне изменения и подпиши это». Я подписал и сказал: «Остальное я выполнить не могу. Я не могу прислать вам изменения. Это просто смешно. Тут все описано, взгляните сами». Вряд ли он смотрел на это хоть раз.
Толкуют, будто были какие-то судебные разборки между Lucid и FSF. Это полная ерунда. Мы подписывали бумаги о передаче авторских прав на все, что делали для FSF. Им было зачем-то нужно утверждать, будто мы делали это не всегда. Бывало, мы подписывали одни и те же бумаги несколько раз, потому что они говорили, будто потеряли их. Кажется, подобная шумиха была с подписыванием бумаг по XEmacs, но это было позже, когда я уже ушел.
Сейбел: Итак, вы начали с Лиспа, но явно не зациклились на нем на всю жизнь. Что было потом?
Завински: Следующим языком, на котором я создавал что-то серьезное, был Си. Казалось, будто вернулись времена программирования на ассемблере под Apple II: это был ассемблер PDP-11, который считал себя настоящим языком. Программирование на Си, как вы наверное знаете, малоприятное занятие, поэтому я старался как можно дольше держаться подальше от всего этого. А C++ — просто гадость. С ним все не так. Так что я старался как можно дольше держаться от него подальше и в Netscape писал на Си. Это было просто — ведь мы были нацелены на небольшие компьютеры, на которых нельзя было нормально использовать программы на C++, потому что код распухал до безумия, как только были задействованы библиотеки. И потом компиляторы для C++ постоянно менялись, что приводило к массе проблем с несовместимостью. Поэтому мы с самого начала выбрали для себя ANSI С, и он хорошо служил нам. После всего этого Java отчасти воспринимался как возврат к Лиспу — в том смысле, что этот язык не лезет из кожи вон, желая отпугнуть вас. Им удобно пользоваться.
Сейбел: В каком смысле?
Завински: Автоматическое управление памятью. Функции выглядят именно как функции, а не как подпрограммы. Очень много сделано для обеспечения модульности. В коде на Си всегда есть искушение применить оператор goto только потому, что это просто.
Сейбел: Значит, сейчас вы в основном используете языки Си и Perl?
Завински: Ну, я вообще сейчас не много программирую. В основном пишу глупые маленькие скрипты на Perl для поддержания работы моих серверов. Я написал кучу дурацких программ поиска картинок для моих МРЗ-файлов или нечто вроде того. Простенькие одноразовые программки.
Сейбел: Вам нравится Perl или он просто всегда под рукой?
Завински: Терпеть его не могу, ужасный язык. Но он установлен абсолютно везде. Садишься за компьютер — и не нужно никого просить установить Perl, чтобы выполнить свой скрипт: Perl там уже есть. Это единственный аргумент в его пользу.
У него неплохая коллекция библиотек. Часто есть библиотека, позволяющая делать именно то, что тебе нужно. Пусть библиотеки иногда неважно работают, но это уже что-то. Не то, что с Java, когда пишешь что-нибудь на этом языке и пытаешься понять, что вышло. Я сам с трудом установил Java на своем компьютере. Это ужасно. Мне кажется, Perl — противный язык. Если научиться использовать его хоть немного, можно сделать его похожим на Си или, скорее, на JavaScript. Сумасшедший синтаксис, непонятные структуры данных. Немного хорошего можно сказать о Perl.
Сейбел: Но он не так плох, как C++.
Завински: Нет, конечно, нет. Они созданы для разных задач. Есть задачи, которые намного проще реализовать на Perl (или подобном ему языке), чем на Си, только потому, что все так называемые скриптовые языки ориентированы на работу с текстом. Вот чего я действительно не понимаю, так это различия между «программированием» и «написанием скриптов». По-моему, чепуха все это. Но если основная твоя работа заключается в обработке текста или запуске программ (например, запустить wget[11], получить от нее какой-то HTML и сопоставить его с образцом), то гораздо легче это сделать на Perl, чем даже на Emacs Lisp.