11. Питер Дойч
11. Питер Дойч
Питер Дойч — вундеркинд, начал заниматься программированием в конце 1950-х, когда ему было всего 11 лет, после того как его отец принес домой заметку о программировании проектных расчетов для Кембриджского ускорителя электронов в Гарварде. Вскоре после этого он оказался в Массачусетском технологическом институте, где работал над реализацией языка Лисп на компьютере PDP-1, разбирая и улучшая код, написанный программистами MIT, которые были практически вдвое старше его.
Учась на втором курсе в Беркли, Дойч принимал участие в проекте Genie, в рамках которого была создана одна из первых систем разделения времени на основе мини-ЭВМ. Дойч написал большую часть ядра операционной системы. (Кен Томпсон, автор операционной системы UNIX, которому посвящена глава 12, также принимал участие в работе над этим проектом, будучи старшекурсником Беркли. Эта работа нашла отражение в его деятельности, связанной с разработкой UNIX.) После неудачной попытки вывести систему Genie на рынок Дойч перешел в лабораторию Xerox PARC, где работал над средой Interlisp и создавал виртуальную машину Smalltalk, оказав существенное влияние на разработку технологии динамической компиляции (DТ).
Он отвечал за исследовательские работы в ParcPlace, подразделении PARC, и получил звание Fellow[69] в Sun Microsystems. Именно во время работы в Sun он написал знаменитые «Fallacies of Distributed Computing» (Заблуждения о распределенных вычислениях). Кроме того, он является автором Ghostscript, программного комплекта, позволяющего интерпретировать язык Postscript. В 1992 году он входил в группу программистов, получивших премию Ассоциации вычислительной техники (АСМ) в номинации «Разработка ПО» за разработку Interlisp, а в 1994 году был избран почетным членом АСМ.
В 2002 году Дойч отошел от разработки Ghostscript и стал вплотную заниматься музыкой. Теперь его можно застать скорее за созданием музыкального произведения, чем программы, но он по-прежнему периодически позволяет себе поиграть с кодом, в основном, собственного музыкального редактора.
В ходе интервью мы среди прочего обсудили серьезные проблемы, актуальные, по мнению Дойча, для любого языка программирования, который включает понятие указателя или ссылки; поговорили о том, почему ПО должно рассматриваться как основной актив, а не статья расхода, и почему он окончательно перестал заниматься программированием на профессиональном уровне.
Сейбел: Как вы начали заниматься программированием?
Дойч: Программированием я стал заниматься по чистой случайности в 11 лет. Мой отец принес домой какую-то заметку о Кембриджском ускорителе электронов, который в то время строили. Существовала некая группа, которая занималась проектными расчетами, и их заметка оказалась у моего отца. Я увидел ее у него в кабинете — там был какой-то компьютерный код, и что-то в нем было такое, что захватило мое воображение.
Оказалось, что эта заметка была лишь дополнением к другой заметке, поэтому я попросил отца найти эту заметку. Когда он принес ее домой, я взглянул на нее и сказал: «Ого, а ведь это на самом деле интересно». Наверное, я даже попросил отца познакомить меня с человеком, который написал эту заметку. Мы встретились. Уже не помню подробностей, это было 50 лет назад. Так или иначе, мне было поручено написать какую-то небольшую часть кода для одного из проектных расчетов для Кембриджского ускорителя электронов. Вот так я и начал.
Сейбел: Вам тогда было 11 лет. В 14 или 15 лет вы уже занимались с PDP-1 в MIT, в котором ваш отец был профессором.
Дойч: В 14 лет я добрался сначала до ТХ-0, а вскоре после этого и до PDP-1. Помнится, однажды ко мне попал экземпляр руководства для программистов на Лиспе версии 1.5. Не помню, как именно это произошло. Это была одна из самых первых версий — она была напечатана на мимеографе старыми фиолетовыми чернилами. Что-то в Лиспе захватило мое воображение. Я всегда любил математику, и Лисп показался мне очень клевым. Я хотел поработать с ним, но никак не мог добраться до мейнфрейма из здания. Поэтому создал свою версию Лиспа на PDP-1.
Сейбел: Вы помните хотя бы приблизительно, как разрабатывали собственную версию Лиспа на PDP-1?
Дойч: Я улыбаюсь, поскольку это была очень небольшая программа. Вы видели ее листинг? Там всего около пары сотен строк кода на ассемблере.
Сейбел: Я видел его, но даже не пытался понять. То есть вы просто перевели написанное в руководстве по версии 1.5 в программу на ассемблере?
Дойч: Нет-нет. Все, что я взял из руководства по версии 1.5, — это интерпретатор. Мне нужно было написать считывание и токенайзер, разработать структуры данных и все такое. Насколько помню, все это я сделал так же, как делал большую часть своих программ — сначала занялся структурами данных. Когда я был молод, интуиция подсказывала мне — не все время, но практически всегда — действительно верные и удачные подходы к написанию программ.
В последние годы я замечаю, что стал уже не тот — интуиция не работает так здорово, как раньше. Я уже несколько лет занимаюсь (нерегулярно, конечно) крупным проектом по созданию хорошего музыкального редактора с открытым исходным кодом и понимаю, что привычный метод работы — позволить интуиции привести меня к подходящей организации структуры данных, и уже потом просто написать код — больше не работает.
Сейбел: Вы считаете, что все дело именно в том, что ваша интуиция стала хуже работать, или, может быть, вы раньше прикладывали больше сил, чтобы все заработало так, как надо, даже если интуиция вас подводила?
Дойч: Думаю, что истина где-то посередине, хотя первое утверждение все-таки более верно. Как мне представляется, интуиция — это бессознательный процесс поиска решения на огромном поле исходной информации. И чем меньше я погружен в работу над ПО, тем меньше в моем распоряжении исходной информации, которая используется при поиске решений.
Я где-то слышал мнение, согласно которому профессионал в любом деле должен иметь в своем распоряжении около 20 000 конкретных примеров. И дело в том, что 20 000 конкретных примеров из области разработки ПО, которые прошли перед моими глазами за 45 лет работы в этой индустрии, постепенно выветриваются из моей памяти, как это всегда бывает. Мне кажется, по большому счету дело именно в этом.
Сейбел: Вы помните, что именно привлекло вас в программировании?
Дойч: Имея возможность окинуть ретроспективным взглядом 50 лет, вижу, что меня всегда интересовали системы денотативных символов — языки. И не только «словесные» (человеческие) языки, но и языки, в которых все высказывания имеют определенные результаты. Языки программирования идеально соответствуют этому требованию.
Мне кажется, этим же в какой-то мере объясняется и то, почему я сейчас занимаюсь именно сочинением музыки. Музыка — это язык, или семья языков, но у высказываний на этих языках есть не только значения, они еще и воздействуют определенным образом на людей. Музыка представляет для меня интерес, поскольку по степени формализации она находится между естественными языками и языками программирования. Музыка более формализованна и упорядоченна в сравнении с естественными языками, но до языков программирования ей в этом отношении очень далеко. Именно этим, наверное, объясняется, почему я выбрал музыку, а не поэзию. Мне кажется, что поэзия для меня недостаточно формализована.
Но если говорить коротко, то меня туда просто сразу потянуло.
Сейбел: Помните первую интересную программу, которую вы написали?
Дойч: Первой программой, которую я написал, потому что тема заинтересовала меня, стала моя вторая по счету программа. Первой программой был небольшой фрагмент кода, имевший отношение к Кембриджскому ускорителю электронов. Второй же стала программа для форматирования чисел с плавающей запятой.
Сейбел: Это достаточно сложная задача.
Дойч: Для бинарной машины — конечно. Но работая на десятичной машине, эту задачу решить вовсе не сложно. А я работал на десятичной машине.
Нужно просто двигаться по строке и решать, где поставить десятичную запятую. Нужно решить, какой формат использовать — Е или F. Но в те дни все было намного сложнее — я писал на ассемблере на машине пакетной обработки, поэтому эта задача все-таки не была столь уж тривиальной. Это была первая программа, которую я написал, потому что хотел написать.
Сейбел: В старших классах вы много времени проводили в MIT, после чего поступили в колледж в Беркли. Вы хотели сбежать с восточного побережья?
Дойч: Что-то вроде того. Я решил, что мне будет полезно уехать куда-нибудь подальше от своих родителей. Серьезно я рассматривал три места: университеты в Рочестере, Чикаго и Беркли. Думать тут особенно было нечего: лишь в одном из этих трех городов сносная погода. Именно так я оказался в Беркли. И это событие было одним из лучших в моей жизни.
Я учился в Беркли и нашел там — достаточно быстро — проект Genie, и продолжал заниматься им до тех пор, пока... Сначала был проект Genie, затем Berkeley Computer Corporation, потом Xerox.
Сейбел: Судя по всему, именно в Беркли вы стали работать над гораздо более крупными проектами, чем разработка Лиспа на PDP-1.
Дойч: О, да. В рамках проекта Genie я работал над гораздо более крупными проектами. Для начала я написал ядро операционной системы, практически целиком. А это больше 10 000 строк.
Сейбел: Каким образом это изменение масштаба работы повлияло на процесс написания кода?
Дойч: Пытаюсь вспомнить, из чего состояло ядро. Это была достаточно небольшая программа, поэтому я мог воспринимать ее как единое целое. Очевидно, там были некие функциональные части. Помню, что у меня было ясное представление того, какие разделы программы и ключевые структуры данных могли вступать во взаимодействие друг с другом. Но на самом-то деле, черт возьми, этих самых структур данных было не так уж много. Была таблица процессов, были таблицы готовности. Были буферы ввода/вывода и было что-то, что отвечало за отслеживание виртуальной памяти. Кроме того, была таблица открытых файлов — для каждого процесса. Но описания всех системных структур данных, видимо, можно было бы уместить — в терминах структур языка Си — на двух страницах. Поэтому, как вы понимаете, это была не очень сложная система.
Сейбел: Какой была самая большая программа, над созданием которой вы работали, и чье устройство вы помните?
Дойч: Я был основным вдохновителем трех крупных систем. В Ghostscript — не считая драйверов устройств, большинство из которых написал не я, — мною было написано порядка 50-100 тысяч строк на Си.
Что касается ParcPlace, виртуальной машины Smalltalk, то в этом проекте я работал лишь над JIT-компилятором, составлявшим лишь 20% от всего проекта. Количество написанных мною строк исчисляется четырехзначными числами, где-то 3000-5000.
Что касается реализации Interlisp — той ее части, к которой я имел отношение, — то я написал около пары тысяч строк микрокода, и возможно — сейчас я могу только гадать, — еще около 5000 строк на Лиспе. Получается, что Ghostscript — самая большая система, над которой я когда-либо работал.
Сейбел: И не считая драйверов устройств, написанных другими, вы создали его практически в одиночку.
Дойч: До конца 1999 года я написал код практически целиком — до единой строки. Сначала я принял несколько архитектурных решений, первым из которых стало решение полностью развести языковой интерпретатор и графику.
Сейбел: Язык, о котором идет речь, — Postscript?
Дойч: Именно он. То есть интерпретатор языка ничего не знал о структурах данных, которые использовались для создания графики. Они обращались к графической библиотеке, у которой был API.
Второе решение, которое я принял, заключалось в структуризации графической библиотеки с помощью интерфейса драйвера. Таким образом, графическая библиотека знала все про пикселы, про визуализацию кривых и текста, но ничего не понимала в том, каким образом пикселы были закодированы для данного конкретного устройства и каким образом они на него передавались.
Третье решение заключалось в том, что драйверы должны выполнять основные графические команды, которые вначале сводились к draw-pixmap и fill-rectangle.
То есть библиотека визуализации передавала прямоугольники и массивы пикселов драйверу. А драйвер мог либо составить полностраничное изображение, если хотел, либо мог передать их напрямую в Xlib, GDI и так далее. Я принял эти три глобальных архитектурных решения — и это были верные решения. В этом, по большому счету, и состоял процесс создания этой системы. Мне кажется, что я придерживался следующего принципа: если есть что-то, функционирующее во множестве областей, и эти области по сути не склонны к взаимодействию друг с другом, то в этом случае лучше всего установить достаточно мощные программные ограничения.
То есть интерпретация языка и графика по сути не очень-то пересекаются и не взаимодействуют друг с другом. Процессы визуализации графики и представления пиксельных изображений взаимодействуют больше, но мне показалось хорошей идеей установить там еще и границу абстрактности.
На самом деле, интерпретатор Postscript первого уровня я написал без графики — лишь после я написал первую строку кода графики. Откройте руководство и просто пройдитесь по всем операторам, никак не связанным с графикой, — я реализовал их все до того, как начал разрабатывать графику. Мне нужно было разработать токенайзер; мне нужно было определиться с представлением всех типов данных Postscript и всего того, что, согласно руководству, интерпретатор должен делать. Мне нужно было вернуться и переделать многие из них, когда мы добрались до разработки Postscript второго уровня, в котором была функция сборки мусора. Но именно с этого я начинал.
После чего я стал разрабатывать структуры данных для интерпретатора, просто опираясь на свой опыт работы с языковыми интерпретаторами. Между моментом начала и моментом, когда я мог набрать 3 4 add equals и получить на выходе 7, прошло около трех недель. Это было очень легкой работой. Кстати говоря, среда, в которой я работал, — MS-DOS. MS-DOS с упрощенным Emacs и чьим-то компилятором Си — не помню точно, чьим.
Сейбел: Подобную работу вам приходилось много раз выполнять до этого: реализовывать интерпретатор для языка. Вы просто сели и начали писать код на Си? Или предварительно набросали в блокноте схемы структур данных?
Дойч: Эта задача казалась мне достаточно простой, поэтому я не заморачивался со схемами. Насколько сейчас помню, сначала я внимательно изучил руководство Postscript. Затем, возможно, сделал несколько заметок в блокноте, но, скорее всего, просто начал писать заголовочные файлы в Си. Поскольку, как я уже говорил, мне нравится начинать разработку программы с данных.
Затем мне пришла идея, что, наверное, должен быть файл с главным циклом интерпретатора. Каким-то образом должна была происходить инициализация. Нужен был токенайзер. Нужен был менеджер памяти. Нужно было как-то управлять представлением файлов в Postscript. Нужно было реализовать отдельные операторы Postscript. Поэтому я разделил все это на несколько файлов, можно сказать, функционально.
Когда я озаботился проблемой получения авторских прав на код Ghostscript, мне пришлось отправить полный листинг самой первой его реализации. На тот момент уже прошло около десяти лет — мне было интересно взглянуть на первые варианты кода, структуры и названий для разных вещей. Примечательно также то, что около 70-80% структуры и принципов наименования остались теми же — спустя десять лет и после двух серьезных переработок языка Postscript.
По большому счету, этим я и занимался — в первую очередь структурами данных. Предварительным разделением на модули. Я до сих пор убежден, что если сделать правильно структуры данных и их инварианты, то большая часть кода напишется сама собой.
Сейбел: То есть говоря о написании заголовочного файла, вы имеете в виду создание сигнатуры функций или структур — или и то, и другое?
Дойч: Речь идет о структурах. Это был 1988 год, еще не было ANSI С и не было сигнатур функций. Как только компиляторы ANSI С стали более или менее нормой, я потратил два месяца, прошелся по всей программе и сделал сигнатуры для каждой функции в Ghostscript.
Сейбел: Каким образом ваши идеи о программировании или ваш подход к программированию изменились с того далекого времени?
Дойч: Они изменились очень сильно, поскольку очень сильно изменились те программы, которые мне интересны. Думаю, не погрешу против истины, если скажу, что программы, которые я писал первые пару лет, были всего лишь небольшими фрагментами кода.
Я все время размышлял над проблемами, связанными с тем, как нужно браться за программу, которая делает что-то более глобальное и интересное, как ее структурировать, как с ней работать, как нужно работать с языками, которые используешь, чтобы написать эту программу в соответствии с тобою же установленными критериямя практичности, надежности, эффективности, прозрачности.
Теперь я знаю намного больше критериев, применяемых для оценки ПО. И воспринимаю эти критерии в контексте намного более масштабных и сложных программ — программ, в которых наибольшую сложность представляют архитектурные и системные задачи. Речь не о том, что в них не осталось сложностей, связанных с отдельными алгоритмами, но не это привлекает меня в них в первую очередь — и уже давно.
Сейбел: По-вашему, все программисты должны стремиться к работе на подобном уровне?
Дойч: Нет. На самом деле, я буквально на днях прочитал, что мой давний знакомый по работе в Xerox PARC Лео Гуибас только что получил достаточно престижную профессиональную премию. Он никогда не был по-настоящему системным программистом — таким, каким был я; он всегда был алгоритмовым программистом и всегда работал блестяще. Он нашел подход к определенным классам анализа и оптимизационным алгоритмам, который позволил применять их для решения множества различных задач, и создал новые инструменты для работы с этими задачами. Это прекрасная работа. К тому, чтобы работать на уровне Лео Гуибаса, программисты тоже должны стремиться.
Есть некое сходство между архитектурными принципами и теми принципами алгоритмической разработки, которые Лео и программисты его типа применяют для решения сложных оптимизационных и аналитических задач. А разница в том, что принципы работы с алгоритмическими задачами основаны на 5000-10000-летнем опыте математической науки. В современном же программировании у нас нет подобной базы. Возможно, именно в этом одна из причин того, что сейчас так много плохого ПО; мы не понимаем толком, что делаем.
Сейбел: То есть ничего страшного, если человек, не обладающий системным мышлением, будет работать над более мелкими элементами ПО? Можно ли разделить специалистов на программистов и архитекторов? Или вы действительно хотите, чтобы любой человек, работающий над ПО, выполненным в системном стиле, был способен мыслить в масштабе целой системы, поскольку такие программы достаточно фрактальны по своей сути?
Дойч: Я не считаю, что ПО является фракталом. Было бы неплохо, если бы это действительно было так, но мне кажется, что это не так, поскольку я не считаю, что у нас есть хорошие инструменты для работы с теми явлениями, которые происходят, когда системы становятся больше. Мне кажется, что явления, которые происходят, когда системы становятся большими, качественно отличаются от тех явлений, которые происходят, когда системы из небольших становятся системами средних размеров.
Но если говорить о том, кто должен заниматься разработкой ПО, то на этот вопрос у меня нет однозначного ответа. Единственное, что я знаю, — это то, что чем сложнее программа, тем важнее, чтобы ее делали действительно хорошие программисты. Я знаю, что такая точка зрения — это элитизм, и убежден в своей правоте.
Сейчас происходит множество разных вещей — в частности, размывается граница между представлениями о том, чем ПО является и чем оно не является. Если кто-то разрабатывает веб-сайт, на котором есть хотя бы отчасти сложные моменты, касающиеся взаимодействия с пользователем или отслеживания состояния, то есть и инструменты для создания подобных сайтов. Человек, работающий с подобными инструментами — насколько я их понимаю, хотя я с ними никогда не работал, — решает некоторые из тех задач, которые стоят перед программистом, однако средства решения этих задач не очень-то похожи на написание программ.
Поэтому, пожалуй, на ваш вопрос можно ответить и так: с течением времени все большее количество задач, решение которых раньше требовало программирования, теперь уже не будет решаться с помощью программирования, и практически кто угодно сможет справляться с решением этих задач — и на хорошем уровне.
Знаете старую байку о телефоне и телефонных операторах? Дело в том, что когда телефон только входил в обиход и когда стало ясно, что популярность телефонов стремительно растет, требовалось все больше и больше телефонных операторов, поскольку тогда еще не было автоматических телефонных аппаратов. Кто-то подсчитал уровень роста и воскликнул: «Боже, через 20-30 лет абсолютно всем людям придется стать телефонными операторами». Собственно говоря, так все и произошло. Мне кажется, нечто подобное происходит сейчас и в некоторых крупных областях программирования.
Сейбел: Возможен ли исход, при котором та же история произойдет и с программистами, — что их заменят?
Дойч: Это зависит от того, какую программу нужно написать. Один из вопросов, который я себе постоянно задавал на протяжении последних пяти с лишним лет: «Почему программирование — такая сложная штука?»
Занимаясь программированием, приходится работать в том числе с алгоритмами, по сути достаточно близкими к математике, чтобы ее можно было при желании использовать как некую базовую модель для работы с алгоритмами. Можно применять математические методы и математические подходы. Это не делает программирование легким, но никто и не думает, что заниматься математикой легко. То есть существует достаточно высокий уровень совпадения между материалом, с которым вы работаете, нашим представлением об этом материале и нашим представлением об уровне мастерства, который необходим для работы с ним.
Думаю, отчасти проблема с иным методом программирования заключается в том, что мир практически всех известных нам языков программирования в корне отличается от физического мира, с которым наши чувства, наш разум и наше общество прочно связаны, и было бы безумием ожидать, что люди станут с ним хорошо справляться. С человеком что-то должно быть слегка не так, чтобы он стал хорошим программистом. Может быть, «слегка не так» — это чересчур, но качества, необходимые для того, чтобы быть полноценно функционирующим человеком, и качества, необходимые действительно хорошему программисту, — эти множества, конечно, пересекаются, но не так чтобы очень сильно. И это говорю я, человек, который когда-то был очень хорошим программистом.
Мир фон-неймановских вычислений и языков семейства Алгол настолько непохож на физический мир, что меня на самом-то деле сильно удивляет, что мы еще умудряемся создавать крупные системы, которые хоть как-то работают — даже так несовершенно, как сейчас.
Возможно, кому-то это представляется не более удивительным, чем тот факт, что мы можем строить реактивные самолеты, но реактивные самолеты существуют в физическом мире, и у нас за плечами сотни тысяч лет опыта в машиностроении. Если же говорить о ПО, то перед нами странный мир со странными, причудливыми свойствами. Свойства физического мира неразрывно связаны с субатомной физикой, и есть несколько уровней: субатомная физика, атомная физика и химия. Есть множество неожиданно обнаруживающихся свойств, обусловленных этими уровнями, и у нас есть все инструменты для успешного функционирования в этом мире.
Глядя по сторонам, я не вижу ничего, что напоминало бы мне адрес или указатель. Я вижу объекты — не те странные вещи, которые специалисты в области информационных технологий по какому-то недоразумению называют «объектами».
Сейбел: Не говоря о масштабе. 264 чего бы то ни было — это много, а когда какое-то действие происходит несколько миллиардов раз в секунду — это быстро.
Дойч: Но в реальном мире нас этот масштаб не заботит. Вы ведь знаете число Авогадро — 1023? Мы живем в мире, где одновременно сосуществует невероятное количество мелочей. Но нас это не заботит, потому что мир устроен таким образом, что нам не нужно понимать, к примеру, вот этот стол на субатомном уровне.
Физические свойства материи таковы, что в 99,9% случаев мы можем воспринимать ее в целом. Все, что нам необходимо о ней знать, мы можем узнать, воспринимая ее целиком. И по большому счету этот принцип не работает в мире ПО.
Постоянно предпринимаются поиски подходов к модуляризации ПО. Нужно отметить, что с течением времени эти попытки становятся все более успешными, но, на мой взгляд, еще не скоро будет достигнута та же легкость, с которой мы смотрим по сторонам и видим перед собой вещи — что бы это ни было, — в которых содержатся 1023 атомов, и это нас нисколько не занимает.
Разработка ПО — это наука о деталях, и это самая глубокая, самая ужасная фундаментальная проблема ПО. До тех пор пока мы не научимся понимать и организовывать ПО так, что нам не придется думать о том, каким образом каждая мельчайшая деталь взаимодействует со всеми другими мельчайшими деталями, ничего коренным образом не изменится в лучшую сторону. И нам еще очень далеко до подобных открытий.
Сейбел: То есть нужно лишь преодолеть технические проблемы или просто все дело в сущности самого процесса?
Дойч: Нужно все начать заново. Для начала нужно забыть обо всех языках, в которых существует понятие указателя, потому что в реальном мире нет такого понятия. Нужно смириться с фактом, что информация занимает пространство, существует какое-то время и размещена в определенном месте.
Сейбел: По мере того как вы переходили от работы над небольшими фрагментами кода к созданию крупных систем, вы писали эти маленькие фрагменты с помощью прежних методов и просто приобрели новый взгляд на более крупные системы или это повлияло на ваш подход ко всей работе в целом?
Дойч: Это изменило мой подход к работе в целом. Первыми значительными программами, которые я создал, стали программы на UNIVAC в Гарварде. Следующие несколько программ я сделал на PDP-1 в MIT. В то время — 1960-е, когда я учился в старших классах, — мною были созданы три действительно разные программы, или системы.
Для серийного PDP-1 я написал интерпретатор Лиспа. Я написал какой-то кусок кода операционной системы для причудливо модифицированного PDP-1 Джека Денниса. Кроме того, я написал текстовый редактор для PDP-1 Денниса.
Эти три системы я сделал в целом монолитными. Отличие от моих предыдущих программ на UNIVAC заключалось в том, что здесь мне уже пришлось начать разрабатывать структуры данных. Это было первое серьезное изменение относительно типа программирования, которым я тогда занимался.
Я начал осознавать существование того явления, которое я назову функциональным сегментированием, но тогда я не придавал ему особого значения. Я знал, что можно писать определенные части программы и не заботиться в этот момент о других частях программы, но проблемы с интерфейсами, которые приобретают гигантское значение по мере того, как программа увеличивается в объеме, насколько я помню, не представлялись мне тогда важными.
Переход случился во время работы над моим следующим крупным проектом — во время учебы на старших курсах в Беркли в рамках проекта Genie — над системой разделения времени 940 и над текстовым редактором QED. Еще я написал программу отладки для ассемблера, но почти ничего о ней не помню.
Наиболее системной частью того проекта была операционная система. Я бы погрешил против истины, если бы сказал, что написал всю операционную систему целиком, но это не так. Но я по большому счету написал все ядро на ассемблере. Сейчас речь уже идет о немного более крупных программах — возможно, порядка 10 000 на ассемблере. Там были планировщик процессов, виртуальная память, файловая система. На самом деле там было несколько файловых систем.
И здесь уже передо мной возникли более сложные проблемы в связи с организацией структур данных. Например, из того, что я помню, там была таблица активных процессов. И передо мной встал вопрос: как ее организовать и каким образом операционная система должна решать, когда процесс работоспособен, и прочее. Были и структуры для отслеживания системы виртуальной памяти. Но стали появляться и некоторые проблемы, связанные с интерфейсом. Не в рамках самой операционной системы, нет, поскольку она была настолько мала, что ядро было создано как единый кусок, монолит.
Но были две важные области, в которых стали появляться проблемы программного интерфейса. Одна из них — интерфейс между пользовательскими программами и ядром. Какими должны быть системные вызовы? Как должны быть размещены параметры? Я знаю, что в первых версиях системы 940 основные операции для чтения и записи файлов были эквиваленты вызовам read и write в UNIX, когда вы просто даете базовый адрес и смещение. Это все было очень хорошо, но большую часть времени это было не тем, что нужно. А нужен был попросту потоковый интерфейс. Но в те дни мы и понятия не имели, что можно взять функции операционной системы и затем обернуть их кодом пользовательского уровня, чтобы получился интерфейс получше — вроде того, когда getc и putc надстраиваются над read и write. To есть в более поздних версиях операционной системы мы просто добавили системные вызовы, эквивалентные getc и putc.
Другое место, в котором стали появляться проблемы, связанные с интерфейсом, — вновь на базе режима MULTICS — с самого начала мы строго различали ядро и то, что сегодня называется оболочкой. Это был достаточно ранний этап развития операционных систем, и мы не понимали, что можно на самом-то деле создать оболочку, не обладающую никакими особыми привилегиями. Оболочка была программой, работающей в пользовательском режиме, но у нее было множество особых привилегий. Были небольшие вопросы касательно того, какие функции ядро должно было передать оболочке, — что оболочка должна была делать сама, а что — через вызовы ядра.
Принимая решения по организации интерфейсов, мы исходили из каждой отдельной задачи. Именно в этот момент карьеры ко мне начало постепенно приходить понимание того, что интерфейсы между сущностями нужно разрабатывать по отдельности, что интерфейсы между ними были действительно важной задачей для разработчика.
Поэтому ответ на ваш вопрос о том, изменился ли мой метод программирования после того, как я перестал работать с небольшими кусками кода и перешел к работе с более крупными системами, — да, изменился. По мере того как я создавал все более крупные системы, я стал замечать, что, садясь писать кусок кода, я все чаще и чаще первым делом задавался вопросами: «Каким будет интерфейс между вот этим и всем остальным?», «Что будет на входе?», «Что будет на выходе?», «Какая часть задачи будет отдаваться каждой из сторон этого интерфейса?». Подобные вопросы начали становиться все более крупной частью моей работы. И это, видимо, оказывало влияние на то, как я писал отдельные, более маленькие куски кода.
Сейбел: И это было естественным следствием работы с более крупными системами — в конце концов системы становятся настолько большими, что приходится думать, как разбить их на части.
Дойч: Именно. В этом смысле я согласен, что ПО фрактально, поскольку декомпозиция — процесс многоуровневый. Я хотел сказать, что не уверен в том, что декомпозиция на более высоких уровнях качественно не отличается от декомпозиции на более низких уровнях. Когда занимаешься декомпозицией на более низком уровне, можешь не думать, например, о выделении ресурсов; когда же занимаешься декомпозицией на более высоком уровне, от этого никуда не деться.
Сейбел: Приходилось ли вам работать с людьми, которые, на ваш взгляд, были очень хорошими программистами и тем не менее могли работать только с задачами определенного уровня? Например, они могли хорошо справляться с задачами определенного масштаба, но их склад ума не позволял им разбирать системы на составные элементы, видеть их насквозь?
Дойч: Мне приходилось работать с очень сильными программистами, которым не хватало опыта, чтобы работать на более высоком, системном уровне. Например, во время работы над Ghostscript у меня были достаточно серьезные разногласия с двумя инженерами, которые попали в мою команду, когда началась ее передача компании, которую я создал. Оба инженера были очень умными, очень трудолюбивыми, очень опытными. Мне они казались очень хорошими программистами, хорошими разработчиками. Но оказалось, что они не могли мыслить системно. Они не только не могли думать в терминах влияния или ветвления изменений — им даже в голову не приходило, что подобными вопросами вообще нужно было задаваться. На мой взгляд, одни понимают, какие вопросы нужно задавать при более масштабном подходе к разработке ПО, а другие — по какой бы то ни было причине — вообще не задаются такими вопросами.
Сейбел: Но как вам кажется, эти люди — когда они не пытаются разработать всю систему целиком — делают свою работу хорошо?
Дойч: Да. Те два инженера, о которых я сейчас говорил, приносили огромную пользу компании. Первый работал над одним крупным проектом — это была достаточно неблагодарная работа, но весьма важная с коммерческой точки зрения. А второй переделал крупные фрагменты моего графического кода, и с его кодом мы получили более приятное глазу визуальное воплощение. Они оба хорошие, умные, опытные ребята. Просто они видят не все части картины — по крайней мере, у меня осталось такое впечатление о них.
Сейбел: Есть ли у вас какие-то особенные навыки, которые, по вашему мнению, помогли вам стать хорошим программистом?
Дойч: Я отвечу вам сейчас в духе Нью-эйдж. Вообще говоря, меня нельзя назвать приверженцем Нью-эйджа, хотя и я в свое время носил длинные волосы. Будучи (по собственным оценкам) на пике своих возможностей, я обладал чрезвычайно надежной интуицией. Я просто делал какие-то вещи, и само собой получалось, что я делал их правильно. Где-то мне везло. В каких-то случаях, уверен, дело было в том, что я настолько слился со своим опытом, что мне даже не нужно было сознательно участвовать в процессе принятия решения. Но мне кажется, что у меня просто был к этому талант. Понимаю, что объяснение не очень-то убедительно, но я действительно верю, что кое-что из того, благодаря чему я стал хорош в своем деле, просто было у меня.
Сейбел: Когда вы были не по годам развитым подростком и проводили много времени в MIT, думали ли вы о ком-нибудь: «Да, этот парень очень умен, но он не знает, как делать вот эту штуку, а я знаю»?
Дойч: Нет, такого не было. Хотя, нет, помню один случай, когда я начинал переписывать текстовый редактор на PDP-1 Денниса — мне, наверное, было лет 15 или 16. Исходный код был написан одним или двумя парнями из Клуба технического моделирования железной дороги. Это были умные ребята. Я смотрел на этот код и часто думал про себя: насколько же он ужасен!
Я бы не сказал, что речь о разнице между мной и теми, с кем я работал. Речь о разнице между тем, каким код должен был быть в моем представлении, и тем кодом, который я видел перед собой. Я бы не стал исходя из этого наблюдения делать какие-то обобщающие выводы о людях.
Я всегда достаточно комфортно чувствовал себя в том, что называю символическим миром, в мире символов. Символы и их сочетания — вот что я обычно ем на завтрак. Этого же не скажешь о других. Например, о моем партнере. Мы оба музыканты. Мы оба композиторы. Мы оба вокалисты. Но я рассматриваю музыку в первую очередь с точки зрения символов. Я часто сочиняю, просто сидя за столом с ручкой и листом бумаги. Я записываю ноты, но не играю их тут же на фортепиано. Я их слышу, и у меня есть план.
В то время как у него большая часть процесса сочинения музыки происходит непосредственно с гитарой в руках. Он что-то на ней играет, дурачится с ней, иногда побацает на фортепиано немного, потом играет все сначала. И никогда ничего не записывает. Может, если на него надавить, то он и запишет последовательность аккордов, и, насколько я понимаю, в какой-то момент он записывает слова. Но он подходит к процессу сочинения музыки не с символической точки зрения.
То есть кто-то устроен так, кто-то иначе. Если бы мне нужно было сделать из этого наблюдения какой-то вывод — что ж, повторюсь еще раз, я немного элитист, — я бы сказал, что программированием должны заниматься люди, которые чувствуют себя в мире символов как рыба в воде. Если вы не очень-то комфортно ощущаете себя в этом мире, что ж, может быть, программирование — это просто не ваше.
Сейбел: Были ли у вас учителя, которым вы многим обязаны?
Дойч: Их было двое. Один из них уже не с нами — его звали Кэлвин Муэрс. Он был первопроходцем в исследовании информационных систем. Кажется, это он придумал термин «информационный поиск». По образованию он был библиотековед. Я познакомился с ним в старших классах или уже в колледже. Он тогда занимался разработкой языка программирования, который по его задумке мог бы использоваться неспециалистами. Но он ничего не знал о языках программирования. А я к тому моменту уже кое-что знал, поскольку уже успел создать Лисп-систему и изучал кое-какие другие языки программирования.
Мы сошлись, и в конце концов он сделал язык TRAC — думаю, можно сказать, что мы его создали вместе. Он в тот момент оказывал мне очень серьезную поддержку.
Другой человек, которого я всегда воспринимал как своего наставника, — это Дэнни Боброу. Мы очень долго дружили. И на протяжении своей профессиональной деятельности я всегда считал его своим наставником.
Но если говорить непосредственно о программировании, о разработке ПО, то никого такого в MIT не было. Никого, по большому счету, не было и в Беркли. В PARC был лишь один человек, который по-настоящему повлиял на то, как я разрабатывал ПО, — и то он даже не был программистом. Это был Джерри Элкинд, менеджер лаборатории информационных технологий в PARC.
Вот его слова, которые значительно на меня повлияли: очень важно всегда проводить количественные оценки; будут моменты — даже больше моментов, чем сейчас кажется, — когда твои убеждения и твоя интуиция окажутся неверны, поэтому все измеряй. Иногда даже нужно измерять вещи, которые, как тебе кажется, и измерять-то не надо. Эта мысль очень сильно на меня повлияла.
Когда я хочу заняться чем-то, неизбежно включающим значительный объем вычислений или обработку значительного объема данных, помимо прочего я теперь всегда все измеряю. И это началось с того времени, когда я работал в PARC, то есть около 35 лет назад.
Сейбел: Вы единственный из тех, к кому я обращался по поводу этой книги, весьма резко отреагировали на слово «кодер» в ее названии. Как бы вы предпочли себя называть?
Дойч: Должен сказать, что сейчас у меня даже к слову «программист» слегка негативное отношение. Если вы посмотрите на процесс создания ПО, которое действительно работает, выполняет полезные функции, то увидите, что для достижения этой цели применяется множество разных ролей, процессов и навыков. Кто-то называет себя программистом, но это не очень-то много скажет вам о том, какие навыки они на самом деле используют во время своей работы.
Но, по крайней мере, слово «программист» — достаточно устоявшийся термин для описания достаточно широкого круга специалистов. Тогда как слово «кодер» ассоциируется исключительно с самой незначительной и наиболее узконаправленной частью этого огромного предприятия. Можно сказать, по отношению к процессу создания ПО, которое действительно работает и выполняет полезные функции, кодер — то же, что каменщик для процесса постройки действительно хорошего здания.
Нет ничего плохого в том, чтобы быть кодером. Как нет ничего плохого в том, чтобы быть каменщиком. Чтобы делать то и другое хорошо, требуется множество навыков. Но это лишь очень маленькая часть всего процесса.
Сейбел: Какой же обобщающий термин вас устроит? Разработчик ПО? Специалист в области компьютерных наук?
Дойч: Против термина «компьютерные науки» у меня тоже есть небольшое предубеждение. Могу очень убедительно показать вам, что слово «наука» вообще не должно применяться к программированию. На мой взгляд, по большому счету, все, что называется термином «компьютерные науки», — это сочетание машиностроения и прикладной математики. Думаю, лишь малую часть этого можно назвать наукой, если говорить о наличии истинно научного процесса, то есть когда вы получаете более качественные описания наблюдаемых явлений.
Думаю, если бы мне нужно было выбрать короткое, броское определение, я, пожалуй, остановился бы на «разработчике ПО». Этот термин учитывает практически все — от проектирования архитектуры до кодирования. Он не учитывает некоторые вещи, которые необходимо выполнить для создания ПО, которое действительно работает и выполняет полезные функции, но он описывает практически все, чем занимался я.
Сейбел: А что он не описывает?
Дойч: Он не описывает процесс понимания области задачи, а также определения и понимания требований. Он не учитывает процесс — по крайней мере, весь процесс — получения обратной связи, начиная от тестирования и заканчивая теми вещами, которые происходят после выпуска ПО. По сути, термин «разработчик ПО» описывает мир, ограниченный рамками организации, которая занимается разработкой ПО. Он практически ничего не говорит о связях между этой организацией и ее клиентами по всему миру, которые, по большому счету, и являются исходной причиной появления этого самого ПО.
Сейбел: Как вам кажется, в этой области происходят какие-то изменения? Некоторые сегодня ратуют за то, чтобы связываться с клиентом или пользователем на ранней стадии процесса разработки, и на самом деле хотят сделать это частью работы разработчика ПО.
Дойч: Да, именно этим занимается экстремальное программирование (ХР). Я не являюсь большим поклонником этого подхода. Экстремальное программирование ратует за тесную связь с клиентом во время процесса разработки по двум, как мне кажется, причинам. Первая — таким образом нужды клиента можно лучше понять и выполнить. Может быть, это действительно так. Я не обладаю информацией из первых рук, но отношусь к этому с небольшим скепсисом, поскольку клиенты не всегда знают, чего хотят.
Вторая причина, по которой, как мне кажется, экстремальное программирование стоит за подобное тесное взаимодействие с клиентом, — стремление избежать поспешных обобщений или специализаций. Полагаю, это палка о двух концах, потому что я видел, как реализовывались оба нежелательных сценария — и поспешные обобщения, и поспешные специализации.
Поэтому здесь у меня есть несколько вопросов к экстремальному программированию. Что происходит после того, как проект «завершен»? Оказывается ли техническая поддержка? Выходят ли дополнения и улучшения? Что происходит, когда уходят разработчики, сделавшие исходный вариант проекта? Поскольку экстремальное программирование панически боится всякой документации, я весьма скептически ко всему этому отношусь.
С подобной проблемой я сталкивался при общении с теми, кто очень любит быстрое прототипирование или занимается любой формой разработки ПО, не считая это занятие инженерной дисциплиной. Очень сильно сомневаюсь в том, что ПО, разработанное без применения инженерных подходов, может хоть сколько-нибудь долго проработать.
Сейбел: Вы можете привести пример неудачного обобщения или специализации из своего опыта?
Дойч: Когда я был на пике своей карьеры, одна из вещей, что удавались мне очень хорошо (не утверждаю, что всегда), — я умел выбирать верную степень универсальности, охватывающую несколько последующих лет развития в абсолютно неочевидных направлениях.
Но теперь, вспоминая, я могу назвать один пример поспешной специализации на уровне архитектуры — когда я, занимаясь Ghostscript, принял решение использовать пиксельное, а не плоскостное представление цветовой схемы. Использовать побитовое изображение и соответственно делать так, чтобы представление пиксела укладывалось в long.
Тот факт, что там использовалось точечное, а не планарное представление, означал, что возникали большие трудности, когда приходилось взаимодействовать с дополнительными цветами — при использовании специальных принтеров, в которых применяются цвета, не входящие в стандартный набор CMYK. Например, серебряный, золотой или специальные оттенки, которые должны были быть точно подобраны.
Если вы взглянете на цветовое изображение, разбитое на пикселы, то поймете, что в памяти его можно представить несколькими способами. Можно представить его в памяти как массив пикселов, где каждый пиксел (точка изображения) содержит данные о цветах из схемы RGB или CMYK. Например, так работают обычные контроллеры дисплеев.
Другой способ, наиболее распространенный в полиграфической промышленности, — взять массив, который содержит значение красного цвета для каждого пиксела, затем другой массив, который содержит значение зеленого для каждого пиксела, затем тот, который содержит значение голубого, и так далее. Если изображения обрабатываются по-пиксельно, этот способ наименее удобен. С другой стороны, он не накладывает никаких изначальных ограничений на количество краски или пластин, которые могут быть использованы при создании того или иного изображения.
Сейбел: То есть если у вас есть печатное устройство, которое использует золотую краску, то вы просто добавляете дополнительную пластину.
Данный текст является ознакомительным фрагментом.