Однако компилятор — такая система, которая объективно (исключая вырожденные случаи) не может быть сделана за три месяца, даже если предположить, что найдется гений, который физически смог бы написать за этот срок нужный объем кода. Как процесс его разработки, так и процесс кодирования должен предполагать совместную работу, постоянное обсуждение всех мало-мальски существенных решений и крайне аккуратное продвижение вперед, по крайней мере, до тех пор, пока не будет достигнут этап отладки. Слишком велико число связей между всеми компонентами компилятора и невозможно предвидеть, насколько серьезными окажутся последствия самого, казалось бы, невинного решения, принятого "на проходе" как очевидное.
Скрытое напряжение в команде возрастало, и первым не выдержал тот, кто не связывал с проектом все свои помыслы. В один прекрасный день мы двое обнаружили в общем каталоге с рабочими тестами полторы сотни примеров, которые ломали компилятор, причем ломали его вроде бы на тех модулях, которые писали мы. Третий участник исчез. Мы поняли это однозначно: мое терпение кончилось, разберитесь, наконец, с тем, что у вас не работает, догоните меня, а я пока займусь другими делами.
Ошибки были исправлены примерно за неделю (половина из них оказалась "не нашими", а как раз того третьего), однако он так и не вернулся в проект никогда… Мы остались вдвоем.
Как ни покажется странным, мы с Сашей не восприняли происшедшее как катастрофу, хотя вроде бы потерю такого классного специалиста невозможно возместить. Наоборот, мы почувствовали, что у нас появилось второе дыхание, распределили "ничейные" теперь модули между собой и с подлинным энтузиазмом принялись переделывать их. К настоящему времени в них не осталось, наверное, ни единой строчки первоначального кода. Но, к сожалению, осталось несколько тех самых "волевых" проектных решений, которые были приняты без всяких обсуждений как очевидные, которые оказались впоследствии ошибочными и которые к тому времени настолько вросли в ткань компилятора, что духу и сил не хватает их из него вырезать.
Я хочу, чтобы нас правильно поняли. У нас нет к ушедшему абсолютно никаких претензий. Нас не обманули, не предали, не нарушили никаких обязательств. Более того, я вполне допускаю, что сами мы не без греха, и работа в то время шла не слишком ритмично (надеюсь, что и ему уход не принес много горечи). И если я рассказываю об этом эпизоде, то только потому, что мы сами многое при этом поняли и многому научились.
Чем меньше коллектив, тем большее, часто определяющее, значение приобретает проблема личностной совместимости — характеров, темпераментов, привычек и манер, т. е. вещей, которые прямо не относятся к профессии. Примером, близким к идеалу, можно считать Дениса Ритчи и Кена Томпсона. Вот как последний говорил об этом в выступлении при вручении ему премии имени Тьюринга: "Наше сотрудничество было образцом совершенства. За десять лет, которые мы проработали вместе, я могу вспомнить только один случай нескоординированной работы. Тогда я обнаружил, что мы оба написали одинаковую ассемблерную программу из 20 строк. Я сравнил наши тексты и был поражен, обнаружив, что они совпадают посимвольно. Результат нашей работы был намного больше, чем вклад нас обоих по отдельности". Но это, как говорится, от Бога, один случай на миллион. Каких-либо рекомендаций давать невозможно, единственное — надо быть очень и очень осторожным при формировании коллектива.
Что же касается тщательного проектирования и особенностей процесса реализации, то изначальное жесткое разбиение на модули, снабжаемые строгими спецификациями, после чего реализацию этих модулей можно отдать даже и студентам, проходит для хорошо формализуемых и не впервые решаемых типовых задач, а не для систем с предельно сложной логикой, где решительно все взаимосвязано. Традиционная этапность разработки ПО (спецификация и анализ требований, проектирование архитектуры системы, спецификация модулей, реализация и т. д.) в данном случае неизбежно размывается, модифицируется и приобретает существенно итеративный характер: проектирование (и перепроектирование) многих структур данных и алгоритмов компилятора происходит неоднократно уже на этапе реализации. Такой возвратно-поступательный процесс, как мне кажется, органически характерен для создания любой сложной программной системы, семантика которой не может быть осознана и формализована полностью на этапе проектирования в приемлемые сроки. К тому же надо иметь в виду, что в процессе работы над компилятором изменялся и сам язык — процесс стандартизации зачастую преподносил совершенно неожиданные сюрпризы, и многого нельзя было предугадать заранее.
Эта точка зрения, точнее, конкретный опыт, быть может, входит в противоречие с современными моделями процесса создания ПО, описанными классиками,-- Г.Бучем, Э.Йоданом и другими, однако повторю еще раз, компилятор Си++ — не вполне типичная программная система, по крайней мере, с точки зрения семантической и логической сложности.
Так или иначе, мы приобрели ценнейший опыт, полностью пройдя все этапы жизненного цикла программного продукта (в том числе и его сопровождение) и набив на этом пути много шишек. Теперь, надеюсь, мы не наступим еще раз на те же самые грабли.
А вы?
Стиль программирования: на вкус и цвет товарища нет
По условиям контракта языком реализации был стандартный Си. Бельгийцы прислали свой компилятор ANSI C, но основным рабочим инструментом для нас служил gcc из системы GNU, так как он был лучше совместим с нашим любимым отладчиком gdb по формату объектных файлов. Много позже, и это ощущалось нами как внушительный успех, мы начали транслировать компилятор самим собой.
Как и полагается каждой солидной фирме, у наших партнеров имелись собственные внутренние правила и стандарты программирования. В числе необходимых для работы материалов они привезли нам документ под названием "C Coding Standards".
Трудно высказывать объективное мнение по такому тонкому вопросу, как стиль программирования. Здесь, как нигде больше, в полной мере проявляются вкусы и привычки программиста, которые очень трудно преодолеть, если они вступают в противоречие с требованиями, которым приходится следовать в работе. Зачастую расходятся мнения и участников проекта.
Я оказался в меньшей степени отравлен магнетическим воздействием системы UNIX и традициями программирования на Си, или, если угодно, находился под влиянием иной системы традиций ("правильно" построенные языки типа Алгола-68, Паскаля и Ады, большие компьютеры с "настоящими" операционными системами и т.д.), и с большим трудом привыкал к диктуемому "птичьим" языком Си стилю программирования, идущему, как мне кажется, непосредственно от личных пристрастий и привычек создателей языка. Фирменный стандарт, которому предлагалось следовать, честно воспроизводил эти "исторические" особенности, возводя их в ранг если не абсолютной истины, то безусловной нормы.
Мой коллега принадлежит к следующему поколению программистов, чье взросление пришлось на эпоху повсеместного распространения мини-машин и, стало быть, на период повального увлечения UNIXом. Поэтому он впитал дух Кернигана, Ритчи и Томпсона одновременно с базовыми концепциями вычислительной науки и гораздо раньше почувствовал себя в этой среде как рыба в воде. Понятно, что он воспринял все рекомендации и требования фирменного стандарта как нечто естественное и само собой разумеющееся.
Автор практически полностью пропустил эпоху СМ-ок, пересидев ее в машинном зале "Эльбрусов". Выдающаяся элегантность архитектуры этой системы, ее несомненная революционность в сочетании с классическими традициями программирования, положенными в ее основу, заставляли относиться к UNIX с легкой иронией — как к любопытной системе с развитым командным языком и с удачным набором небольшого числа хорошо сочетаемых базовых понятий.
А язык Си показался поначалу чуть ли не студенческой поделкой, сляпанной на скорую руку для себя и друзей, когда уже не было сил программировать на ассемблере и BCPL. Да, собственно, и сами создатели языка не слишком скрывали именно такой первоначальной ориентации Си. Своеобразное изящество, несомненный магнетизм и подлинная мощь этого языка стали осознаваться (и это очень интересно и знаменательно) только при изучении тех новых свойств, которые были внесены в него создателями Си++. В частности, знаменитая лаконичность Си — объект особенно сильной критики его противников — показала свою несомненную полезность и необходимость для механизма шаблонов. Несомненно, основанная на шаблонах парадигма обобщенного программирования А. Степанова не выглядела бы в Си++ так органично, будь этот язык столь же многословен, как Ада. (Сам Александр Степанов признавался, что его попытка создать STL для Ады провалилась прежде всего из-за чересчур «статического» характера этого языка.)