Текст книги "Кодеры за работой. Размышления о ремесле программиста"
Автор книги: Питер Сейбел
сообщить о нарушении
Текущая страница: 5 (всего у книги 41 страниц) [доступный отрывок для чтения: 15 страниц]
Затем я переделал все под FastGCI, настроил Apache и вырубил обратный поиск по DNS. После того как все эти этапы пройдены, упираешься в ограничения ввода/вывода или в ресурсы процессора. Потом я получил собственный выделенный сервер, но он был только один, и когда он умирал, у меня начинались проблемы с ресурсами. Я дал доступ на него своим друзьям и просто оставил страницу регистрации открытой. Потому друзья пригласили своих друзей, которые, в свою очередь, пригласили своих друзей, хотя сайт не задумывался как общедоступный. Страница регистрации осталась открытой случайно. Так что потом я поместил на страницу новостей Живого Журнала объявление: «Помогите. Нам нужно купить серверы».
Мы собрали, кажется, тысяч 6 или 7 долларов или около того, купили два больших Dell и поставили их у провайдера Speakeasy в деловом центре Сиэтла, Кто-то порекомендовал нам эти Dell, огромные шести-юнитовые громадины, килограммов под пятьдесят каждая. Логическое разделение было следующим: сервер базы данных и веб-сервер. Это единственное разделение, которое я знал, поскольку работал с двумя процессами – MySQL и Apache.
Какое-то время все работало как надо. Веб-серверы торчали напрямую во внешний мир, у них было по две сетевые карты и небольшой кабель к серверу базы данных. Потом веб-сервер перестал справляться с нагрузкой, но это не было проблемой, поскольку на тот момент у меня имелось несколько одноюнитовых серверов. Итак, у нас было три вебсервера и один сервер базы данных. Тогда я попробовал три-четыре программы балансировки нагрузки для протокола HTTP – mod_backhand, modproxy и Squid – и возненавидел их все. С тех пор не люблю балансировщики нагрузки.
Потому упала база данных. «Вот черт», – сказал я себе. Веб-серверы прекрасно масштабируются, ведь они не сохраняют состояния. Просто добавляешь новые серверы и распределяешь нагрузку. Это был долгий напряженный период. «Так, я могу слегка оптимизировать запросы», но это дает лишь неделю, а потом они опять перестают справляться с нагрузкой. В какой-то момент я задумался, что же нужно каждому конкретному запросу.
Тогда я решил – казалось, мне первому в мире пришла такая мысль, – разбить все это на разделы (partition). Я подготовил документ с рисунками, в котором говорилось, как наш код будет работать. «В главной базе данных будут храниться только метаданные каких-то глобальных вещей, которые дают небольшую нагрузку, а все данные, связанные с индивидуальными блогами и комментариями, для каждого пользователя будут выделены в кластер базы данных. Пользователям с такими-то идентификаторами предназначен определенный раздел базы данных». Задним числом я понимаю, что именно так все и поступают. Но тогда потребовалось много усилий, чтобы переделать код на работающей системе.
Сейбел: Был ли назначен день перевода со старой версии на новую?
Фицпатрик: Нет. У каждого пользователя был флаг, определяющий номер кластера: если он был равен нулю, значит данные находились в основной базе, если отличался от нуля, значит данные уже находились в каком-то разделе. Потом была версия «Ваша учетная запись заблокирована». Учетная запись блокировалась и выполнялась попытка переноса данных, программа пыталась переместить данные и снова сделать это, е£ли вы в это время вносили какие-то изменения. Примерно в таком духе: «Ждите, пока мы не переместим данные, и не вносите никаких изменений в данные в основном кластере, скоро мы переместим вас в ваш индивидуальный кластер».
Такой перевод в фоновом режиме длился несколько месяцев. Мы прикинули, что если бы мы просто выгрузили данные, написали что-то для разбивки SQL-файлов и залили данные назад, то это потребовало бы около недели. Неделя простоя или два месяца медленного переноса? Но в процессе переноса данных 10% пользователей работоспособность сайта снова становилась приемлемой для других пользователей, так что мы смогли увеличить темпы переноса данных с загруженных кластеров.
Сейбел: Это было еще до memcached и Perlbal.
Фицпатрик: До Perlbal – это точно. Memcached, пожалуй, тоже была позднее. По-моему, я создал memcached сразу после колледжа, когда переехал. Помню, как ко мне пришла эта идея. Сайт был на грани, я пошел в душ и вдруг понял, что у нас ведь есть вся эта свободная память повсюду! Я набросал прототип тем же вечером, написал на Perl сервер и клиент, но сервер упал, потому что для сервера на Perl было слишком много обращений к процессору. Поэтому мы начали переписывать его на Си.
Сейбел: И вам не понадобилось покупать новые серверы для базы данных.
Фицпатрик: Да, серверы были дорогими, а процесс перехода с одного на другой – очень медленным. Веб-серверы были дешевы, и добавление новых сразу давало эффект. А при покупке новой базы данных где-то неделя уходит только на запуск и проверку: нужно проверить диски, все установить и настроить.
Сейбел: Значит, все элементы созданной вами инфраструктуры, такие как memcached и Perlbal, были разработаны в ответ на реальные потребности, связанные с масштабированием Живого Журнала?
Фицпатрик: Да, конечно. Все, что мы создали, делалось только потому, что наш сайт падал, и мы ночь напролет выдумывали новые штуки. Однажды мы даже решили купить систему хранения данных NetApp. Это выглядело так. Мы спросили: «Сколько она стоит?», а они в ответ: «Расскажите нам о вашем бизнесе». – «У нас платные учетные записи». «Сколько у вас клиентов? Какая нагрузка?» – «Мы знаем только, что их число растет, вот и все». – «Тогда цена такая: весь доход, который вы можете заплатить, чтобы не развалиться». – «Да пошли вы». Но все же нам была нужна эта штука, и мы ее купили. Скорость ввода/вывода нас не слишком впечатлила, цена была слишком высока, и здесь по-прежнему оставалась единственная точка отказа. Они попытались продать нам конфигурацию с высокой скоростью доступа, но мы сказали: «Да пошли вы. Мы эту ерунду больше не купим».
Итак, мы начали работу над файловой системой. Я даже не уверен, что к этому моменту был опубликован документ по GFS, кажется, я просто услышал о ней от кого-то. В то время я всегда использовал хеш-значение ключа для указания на фрагмент памяти. Почему бы не сделать то же самое с файлами? Файлы постоянны, поэтому нам нужно записывать, где они хранятся, поскольку при добавлении новых узлов хранения меняется и конфигурация. И дело не только в вводе/выводе и отслеживании местонахождения файлов, но и в высокой доступности системы. Мы нашли решение, и я пришел к следующей схеме: «Нам нужно хранить все обращения к файлам, чтобы знать, где что лежит».
Я написал схему для MySQL, сначала главного устройства, а потом для устройства отслеживания файлов. И меня осенило: «Черт! Да эту роль может выполнять протокол HTTP! Это же совсем не сложно».
Помню, как пришел на работу, всю ночь обдумывая это. У нас в здании была общая комната для совещаний – большая и мрачная. «Итак, ребята, прекращаем работу. Все идем вниз и будем рисовать». Я говорил это каждый раз, когда нам предстояло заняться проектированием, и мы просто находили доску, на которой можно было бы рисовать.
Я объяснил схему, и кто с кем должен общаться, и кто что будет делать с запросом. Потом мы поднялись наверх, и я первым делом заказал все оборудование, потому что на его доставку уходило недели две. Потом мы занялись кодированием, надеясь завершить его до получения оборудования. Нам всегда что-то угрожало. Что-нибудь постоянно ломалось, так что нам все время приходилось создавать новые компоненты инфраструктуры.
Сейбел: Если бы кто-нибудь в самом начале сказал: «Вам нужно знать А, Б и В», – упростило бы это вашу жизнь?
Фицпатрик: Всегда легче сделать что-то как надо с первого раза, а не переносить с уже работающего сервиса. Это всегда большой геморрой. Все, о чем я говорил, вы можете сделать на одном компьютере. Проектируете систему таким образом, чтобы было с чего начать. И не делаете предположений о возможности объединений вот этих пользовательских данных с этими и так далее. Предположим, вам нужно загрузить 20 объектов, и ваша реализация может загрузить их из одной таблицы, но код более высокого уровня, которому нужны эти 20 объектов, может собирать их с нескольких машин. Если бы я делал так с самого начала, куда меньше было бы головной боли с переносом.
Сейбел: Итак, урок в основном таков: «Имейте план на тот день, когда ваши данные перестанут влезать в одну базу».
Фицпатрик: Думаю, сегодня это уже общеизвестный факт в сообществе веб-разработчиков. Сейчас многие перегибают палку, считая что их сайт разрастется до неимоверных размеров. Но в то время все считали, что Apache и MySQL достаточно.
Сейбел: Думаю, вы разрабатывали все эти штуки не только по необходимости, но вам было интересно делать все это.
Фицпатрик: Конечно. Я определенно пытался найти повод применить или изучить что-то новое. Никогда не изучишь что-либо, не написав для этого программу и не начав жить и дышать этим. Одно дело выучить язык ради удовольствия, но нельзя говорить о том, что знаешь его, пока не напишешь на нем большую сложную систему.
Сейбел: Итак, какие языки вы можете назвать своими, какими языками вы жили и дышали?
Фицпатрик: Perl. Си. Когда-то Бейсик, но не уверен, что его стоит учитывать. Еще я много писал на Лого. В школе у нас были уроки по Лого. Ребята что-то рисовали, а я сумел выйти из графического режима – это можно сделать, когда знаешь, как, – и писал функции. Учитель подошел и сказал: «Что ты делаешь? Ты должен рисовать домики». – «Нет, я пишу на Лого. Посмотрите». – «Ты все делаешь не так». В конце урока у меня уже была библиотека, позволяющая рисовать буквы алфавита любого размера и повернутые под любым углом. Я мог выводить целые сообщения на волнистых баннерах, которые отдалялись, приближались и все такое, и все стали спрашивать: «Какого черта?» Не знаю, считать этот язык или нет.
Но я много писал на Perl и на Си, потом в колледже много писал на C++ по работе и для Windows. Потом я забыл C++, за ненадобностью, но за последний год, работая в Google, я много писал на C++, Python и Java. Я много писал на Java, когда этот язык только появился, но потом он мне осточертел. Сейчас я опять много пишу на Java, и он меня уже снова достал.
Сейбел: Насколько для вас важен язык, на котором вы пишете?
Фицпатрик: Полностью мне все еще не нравится ни один из них. И я не знаю, какой язык понравился бы мне полностью. Мне не нравится, что в текущем проекте приходится перепрыгивать с одного языка на другой. Я хочу статически типизированный язык, который бы проверял все во время компиляции, когда я этого захочу. Perl очень близок к этому – он позволяет мне кодировать так, как я хочу. Он не выполняет достаточное количество проверок во время компиляции, но я могу заставить делать их во время выполнения. Но и он все же недостаточно хорош.
Я хочу необязательную статическую типизацию. В Perlbal нет нужды в высокой производительности половины всех возможностей, за исключением ядра и копирования байтов туда-сюда. Я хочу, чтобы у меня была возможность во время выполнения давать подсказки в определенных частях кода и объявлять типы. Но если мне лень и хочется что-то протестировать, то могу оформить код соответствующим образом.
Сейбел: То есть типы вам нужны в основном, чтобы улучшить оптимизацию кода компилятором?
Фицпатрик:. Нет. Я хочу, чтобы компилятор говорил мне что-то вроде: «Ты делаешь глупость». Но иногда мне плевать на такие предупреждения и я хочу заставить код выполняться независимо ни от чего. Не хочу показаться слишком большим оптимистом по поводу Perl 6, но они обещают много вещей, которых мне не хватает. Правда, не думаю, что он вообще когда-либо будет выпущен.
Сейбел: А C++ вам нравится?
Фицпатрик: Даже говорить о нем не хочу. Жуткий синтаксис, совершенно непоследовательный, а сообщения об ошибках – по крайней мере компилятора GCC – просто нелепы. Можно получить 40 страниц сообщения только потому, что забыл поставить точку с запятой. Но, как и во многих других случаях, основные шаблоны быстро запоминаешь. Даже не вчитываешься в слова, а просто смотришь на структуру сообщения и понимаешь: «Ага, кажется, я забыл закрыть пространство имен в заголовочном файле». Думаю, новая версия спецификации C++, хотя и добавляет огромное количество сложностей, содержит много всего, что сделает процесс ввода не таким мучительным, по крайней мере, потребуется меньше стучать по клавишам. Переменные auto и нововведения в циклах for[21]21
Имеется в виду новая версия языка C++, которую в настоящее время принято называть C++ Од:. Ключевое слово auto позволяет не указывать явно тип, вместо этого компилятор определит его автоматически (строгая типизация сохраняется). Что касается циклов, то здесь речь идет о так называемом range-based for, который в значительной степени упрощает итерирование коллекций. – Прим. науч.ред.
[Закрыть]. Очень напоминает Python. И лямбда-выражения. Можно даже подумать, что пишешь на Python, а не на C++.
Сейбел: А C++ вы используете из-за его эффективности.
Фицпатрик: Скорее всего, да. В основном я пишу на нем в Google. Там все, что более или менее требует производительности, пишется на C++. Кроме того, в Google я много пишу на Java.
Сейбел: Насколько я понимаю, в компании Google сложилась «С++-центрическая культура», поскольку они использовали этот язык с самого начала, построив на его основе обширную программную инфраструктуру. Хотя и нельзя просто так взять и забыть свою историю – пожалуй, на C++ в Google написана значительная часть кода, которая не требует такой эффективности.
Фицпатрик: Особенно учитывая, что со временем Java стал быстрее, a JVM – значительно умнее. В Java мне не нравится то, что у всех сложилось стойкое отвращение к JNI[22]22
JNI (Java Native Interface) – инфраструктура, позволяющая взаимодействовать коду внутри JVM с «неуправляемым» (native) кодом, таким как API операционной системы или любой код на Си или C++. – Прим. науч. ред.
[Закрыть]. Есть библиотеки на C++. Разработчикам, использующим Python, как внутри компании Google, так и за ее пределами, все равно. Их первая мысль: «Да мы просто обернем все это с помощью SWIG[23]23
SWIG (Simplified Wrapper and Interface Generator) – инструмент с открытым исходным кодом, предназначенный для взаимодействия языков программирования C/C++ с языками сценариев, такими как Tel, Perl, Python, Ruby и др. – Прим. науч.ред.
[Закрыть]». У них есть собственный путь, и они счастливы. Разработчики на Python могут сразу же использовать все, что написано на C++, потому что они не относятся так благоговейно к языку источника.
А сторонники Java говорят: «Надо писать только на чистом Java. Мы не можем использовать JNI, потому что если JVM рухнет, то мы не узнаем, почему». Проблема в том, что все приходится писать дважды – один раз для C++, Python и прочих языков, а второй раз для Java. Так что если они найдут хороший способ взаимодействия или избавятся от страха перед JNI, то я не буду иметь ничего против Java.
Сейбел: А как насчет вопроса «ручное управление памятью против автоматического»? Об этом все еще спорят. У вас есть твердое мнение на этот счет?
Фицпатрик: По правде говоря, нет. Занятно смотреть, как люди высказывают твердое, ничем не подкрепленное мнение. Лично мне ручное управление памятью не кажется таким уж раздражающим, по крайней мере, в C++ с умными указателями. Я могу днями писать на C++, ни разу не применив явно оператор new или delete. Вот так.
Я переписал memcached, уже работая в Google, для работы с инфраструктурой Google и для добавления ее к Арр Engine[24]24
Google Арр Engine – сервис хостинга сайтов и веб-приложений на серверах Google с помощью различных служб Google. См. http://ru.wikipedia.org/wiki/Google_App_Engine. – Прим. науч. ред.
[Закрыть]. Она написана целиком на C++, потому что мне было нужно очень строгое управление памятью для уменьшения фрагментации. И я очень рад возможности ручного управления памятью в C++.
Сейбел: Изначально программа memcached была написана на Си. Вы переписали ее на C++, потому что этот язык предпочтительнее в Google или у него есть другие преимущества?
Фицпатрик: Сперва я хотел просто взять существующую реализацию и перенести ее на C++, но работы оказалось слишком много. Оказалось не так много кода, которым я мог бы воспользоваться, поэтому было гораздо быстрее просто переписать его на C++. Объем кода уменьшился вдвое.
Сейбел: Это из-за C++ или из-за того, что вы стали опытнее?
Фицпатрик: Может, и из-за опыта. Лет в 11-12 я путешествовал с родителями по стране и писал игру Mastermind для калькулятора TI-85 – пару сотен строк – на крошечном экранчике, пытаясь понять, что же я делаю. Я дважды стирал эту проклятую штуковину. Так что я написал ее три раза. Но с каждым разом становилось все легче. Верно подмечено: разрабатывать систему во второй раз намного проще.
Сейбел: Вы много писали на Perl, весьма симпатичном высокоуровневом языке программирования. Как по-вашему, насколько «низко» нужно спускаться программистам? Нужно ли им знать ассемблер и понимать, как работает процессор?
Фицпатрик: Не знаю. Мне знакомы по-настоящему умные люди, я бы сказал, хорошие программисты, но которые знают только Java. Они думают о решении задачи в пределах известной им области. Они не думают о задаче от начала и до конца. По-моему, надо знать всю цепочку, даже если оперируешь только с одним звеном.
Занимаясь Живым Журналом, я думал о разных вещах, начиная от языка JavaScript и заканчивая вопросами взаимодействия с ядром операционной системы. Я читал код системных вызовов epoll[25]25
epoll – новый системный вызов, который появился в Linux 2.6. Призван заменить устаревший select (а также poll). В отличие от старых системных вызовов, длительность работы которых зависела от количества прослушиваемых дескрипторов, epoll использует алгоритм, который не зависит от количества дескрипторов, позволяя добиться хорошего масштабирования при увеличении количества прослушиваемых дескрипторов. – Прим. науч. ред.
[Закрыть] в ядре ОС Linux и думал: «А что если у нас будут все эти длительные соединения по протоколу TCP, и код на JavaScript будет опрашивать открытые TCP-соединения, ведущие к системе балансировки нагрузки?» Я попытался понять, сколько памяти нужно каждой структуре данных на одно подключение. Все это вопросы достаточно высокого уровня, но потом мы задумываемся, скажем, об огромном количестве прерываний от сетевой карты – не переключиться ли нам на использование NAPI ядра ОС вместо получения прерывания по каждому принятому пакету от сетевой карты, которые она будет соединять со скоростью, эквивалентной 100 мегабитам, даже для гигабитной сетевой карты? Мы собирали данные, чтобы определить, на каком уровне это будет иметь смысл и освободит процессор.
Мы много чего сделали для достаточно низкоуровневых вещей. Недавно кто-то сказал мне по какому-то поводу: «Java сам заботится об этом; нам не нужно думать об этом». Я ответил: «Нет, Java не может позаботиться об этом, потому что я знаю, какую версию ядра вы используете, и это ядро не поддерживает эту возможность. Ваша виртуальная машина может скрывать это от вас, предоставляя какие-то абстракции, которые выглядят эффективными, но они будут эффективными только при запуске на определенном ядре». Я расстраиваюсь, когда люди даже поверхностно не знают, как все устроено.
На практике никогда ничего не работает нормально. За прекрасными абстракциями скрывается всякая дрянь. Библиотеки могут выглядеть прекрасно, но работают отвратительно. И если именно вы отвечаете за покупку серверов или за поддержку, то очень полезно знать, что же на самом деле происходит внутри, не доверяя чужим библиотекам, коду и интерфейсам.
Я даже склоняюсь к мысли, что сегодня вряд ли стал бы программистом. Это совсем неинтересно. Вот почему мне так нравятся вещи вроде Арр Engine. Кто-то сказал, что Google Арр Engine – это Бейсик нашего поколения. Потому что для нынешнего поколения все перешло в Сеть. Когда я занимался программированием, был только один язык, и он был установлен на моей собственной машине, а для развертывания системы достаточно было нажать кнопку Run. Сегодняшние дети не хотят заниматься такими глупостями, как «прыгающие мячики» на собственном компьютере. Им нужен веб-сайт.
Мне до сих пор пишут что-нибудь вроде: «Привет, у меня появилась идея: я хочу сайт, который уделал бы Википедию, YouTube,...» Каждый хочет сделать веб-сайт, поскольку четыре его любимых веб-сайта не совсем правильны, и хочет что-то внешне похожее.
То, что Арр Engine предоставляет всего одну кнопку Put this on the Web (Выложить в Сеть) и можно писать все на одном языке – Python, который кажется довольно простым для изучения, – просто прекрасно. Это отличное введение в программирование – вас избавляют от множества уровней всякой ерунды.
Сейбел: Как же это вяжется с вашим расстройством по поводу поклонников Java, когда они говорят: «Java позаботится об этом за вас». Разве это не одно и то же, когда вы говорите: «Арр Engine позаботится об этом за вас»?
Фицпатрик: Не знаю. Может, просто мне известно, что происходит на самом деле. В принципе, JVM не так уж плоха. Думаю, проблемы начинаются тогда, когда люди принимают на веру некие абстракции, не понимая, что происходит на самом деле.
Сейбел: У вас был большой опыт программирования к тому времени, как вы поступили в колледж и начали слушать курс по компьютерным наукам. Как это вам помогло учиться?
Фицпатрик: Поначалу я пропускал много занятий по компьютерным наукам – такая была там скука. Я появлялся только на экзаменах.
Дальше, на третьем-четвертом курсе стало поинтереснее. Но тут, как назло, я окончил колледж. А на занятия магистров меня не пускали, ведь я не учился в магистратуре.
Помню, на курсе по компиляторам последнее задание было таким: взять один из существующих языков, с которыми мы возились, и добавить определенный набор возможностей, включая одну функцию по своему выбору, за которую полагались дополнительные баллы. Я решил реализовать проверку выхода за границы массива во время выполнения. Преподаватель взял мой скомпилированный код и запустил на нем свой набор тестов, и выполнение нескольких из них завершилось неудачно. Тогда он сказал: «Извините, но ваш код не прошел мои модульные тесты. Вы получаете тройку». Я посмотрел на код его тестов и сказал: «Так ваш тест содержит ошибку диапазона (off-by-one error)». Он исправил оценку на пятерку. Но дополнительных баллов я так и не получил и разозлился на колледж.
Еще помню курс по базам данных, который читал человек, видимо, без реального опыта работы с базами данных. А я в то время уже работал с Oracle, Microsoft Server и особенно плотно с MySQL. И я задавал вопросы практического характера, на которые хотел получить ответы – тогда они были актуальны для меня, – но мне выдали стандартную фразу из учебника. Я сказал: «Нет-нет, это не работает».
Сейбел: Вы окончили колледж в 2002 году. Теперь вы можете лучше оценить то, чему вас учили, или нет?
Фицпатрик: Половина курсов мне очень нравилась, я или узнавал что-то новое, чего в то время еще не знал, или получал соответствующие базовые знания и изучал правильную терминологию. До того я неплохо знал программирование, но у меня не было достаточного словарного запаса, чтобы объяснить то, что я делаю. Я мог выдумать собственную терминологию, но в результате люди могли бы подумать, что я не знаю, о чем говорю. В этом плане формальное образование помогло мне.
Сейбел: Вы сожалеете о том, что приходилось совмещать работу с учебой? Может быть стоило заниматься либо одним, либо другим?
Фицпатрик: Нет, мне кажется, это был наилучший вариант. У меня были приятели, которые только учились, но я уже знал так много, что мне было бы скучно. Один мой приятель был действительно знающим, но он считал, что пошел в колледж за знаниями, а вовсе не за дипломом, – и параллельно изучал арабский, китайский и японский. И все эти безумные языки программирования. Каждую неделю он говорил: «У меня теперь новый любимый язык. Эту неделю я программирую только на OCaml». Таким образом, он был постоянно занят. Я тоже был постоянно занят и боролся со скукой, но по-другому.
У меня были приятели, которые бросили колледж в первый же год и стали делать всякую ерунду для Сети. Некоторые занялись порносайтами и всяким таким, типа «мы заработаем кучу денег». И они с головой уходили в работу, но делали только деньги, больше ничего. Колледж – прекрасное место для общения и вечеринок. Если бы я занимался только Живым Журналом, я бы умер от стресса.
Сейбел: Вы довольны тем, что изучали компьютерные науки?
Фицпатрик: Пожалуй, я мог бы обойтись и без этого. Но я много делал и такого, чего сам бы никогда не сделал, так что, думаю, это было полезно. Мне хотелось бы, наверное, заняться чем-нибудь еще, например остаться еще на один год и изучить что-то совершенно постороннее, скажем лингвистику. Мне немного жаль, что я учился в колледже вполсилы из-за того, что много уже знал изначально. На первых курсах я вообще почти не появлялся на занятиях, а когда под конец стало интересно, получилось так: «Поздравляем, вы закончили обучение».
Сейбел: А о магистратуре думали?
Фицпатрик: Да. Было бы интересно, но я был слишком занят.
Сейбел: Вы читаете современную компьютерную литературу?
Фицпатрик: Мы с друзьями посылаем друг другу статьи – хорошие такие статьи. Я, например, недавно читал статью насчет изменения размеров фильтров Блума во время выполнения. Потрясающая статья. Статьи с конференций по системам хранения данных, как из промышленных кругов, так и из академических, о разных прикольных системах – я стараюсь читать все это. Что-то попадалось насчет Reddit[26]26
reddit.com – социальный новостной сайт, на котором зарегистрированные пользователи могут размещать ссылки на какую-либо информацию в Интернете. Как и другие подобные сайты, reddit поддерживает систему голосования за понравившиеся сообщения – наиболее популярные из них оказываются на главной странице сайта. – Прим. науч. ред.
[Закрыть], то ли приятель прислал мне статью, то ли в чьем-то блоге была ссылка на нее.
Сейбел: Вы упомянули о статьях из научных и промышленных источников. Как по-вашему, сегодня есть место, где эти источники сливаются?
Фицпатрик: Иногда у меня и правда возникает такое впечатление. Но часто интереснее читать статьи, основанные на практическом опыте, ведь они пытаются решать реальные проблемы, и их решения работают, в отличие от мыслей вроде: «Мы думаем, будет очень прикольно, если...». Из научного мира исходит много безумных идей, которые на самом деле не работают, так и оставаясь безумными идеями. Может быть, позднее эти идеи превратятся в коммерческие продукты.
Сейбел: Как вы проектируете программное обеспечение?
Фицпатрик: Я начинаю с интерфейсов между некоторыми элементами. Какие методы более свойственны системе – удаленные вызовы или запросы? Если речь идет о хранилищах, я пытаюсь понять, какие запросы будут более частыми. Какие нужны индексы? Как данные будут читаться с диска? Потом я пишу заглушки для различных частей системы, развивая их со временем.
Сейбел: Вы пишете заглушки, чтобы можно было писать тесты до написания остального кода и выполнять их по ходу разработки?
Фицпатрик: Более того. Я всегда проектирую ПО именно таким способом, даже без применения тестов. Сначала я проектирую интерфейсы и хранилища данных, а затем берусь за их реализацию.
Сейбел: В каком виде осуществляется проектирование? Псевдокод? Реальный код? Каракули на белой доске?
Фицпатрик: Обычно я беру редактор и пишу заметки с псевдокодом для схемы базы данных. Доведя ее до ума, создаю реальную схему и копирую/вставляю все скрипты, чтобы удостовериться в том, что операторы create table работают. После этого приступаю непосредственно к реализации. Я всегда начинаю с файла spec.txt.
Сейбел: Бывает ли так, что, написав уже порядочный кусок кода, вы сталкиваетесь с необходимостью пересмотреть свой первоначальный план?
Фицпатрик: Бывает. Но я начинаю с самых сложных кусков или с тех частей, в которых не уверен, и пытаюсь реализовать их в первую очередь. Я стараюсь не оставлять ничего сложного или потенциально неожиданного под конец: я предпочитаю с самого начала решить наиболее трудные вещи. Причина, по которой я так и не завершил ряд своих проектов (друзья говорят, что их целая куча), связана с тем, что я начинал с наиболее сложной части проекта, изучал то, что хотел изучить, и не возвращался к оставшейся неинтересной части.
Сейбел: Можете ли вы дать совет программистам-самоучкам?
Фицпатрик: Всегда старайтесь делать что-нибудь чуть более трудное, чем раньше, то, что вам не по зубам. Читайте чужой код. Я слышал это много раз, но дошло только со временем. Несколько лет я писал много кода, не читая чужой код. Потом я попал в Сеть, а там сплошь и рядом открытый код, в развитии которого каждый может принять участие.
Но я был до смерти перепуган, предполагая, что не смогу в нем разобраться, ведь автором этого кода был не я, и все его устройство не укладывалось у меня в голове.
Потом я начал делать патчи для Gaim, программу мгновенного обмена сообщениями под GTK, начал копаться в коде – и увидел его в целом, я понял это, просто рассматривая отдельные фрагменты кода. После просмотра чужого кода я понял (не могу сказать, что полностью понимаю собственный код), что начал видеть паттерны. «Так, отлично. Я понял структуру, по которой он строится».
И тогда я начал действительно получать удовольствие от чтения кода, потому что, не понимая некоторый паттерн, задавался вопросом: «Какого хрена они сделали это именно так?» – и начинал изучать код внимательнее. Потом говорил себе: «Ух ты, да это же и правда отличный способ решения этой проблемы, мне понятно, как он оправдывает себя». Я бы делал это и раньше, но боялся, поскольку считал, что если код не мой, то я не смогу его понять.
Сейбел: А каким образом вы читаете чужой код? Вы начинаете с того, что читаете код, чтобы понять его в общих чертах, или читаете только тогда, когда нужно внести какие-то исправления?
Фицпатрик: Обычно я хочу что-то исправить. Или просто читаю чужой код, если действительно уважаю его автора. Может, это помогает осознать, что он тоже смертный, и не стоит его боготворить. Или узнать из его кода что-нибудь полезное.
Сейбел: Допустим, вы знаете, какие изменения хотите внести. Как вы поступаете?
Фицпатрик: Прежде всего нужно достать архив исходников или получить последнюю версию из SVN и заставить эту проклятую штуку компилироваться. Преодолеть это препятствие. Для большинства оно оказывается самым сложным из-за дополнительных зависимостей в системе сборки или из-за неверных предположений об уже установленных библиотеках. Иногда мне хочется, чтобы крупные проекты шли с образами виртуальных машин, с полностью настроенным окружением для сборки.
Сейбел: Вы имеете в виду что-то вроде VMware?
Фицпатрик: Да. Если просто хочешь по-быстрому что-то исправить, то вот тебе все зависимости. Связь с людьми устанавливается достаточно быстро. Все отлично работает.
Так или иначе, когда у вас есть чистая работающая сборка, забейте на все и просто сделайте одно долбаное изменение. Измените заголовок окна на «Брэд говорит „Hello world"». Измените хоть что-нибудь. Пусть там все ужасно, просто начните вносить изменения.
Затем по ходу работы пишите патчи. Думаю, это лучший способ начать диалог. Если участвуешь в списке рассылки и пишешь что-то вроде: «Привет, я хочу добавить возможность X», человек, поддерживающий эту систему, скорее всего, ответит: «Какого хрена, я занят. Отвали. Терпеть не могу возможность X». Если же напишешь что-то вроде: «Я хочу добавить возможность X. Я думал сделать такой вот патч», – а это совершенно неверный путь – но ты говоришь: «Но я думаю, что это неправильно. Думаю, что правильный путь – это реализовать X», более сложный путь, и тебе, скорее всего, ответят что-то вроде: «Черт, он старался и, смотрите, пошел совершенно неверным путем».
Возможно, это заденет того, кто поддерживает этот код, и он решит: «Слушай, не могу поверить, что вот на ЭТО потрачено столько сил. Ведь так просто сделать правильно». Или: «Боже, столько работы – и все впустую. Надеюсь, больше этим путем не пойдут». И тогда тебе ответят.
Это лучший путь завязать диалог. Даже в Google я часто начинаю так разговор с командой разработчиков, с которыми не знаком. Исправив ошибку в их коде, я прежде всего посылаю им патч по электронной почте и говорю: «Ребята, что вы об этом думаете?» Или на внутренней ревизии кода говорю им: «Вот описание. Что вы об этом думаете?» Они могут, конечно, сказать: «Черт, нет, это совершенно некорректное исправление».