Беззаконие Брукса?
АрхивКультовое эссе Эрика Реймонда "Собор и базар" было опубликовано в 1997 году. Но ни автор, ни критики не анализировали связь разработки свободных программ и классического закона Брукса. Попытаюсь это сделать я.
В 1997 году Эрик Реймонд опубликовал эссе "Собор и базар", мгновенно ставшее поистине культовым. Индекс цитирования этого документа до сих пор зашкаливает за все мыслимые пределы, и происходить это, по-видимому, будет еще долго.
Книга Фредерика Брукса "Мифический человеко-месяц" к тому времени считалась классическим трудом о процессе разработки программ. И один из основных тезисов, выдвинутых Реймондом, гласит, что так называемый закон Брукса неприменим к разработкам, которые делаются через Интернет (например, Fetchmail или ядро Linux).
Ни Реймонд, ни его критики (см., например, Н. Безруков. Повторный взгляд на "Собор и базар"), связь разработки свободных и открытых программ с законом Брукса детальному анализу не подвергали - попытаюсь это сделать я. Примирим, так сказать, огонь и воду.
Закон Брукса
Но прежде - остановимся немного на сущности "закона". Книга Брукса основана на наблюдениях за разработкой операционной системы OS/360, однако сделанные в ней выводы о работе групп программистов справедливы и по сей день. Кстати, нечасто встретишь книгу, посвященную программированию и сохранившую актуальность столь долгий срок.
Одна из возможных формулировок закона Брукса такова: "Если программистский проект не укладывается в сроки, то добавление рабочей силы только задержит его окончание".
Суть же в следующем. Представьте себе группу программистов, совместно работающих над проектом. Результат работы зависит в общем случае от действий каждого из них: кто-то подвел - и срыв всего проекта обеспечен. В "добруксовскую" эру работу коллективов программистов рассчитывали, как правило, просто складывая "человеко-месяцы". Не учитывая при этом внутренние связи в коллективе и время, затрачиваемое на коммуникацию между членами группы. Два месяца работы одного программиста считались равными одному месяцу работы двух программистов. Этот подход хоть и работает в случае с рытьем траншей и переноской тяжестей, для программирования слишком груб.
Брукс впервые показал, что в группе людей, результат работы которых зависит от действий каждого, значительное количество ресурсов может уходить на обеспечение связей между членами группы и между группами, работающими над различными частями проекта. Количество подобных связей можно посчитать с помощью формулы вида n*(n–1)/2, где n - число членов команды.
Принцип, лежащий в основе "закона Брукса", применим и в обычной жизни. Скажем, если нам нужно собрать в одном месте и в одно время энное количество людей, то при оценке вероятности срыва всего мероприятия полезно помнить о том, как именно эта вероятность возрастает. Обеспечить явку троих - в три раза труднее, чем двоих, а четверых - в шесть раз труднее.
Linux: торговцы вокруг храма
"Меня очень удивил стиль разработки Линуса Торвальдса - частый выпуск релизов, доступность всех исходных текстов и терпимость к разнородным программам". Это, по Реймонду, и есть "базарный", децентрализованный стиль разработки. Что же происходит при таком подходе?
Если взглянуть на исходники ядра Linux, то можно заметить, что в подавляющем большинстве случаев у патча к ядру один, реже - два автора. А закон Брукса относится к случаям, когда работа идет в группе из нескольких человек. Двое - это тоже группа, но действие закона здесь заметить трудно: на внутренние коммуникации тратится ничтожно малая доля всех средств и рабочего времени.
Однако Брукс писал и об этом. В третьей части своей книги он анализирует одну основных трудностей при разработке больших программ. С одной стороны, чтобы обеспечить концептуальное единство проекта, группа должна состоять из малого числа разработчиков, каждый из которых может окинуть взглядом проект в целом. С другой стороны - маленькая группа будет писать операционку класса OS/360 лет двадцать.
Решение проблемы Брукс нашел в "хирургических бригадах" - группах разработчиков, каждая из которых отвечает за отдельную часть проекта. При этом собственно проектирование берет на себя только один ведущий программист. Остальные занимаются организационным обеспечением, кодингом, документированием и тому подобной рутиной. Эдак по-стахановски: один уголь рубит, а за ним еще двое укрепляют свод забоя.
Если мы посмотрим на разработку программы fetchmail, то увидим, что создавался этот проект "почти по Бруксу". Действительно, "частый выпуск релизов", который Реймонд называет одной из главных причин успеха открытой разработки, - способ обратной связи с массой разработчиков, присылающих патчи. Стихийные разработчики интуитивно, сами того не замечая, воспроизвели что-то вроде "бригады" простейшего образца: один или несколько "хирургов" и неопределенное количество ассистентов. А в случае с ядром Linux количество людей, присылающих патчи, становится неимоверно большим.
Косвенное подтверждение этому можно увидеть в словах Линуса Торвальдса, процитированных в "Соборе...": "По-моему, не очень существенно, способен ли координатор на оригинальный дизайн. Однако совершенно необходимо, чтобы лидер проекта был способен отличить хороший дизайн от всех остальных". И точно такую же "группу" мы можем увидеть в случае разработки ядра Linux.
Вот он, кстати, тот сакраментальный абзац "Собора и базара", с которого все началось: "В "Мифическом человеко-месяце" Фред Брукс рассматривал различные зависимости времени разработки. Он показывает, что сложность проекта и его коммуникационные издержки квадратично зависят от числа разработчиков, тогда как проделанная работа зависит только линейно. Это утверждение называется законом Брукса, и большинство признает его правильным. Однако если бы дело было только в законе Брукса, Linux не мог бы существовать".
Но в том и дело, что нет никакого "коллектива" разработчиков. Нет командной работы - вместо нее параллельная. Не нужно управлять коллективом - он самоорганизующийся и управляется стихийно. "Хирургическая бригада", о которой Брукс писал лет за двадцать до эссе Реймонда, оказалась, хотя и в несколько нетрадиционной форме, применима и в открытых разработках.
Сам Реймонд в "Соборе и базаре" пытается дать стихийным процессам в разработке обоснование с точки зрения психологии: "Джеральд Венберг в "Психологии программирования" предложил теорию, которую мы можем рассматривать как жизненную поправку к закону Брукса. Обсуждая "неэгоистичное программирование" (egoless programming), Венберг замечает, что если разработчики не являются безраздельными владельцами исходников программ и приветствуют, когда другие люди помогают искать ошибки и предлагают различные улучшения, программа прогрессирует намного быстрее". Впоследствии тема связи психологии и теории игр с программированием нашла продолжение в эссе "Заселяя ноосферу".
Процесс разработки патчей к ядру носит не совсем случайный характер, а зависит от того, какое оборудование появляется на рынке и становится распространенным, от возрастания популярности определенных форматов данных, а также от других потребностей рынка.
Так что можно немного скорректировать ту модель разработки свободных программ, которая описана в "Соборе…". Она представляет собой группу координаторов, ведущих проект в целом и работающих, по терминологии эссе, в стиле "собора". Вокруг них расположена большая группа программистов "базарного" стиля - эти программисты отвечают за мелкие улучшения в исходных текстах.
Примерно такое же мнение высказал в статье "Повторный взгляд на "Собор и базар" один из критиков Реймонда Николай Безруков. Его статья повествует об этом вопросе более подробно и с большим количеством примеров. Мы же пойдем дальше.
Продолжение статьи - на следующей странице.
GNU: соборы на базаре
...и перейдем от ядра Linux к собственно ОС. Посмотрим теперь, как идет "стихийная" разработка Unix-подобной системы, на примере проекта GNU. Оговорюсь сразу - GNU периода середины-конца девяностых, примерно совпадающего со временем написания "Собора...".
И самое время сейчас вспомнить, что же представляет собой так называемый Unix Way. Под этим выражением обычно понимается системная архитектура, при которой в состав ОС входит множество утилит, причем каждая из них предназначена для выполнения строго своей функции. Другой основополагающий принцип - перенаправление ввода-вывода, благодаря чему эти утилиты могут обмениваться информацией и работать в связках, которые формируются пользователем.
Когда создавался проект GNU, подавляющее большинство программ-кирпичиков для него писалось в свободное время, спонтанно и на некоммерческой основе. Затем, после накопления критической массы ПО, на GNU стали обращать внимание корпорации, и разработка, поставленная на коммерческие рельсы, приобрела характерные черты, присущие большинству коммерческих программ. Но до этого она, благодаря специфике разрабатываемой операционной системы, сильно распараллелена. Так что о "законе Брукса" в данном случае не может идти речи - "группа" разработчиков отдельных утилит из проекта GNU группой, в сущности, не являлась.
Доступность исходников и ядра, и утилит GNU обеспечивает то, что каждый желающий как бы включается в группу разработчиков и может делать с ними что хочет, но - без необходимости координации действий с остальными. Таким образом, не тратятся ресурсы на согласование действий, зато из-за этого же ресурсы уходят на частичное дублирование работы или бесполезно выполненную работу, типа отвергнутых патчей к ядру.
Также, например, многие утилиты в Linux существуют в нескольких экземплярах. В условиях, когда система строится из "кирпичиков", этот недостаток превращается в достоинство.
Итак, когда людские ресурсы ограничены, легче координировать работу, нежели дублировать ее. В условиях неограниченности числа разработчиков из-за недостатка координации возникает дублирование некоторых частей проекта. Это - две стороны одной медали, и между двумя этими процессами необходимо находить баланс, особенно при открытых разработках.
Еще во второй части своей книги Брукс приводит пять причин, по которым программистам не хватает времени для разработки. Две из них - это плохая организация управления ходом разработки и добавление (если становится ясно, что времени не хватает) программистов к группе разработчиков.
Но стихийно сложившимся сообществом никто не управляет - первая проблема, таким образом, отпадает. А ситуация, когда "не хватает времени", среди свободных разработчиков встречается редко - жестких сроков здесь нет.
Обеспечению концептуального единства проекта Брукс уделяет много внимания в четвертой части своей книги, названной "Аристократия, демократическое и системное проектирование". Эпиграфом к главе стоит цитата из путеводителя по Рейнскому собору, и хотя история об этом умалчивает, но весьма вероятно, что эссе Реймонда обязано своим названием как раз Бруксу. Так вот: разработчики GNU/Linux эту концепцию получили готовой, поскольку занимались, в сущности, повторной реализацией Unix-подобной операционной системы.
Таким образом, разработка программы методом открытых исходников - не панацея, она была применена к изначально стандартному Unix, что позволило уменьшить роль координаторов между отдельными частями проекта: просто осталось реализовать эти стандартные части заново.
Также одной из причин успеха GNU/Linux можно назвать и то, что эта связка первой пришла на массовый рынок и являлась сборником для идей и малых проектов: всегда ведь выгоднее примкнуть к большому проекту, чем затевать свой собственный. Впрочем, здесь уже начинаются скорее психологические проблемы разработки, о которых лучше читать, опять же, у Реймонда.
Выводы
Весьма ценным при разработке открытых программ будет знание того, что законы, по которым велась большая часть подобных разработок до завоевания GNU/Linux теперешней популярности, не вечны, а обязаны своим существованием главным образом специфике реализуемой ОС - в случае с GNU, и вдобавок неограниченному количеству разработчиков - в случае с Linux.
Анализируя вопрос о том, что же представляет собой разработка ядра Linux - "собор" или "базар" (иными словами - централизована ли она или распределена), Николай Безруков высказывает предположение о том, в каком случае какая модель лучше применима: "Для крупных проектов, подобных ОС, особенно важно, чтобы ядро системы разрабатывалось централизованно небольшой тесно сплоченной командой. В то же время при разработке периферийных частей системы более выгоден менее жесткий, более децентрализованный подход".
На первый взгляд может показаться, что это изречение в случае с GNU/Linux на их примере опровергается полностью. Тем не менее мы видим просто путаницу в терминах, вызванную слишком жестким разделением между собой "собора" и "базара".
Кстати, в той же работе Безруков проводит параллель между методами разработки ядра и программ Microsoft. Стратегии разработки - повторяются один в один: сначала выпускаем релиз продукта, а затем - используя реакцию пользователей, исправляем в нем ошибки. Разница - в том, что исходники у Microsoft не открыты, и править ошибки приходится самим программистам - по баг-репортам. А пре-релизы в Linux как раз и рассматриваются сообществом как нечто, требующее доработки.
Итак, закон Брукса наконец-то берет свое. Позволю себе предложить несколько путей сглаживания его действия.
В качестве первого пути можно рассматривать "распараллеливание" работы, то есть продолжение Unix Way, но уже в другой форме. Для этого не обязательно, чтобы проект состоял из отдельных утилит, как GNU. Модульной ведь может быть и графическая ОС.
Идея, если честно, была позаимствована у Виктора Вагнера. В статье "True Unix GUI" он описывает концепцию графической оболочки, в которой:
- программы строятся из модулей, каждый из которых предназначен для выполнения отдельной задачи;
- модули обмениваются между собой информацией с помощью стандартных средств ввода-вывода;
- при обмене информацией модули используют регулярные выражения, позволяющие обеспечивать разбор строки, поданной на вход модуля.
Представьте себе графическую ОС, программы которой можно собирать из функций, как из кирпичиков: комбинировать элементы меню, экранные кнопки, просмотровые модули. При этом программирование для нее превращается в разработку отдельных функций, совместную работу которых в связке обеспечивает сама система. Скажем, модуль, который встраивается в текстовый редактор и при выполнении вызывает функцию, реализуемую отдельной динамической библиотекой или даже стандартным скриптовым языком - допустим, awk или perl. То есть задачей просмотрового модуля становится передача системе данных, с которыми он работает, например текстового файла. Задача системы - передать этот файл отдельному скрипту, который выполнит над ним определенное действие, после чего - вернуть просмотрщику. Ничего невозможного с технической точки зрения я в этом не вижу.
Идеология Unix как раз подходит для того, чтобы над текстовым интерфейсом надстроить подчиняющийся сходным законам интерфейс графический, и то, что этого до сих пор не было сделано при разработке какого-либо из оконных менеджеров под X-Window, - как мне кажется, величайшее упущение - ведь графические интерфейсы к текстовым программам существуют давно, та же kppp, например, или графическая "морда" к GNU Chess…
Осталось стандартизировать язык, способы взаимодействия модулей между собой и обмена данными. Как мне кажется, у программистов, занимающихся разработкой под свободными Unix-подобными ОС, есть шанс сотворить что-то похожее. Например, уже сейчас существует язык описания интерфейса XUL (www.mozilla.org/projects/xul), способный стать одной из составных частей нашей гипотетической оболочки. Данные, которыми оперирует система, могут иметь в своей основе метастандарт XML.
Разумеется, такой подход, когда составные части приложений представляют собой сравнительно компактный код, занимающийся конкретной функцией, поможет, распараллелив разработку, свести действие "закона Брукса" к минимуму и дать пользователю возможность самому конструировать приложения, подобно связкам утилит в "классическом" Unix.
Вторым путем может стать уменьшение числа занятых в проекте программистов. Вообще-то, в свободном программировании это уже наблюдается, по мере того, как от реализации стандартных юниксовых (вернее, работающих стандартным для Unix образом) утилит программисты переходят к созданию независимых проектов. Но хотя, как я уже говорил, людские ресурсы при разработке открытой программы потенциально не ограничены, это относится только к "ассистентам" хирургической бригады. "Хирурги" по-прежнему в цене, и успех проекта зависит главным образом от них.
С увеличением количества ПО становится ясно видна тенденция к сокращению числа программистов, работающих над отдельно взятым проектом. Да, исходники открыты, да, можно сделать к ним патч, - но уже ничтожно малый процент пользователей конкретной программы на это способен. Помните, у Честертона отец Браун советовал прятать лист в лесу? Та самая ситуация…
Дублирование части работы, которое также наблюдается в открытых проектах, является по большей части неосознанным. Использование сознательного разделения проекта на частично перекрывающиеся между собой группы функций теоретически тоже может быть каким-то образом применено - осталось придумать как...