Джон Кармак о науке и искусстве разработки ПО

Прошу прощения за слегка вольный перевод. Я старался сохранить мысль максимально близко к оригинальной, но при этом сделать текст чуть более связным. В оригинале это транскрипция, причём довольно сложная.

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

Почему я решил перевести этот текст (ведь он короткий и не особо насыщенный откровениями)? Потому, что это выступление Кармака. А он, как-никак, знаковая фигура в отрасли разработки ПО. То, что написано ниже, показывает отрыв теории разработки ПО от практики. Ведь, если эти мысли посещают такого разработчика и выносятся на QuakeCon, — то что тогда творится в головах рядовых прикладных программистов?

От автора транскрипции, Эндрю Ко

Я не особо увлекаюсь компьютерными играми, но, тем не менее, обязан им моим увлечением программированием (оно начиналось с алгоритмов отрисовки). Поэтому, когда я увидел в своей ленте выступление Джона Кармака на QuakeCon 2012, я подумал, что надо бы его послушать. Вдруг узнаю чего нового о создании компьютерных игр?

На самом деле, вместо этого я услышал рассказ о том, как «самый программист из всех программистов» недавно понял, что разработка ПО — это прикладной аспект социологии. На протяжении десяти минут он рассказывал о человеческом факторе применительно к ошибкам разработчиков, разработке языков программирования, статическому анализу, проверках кода, обучению разработчиков и к анализу затрат/выгод.

Ниже — моя транскрипция этого выступления. Заранее прошу прощения за ошибки.


Выступление Джона Кармака

В стремлении делать игры быстрее (а это, собственно, то, что заставляет нас двигаться вперёд) мы наделали в коде Doom 4 много ошибок. Пусть. Эти ошибки, так или иначе, останутся в прошлом. Но само стремление делать игры быстро — необходимо. Потому что нельзя выпускать новую игру раз в шесть лет.

Если говорить про разработку ПО… Вы знаете, я на выставке E3 дал одно интервью, в котором упомянул, что постоянно учусь и в каждом новом году я расту над собой прошлогодним с профессиональной точки зрения. Интервьюер ещё удивлялся — как это мне удаётся расти над собой в течение 20 лет? А, ведь, на самом деле, я рос над собой достаточно слабо — как с точки зрения собственного мастерства, так и с точки зрения понимания динамики командного процесса разработки ПО. Возможно, я сознательно годами не обращал внимания на этот момент, потому что, знаете, появляется соблазн представлять себя этаким учёным и инженером, безапеляционно заявляющим, что вон там — абстрактное понятие, там — доказуемое, а вот там — объективное. Это же “computer science”. Наука.

Сейчас, объясню, что это за момент.

В реальности всё не так. В “computer science” вы учёный в том случае, когда вы говорите об алгоритмах, как о «вещи в себе». Когда вы оптимизируете алгоритмы — вы становитесь инженером. Но и алгоритмы (научная часть) и оптимизация (инженерная часть) — мелочи по сравнению с самим процессом программирования.

У нас есть очень немного программистов, занимающихся исключительно оптимизацией и алгоритмами. 90% наших программистов занимаются обычной рутиной. Мясом, заставляющим ходить скелет.

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

Вам (да и мне, чего уж греха таить) нравится думать, что мы-то — умные инженеры, что действительно есть академические способы писать хорошее ПО. Но, чем больше я смотрю на всё это, тем больше я понимаю, что не в академических способах дело.

Мы можем что-то измерить и воспроизвести, используя научные инструменты для измерения, воспроизведения, оценки и проверки. После этого мы можем выбрать определённые алгоритмы и, даже, каким-то образом их оптимизировать. Но всё остальное, что мы делаем дальше, не имеет никакого отношения к науке или инженерии. Всё остальное — это вопрос социальных взаимодействий между программистами. Или даже программиста с самим собой в разные моменты времени.

Тут можно, например, начать говорить о функциональном программировании, лямбда-счислении, монадах — это всё красиво и очень наукообразно. Но всё это не влияет на то, что конкретно и как конкретно вы разрабатываете. Да, эти «методики» и полезные штуки позволяют ликвидировать определённые классы ошибок, допускаемых абстрактными разработчиками. Но, знаете, всё то, что я могу сделать с использованием чистого функционального языка (а это, как известно, самый академичный, научный и строго формализованный способ решения задач) — всё это будет преобразовано точно в такой же ассемблерный код, в который будет преобразовано аналогичное решение, реализованное на каком-нибудь BASIC или на чём-нибудь другом на ваш выбор.

Касательно этого я бы хотел привести пример с моим старшим сыном — он как раз сейчас учится программированию. У меня, на самом деле, появлялись мысли — а не научить ли его в семь лет чему-то типа Haskell? Хорошо, что мне хватило здравого смысла не давать этим мыслям дальнейший ход. И не потому, что я знаю Haskell настолько плохо, что не смог бы обучить другого человека, изучающего программирование с нуля. Нет.

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

Даже если вернуться от функционального программирования к структурному — вся эта смысловая вата из курса программирования от циклов while и for до объяснения того, как работает компьютер ни что иное, как смысловая надстройка, например, над блок-схемами.

«Если это, то то, иначе то, а не это». Объяснение причины использования в конкретном месте для конкретной цели цикла while или цикла for. Это условности, помогающие людям избегать типичных ошибок при разработке любого ПО. При этом все такие соглашения и разъяснения не имеют никакого отношения к тому, что на самом деле происходит внутри компьютера. Они предназначены только для того, чтобы люди перестали делать типичные ошибки. Те ошибки, которые делаются всеми, постоянно и упорно.

До меня особенно долго доходило, что программисты обязательно, с некоторой периодичностью, делают ошибки. Я в прошлом году много говорил о том, что мы познакомились со статическим анализом и прогнали через него весь наш код, в результате получив сотни и тысячи выявленных проблем. И это очень круто — ведь теперь можно поднять историю, сказать «Смотри, вот тут я допустил ошибку» и показать всем место, где была допущена ошибка. Все посмотрят и для себя отметят: «О, как оно может быть! Хм, постараюсь такого не допускать». Это хорошо, но проблема-то не в следствии, а в причине. Если синтаксис позволяет что-то реализовать некорректно, то это «что-то» будет некорректно реализовано. Именно поэтому, кроме ввода статического анализа я бы хотел сильнее ограничить выразительность языковых средств и тем самым оградить программистов от совершения ошибок.

Сравнительно недавно я начал проводить ежедневные инспекции кода, на которых я пробегаюсь по изменениям и ищу что-нибудь показательное для обсуждения с командой. Я рассматриваю небольшой кусок кода и говорю о том, где в нём ошибка. На самом деле, показ ошибок из живого кода — не такое и большое социальное зло. Хоть живой код и заставляет авторов чувствовать себя не в своей тарелке, он своей наглядностью показывает характер ошибки и не даёт ей распространяться дальше по команде. Это гораздо эффективнее индивидуальных инспекций кода. Думаю, команда уже освоилась и не испытывает дискомфорта от выноса ошибок на всеобщее обозрение.

Кроме того, в некоторых неочевидных случаях (например, в случае размещения спецификатора const у параметра функции) есть возможность объективно разъяснить свою точку зрения («это перенаправление — список для кэширования», «такое отсутствие спецификатора будет нам стоить таких-то вычислительных ресурсов», «мы можем измерить эти ресурсы») — и при этом сделать такое разъяснение максимально аргументированным. Ведь часто бывает так, что вы, в силу опыта и многих лет работы с какой-то предметной областью, сталкивались с проблемой и рассказываете о ней. А люди, в ответ на ваши слова, говорят «Нет, я такого не встречал. Нет, для меня это не проблема. Я не делаю таких ошибок».

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

Я трачу всё больше и больше времени на поиск этих способов. Например, просматривая отчёты лаборатории разработки ПО NASA, я так и не понял ценности и предназначения большинства разрабатываемых продуктов. Все более-менее ценные продукты были полностью автоматизированными, проводили анализ или вычисления без участия человека, либо принимали какие-то решения. Сначала я думал, что по мере роста наших проектов они всё больше и больше приближаются по объёму кодовой базы к продуктам NASA и надо бы нам использовать те же методологии, что используют NASA. Но, к сожалению, если взглянуть на отчёты NASA и на объём кодовой базы их проектов, то там «большими» называются проекты с трёмя-четырьмя сотнями тысяч строк кода. В наших игровых движках кода гораздо больше. Вообще, весело понимать, что игровые движки (то, что оживляет компьютерные игры) устроены внутри сложнее, чем то ПО, что контролировало полёт людей на Луну и обратно, управляло шаттлом, заставляло работать SkyLab или работало на орбитальной станции.

Истина где-то рядом, но точно не в методологиях NASA. Если использовать их подходы, то можно получить очень корректный код, но — ценой очень низкой продуктивности. К сожалению, нашей работой движет анализ затрат и выгод, а он в этом случае гласит — «вы можете быть перфекционистами, но на выходе будет не то ПО, что нужно, а сроки будут сорваны». С другой стороны, если работать быстро (может быть — не очень аккуратно), то можно получать достаточно классные продукты. И в сжатые сроки. Но тут возникает проблема использования правильных инструментов и правильно выстроенной работы с ними, потому что, не решая эту проблему, можно быстро получить «классное» ПО — а потом жить с ним годами и беспрерывно страдать. Я думаю, что нам, к сожалению, пока ещё есть, куда расти в выборе компромиссного между этими двумя варианта построения рабочего процесса.

Мы знаем, зачем и как живёт наш код. Серьёзно, мы смотрим вперёд на десятилетие. Я говорю ребятам, что код, написанный ими сейчас (если он, конечно, не ориентирован на какую-нибудь конкретную игру), может и, скорее всего, будет жить десять лет. И этот код будут использовать сотни программистов. Они будут читать его, обращаться к нему каким-нибудь образом, и это — серьёзная ответственность. Я твёрдо уверен, что мы обязаны предъявлять очень жёсткие требования к анализу и отделению того, что останется в прошлом от того, с чем мы будем жить дальше. К сожалению, кроме этого есть огромное количество нюансов в разработке разноуровневого API, есть огромное количество других неочевидных вещей — и все они требуют мастерского, творческого подхода. Мне хочется, чтобы появилось больше инструментов для работы именно с такими, тонкими материями. И я трачу много времени на то, чтобы такие инструменты у нас появлялись.

Добавить комментарий

Войти с помощью: