Кодеры за работой — страница 46 из 124

Сейбел: Итак, теперь вы намного больше размышляете о коде. Что именно вы делаете на этом этапе?

Армстронг: Ну, я не просто сижу и думаю — я делаю пометки на бумаге. Пожалуй, это слабо связано с кодом — если взглянуть со стороны, я о чем-то думаю, что-то черчу. Еще один очень важный момент — я спрашиваю своих коллег: «А как бы вы решили эту задачу?» Нередко бывает такое: приходишь к кому-то и говоришь: «Прямо не знаю, как сделать вот это — так или так, выбрать А или Б», — рассказываешь про А и Б и вдруг на полуслове хлопаешь себя ладонью по лбу: «Конечно, Б! Большое, большое тебе спасибо».

Если просто написать все это на доске, ничего не выйдет — нужна обратная связь. Нужен человек, выступающий в роли доски. Вы объясняете что-то, рисуете альтернативные решения, человек вступает в разговор и подсказывает оригинальный ход. И вы внезапно видите решение. Для меня это не распространяется на само написание кода, но диалог с коллегами, решающими сходные проблемы, может быть очень полезен.

Сейбел: Что тут главное — реплики других, вопросы, сам процесс объяснения?

Армстронг: Думаю, вот что: вы переводите задачу из той части мозга, которая ее решает, в ту часть, которая вербализует. Это две разные части. Вы форсируете решение. Я, правда, никогда не пробовал говорить вслух в пустой комнате.

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

Армстронг: Да? Надо попробовать.

Сейбел: Поговорите со своими кошками.

Армстронг: О, само собой! Я работал с одним парнем чуть постарше меня, очень умным. Всякий раз, когда я приходил к нему в офис с каким-то вопросом, он говорил: «Программа — это черный ящик. Есть вход, выход и функциональная связь между ними. Какой у тебя вход, какой выход, какая функциональная связь?» В ходе беседы я вдруг выкрикивал: «Да ты гений!» — и выбегал из комнаты, а тот удивленно качал головой: «Он даже не объяснил мне, в чем проблема». Так что тот парень был вроде медведя.

Сейбел: А что вы чертите — куски кода или просто линии, фигуры?

Армстронг: Чаще всего кружки со стрелками. Когда рисуешь что-то на доске, объясняя людям, то это кружки со стрелками, уравнения, разные обозначения, но не код. Только иногда это куски кода, потому что так экономнее всего что-то выразить. Это в период обдумывания. Код пишу лишь изредка, чтобы понять, сколько времени что займет. Написав строк десять кода, я оцениваю время.

Сейбел: То есть сколько времени займет выполнение программы на компьютере?

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

Сейбел: И посреди обдумывания вы вдруг понимаете, каким должен быть код?

Армстронг: Да, все части складываются воедино. Но, вероятно, объяснить другим я не смогу — просто приходит сильнейшее чувство, что если начать писать программу сейчас, она заработает. Я не знаю в точности, что это за решение. Это как с яйцом. Цыпленок готов вылупиться из яйца. Я тоже готов.

Сейбел: Теперь вы в потоке, и вас нельзя прерывать.

Армстронг: Да-да.

Сейбел: Как я понимаю, остается множество вещей, которые нужно разобрать на уровне кода. Вам нужно сосредоточиться.

Армстронг: Именно так. Но есть два типа сосредоточения. Вещи, которые требуют реального сосредоточения, не те, что можно сделать автоматически, — это вещи, которые надо обдумывать. Это своего рода хитрая сборка мусора, нужно понять, что именно и где разметить. Нужно крепко подумать. Ты знаешь, что решение найдется, потому что ты его уже ограничил со всех сторон. И знаешь, что оно в этом маленьком черном ящике.

Когда Микеланджело расписывал, к примеру, потолок Сикстинской капеллы, у него была команда помощников. Он сперва рисовал общий вид фрески — вот здесь все закрасить голубым, а здесь зеленым. Это напоминает создание программ. Сперва общий набросок, где все расставлено по местам. Некоторые области можно закрасить одним цветом и довольно быстро — это не требует размышления.

А вот рисовать глаза — хитрое дело. Знаешь, что можешь сделать это и что глаза на верном месте, потому что набросок правилен. Начинаешь прорисовывать глаза в деталях. Это не так-то просто, надо всерьез сосредоточиться. А если взять лоб или щеки, особого сосредоточения не нужно — это однородные области. Допустим, на щеках пробиваются волосы, но все равно можно сосредоточиться наполовину.

Затем все набираешь, исправляешь синтаксические ошибки, запускаешь несколько небольших тестов, чтобы проверить, как работает программа. Тут уже можно расслабиться. Увидел мелкую ошибку компиляции, исправил. Поднаторев в языке, можно даже не читать диагностику. Там все равно только номера строк. Ага, такая-то строка неправильная, нужно ее переписать.

Когда я читал курс лекций по Erlang в Чикаго, то бродил по классу и понимал: так, здесь что-то не то. Здесь пропущена запятая или программа даст сбой еще до такого-то события, а у вас нет связей. Моя жена — отличный корректор, сразу видит ошибки. Пропущенная запятая, орфографическая ошибка буквально бросаются ей в глаза. Мне бросаются в глаза ошибки в чужом коде. Это почти бессознательно: смотришь на экран — и бац! — видишь ошибку. Так что речь идет об исправлении несущественных погрешностей.

Сложнее найти небольшие ошибки в написании имен переменных. Чтобы избежать их, я специально подбираю для разных переменных очень непохожие имена. Например, легко спутать переменную person-Name и список имен personNames, поэтому переменную я называю person-Name, а список — listOf People. А вот пунктуацию я вижу хорошо — все, что касается запятых, скобок и так далее. Плюс к тому Emacs сам все раскрашивает, сам делает абзацные отступы, разные скобки выходят разного цвета. Работа сильно облегчается.

Сейбел: Когда вы переходите к написанию кода, то откуда начинаете — сверху, снизу, с середины?

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

Сейбел: Вернемся в прошлое. После Шведской космической корпорации вы работали в исследовательской лаборатории компании Ericsson?

Армстронг: Да. Это было счастливое время, на редкость счастливое — кажется, 1984 год. Я пришел в лабораторию года через два после ее создания, там царил оптимизм. Мы считали, что решим все задачи, убедим руководство запустить новые проекты, производительность компании взлетит. Эти взгляды не имели ни малейшего отношения к реальности. Мы полагали, что придумаем новые полезные программы, и мир встретит нас с распростертыми объятиями. Позже мы поняли, что открывать новые вещи не так-то легко. И невероятно трудно убедить людей пользоваться новыми, более совершенными вещами.

Сейбел: Erlang относился к этим новым, более совершенным вещам?

Армстронг: Да, разумеется. Вначале был Пролог. Я создал нечто вроде небольшого языка, люди стали им пользоваться. Роберт Вирдинг поглядел и сказал: «Прикольно», — а потом спросил, можно ли слегка изменить мой Пролог. Вообще, это довольно опасно — Роберт пишет в комментарии к программе: «Джо придумал, я кое-что изменил», — но на самом деле меняется все. Так что мы переписали код от и до и крепко спорили: «Не могу прочесть твой код, сплошные пробелы после запятых», — в таком духе.

Наконец мы обнаружили кое-кого в Ericsson, кому нужен был новый язык программирования — или, скорее, им нужен был более лучший подход в программировании телефонии. Мы встречались с ними раз в неделю, так продолжалось полгода, может быть, месяцев девять. Общая идея была такова, что они узнают от нас о программировании, а мы от них — о телефонии, о том, что тут за проблема. Это было очень трудно, но при этом стимулировало нас. Язык изменился, поскольку перед нами были живые люди, которые пользовались им, проводили исследования. По результатам они говорили: «Хорошо, но слишком медленно», — и указывали, что все должно работать в 70 раз быстрее. Итак, мы взялись выполнить их требования, заставить язык работать в 70 раз быстрее за два года или около того.

У нас было несколько фальстартов, были и тяжелые моменты. И была одна крупная ошибка. Никогда не обещайте людям, что все будет работать с такой-то скоростью, не осуществив реализации. Но наконец мы поняли, как это сделать. Я написал компилятор на Прологе, Роб занимался библиотеками и разными программами. Примерно после двух лет работы я подумал, что смогу реализовать эту абстрактную машину на Си, — так мне впервые довелось писать на Си. Майк Уильяме, случившийся рядом, посмотрел мой Си-код и сказал: «Это самый плохой Си-код, который я видел в жизни. Никуда не годится». Не думаю, что было настолько плохо, но Майку не нравилось. Поэтому Майк создал виртуальную машину на Си, а я — компилятор на Прологе. Затем компилятор скомпилировал сам себя, произвел байт-код, мы вставили его в машину, поменяли грамматику и синтаксис, скомпилировали компилятор в нем самом и получили нечто такое, что могло самозагружаться. Дело пошло. Это был уже не Пролог, а новый язык.