Следующая статья: Как Microsoft меняет лампочку?
![]() C++ - забытый троянский конь |
Содержание
Я знаю программистов, которые начали изучать C++ с единственной целью: чтобы получить возможность обозначать комментарии символами //. Несомненно, популярность C++ в значительной мере основана на простом факте: любая допустимая программа ANSI С также является программой C++, делающей примерно то же самое.
Я считаю C++ интересным языком. Нет, не потому, что мой компилятор может выдать бессвязную цепочку ошибок, если я забуду включить все заголовки для умиротворения гневных богов STL. И не потому, что круг его сторонников достиг устойчивого состояния и теперь начинает медленно сужаться. C++ интересен тем, что история завоевания им сообщества программистов стала для меня хорошим уроком. Избранная им тактика была обманчиво проста, и все же многие технологи, особенно системные архитекторы, редко осваивают ее.
Чтобы понять, что произошло, необходимо запустить машину времени. До Р2Р, до появления спама, до появления Web, еще до того, как Интернет хотя бы отдаленно приблизился к массовым технологиям - нужно вернуться к тому времени, когда компьютеры Macintosh еще работали на классических чипах Motorola 68000. C++ родился в мире, в котором явно должен был доминировать язык С. В конце 1980-х годов С стал основным языком многих выпускников в области компьютерных технологий. Он был достаточно уважаемым для преподавания на университетском уровне и достаточно быстрым для применения в деградирующей предметной области, называемой «реальным миром». Реальная угроза владычеству С исходила разве что от таких мощных конкурентов, как Pascal, Basic, FORTRAN и Cobol. Pascal недолго грелся в лучах славы, но обгорел в них. Basic завоевал свою долю рынка, однако так и не смог стереть темного пятна со своего происхождения, сколь бы несправедливой не была такая участь. Остаются всего два реальных претендента. FORTRAN предназначался для инженеров с логарифмическими линейками, a Cobol был… Cobol, и этим все сказано. В
С идеальным образом (на тот момент) сочетались уважаемый язык программирования и практичный деловой инструмент. С этих позиций он захватил рынок разработки программного обеспечения.
Конечно, я не забыл, что было немало других языков. Был язык Ada, но вся его привлекательность сводилась к 800-страничным требованиям от Министерства обороны США. Остальные потенциальные конкуренты - Modula, CLU, Smalltalk, Prolog - так и не смогли найти свою рыночную нишу, потому что они упустили потребности своей главной аудитории: студентов. Эти языки не вмещались в «персоналки», стоящие в общежитиях, не говоря уже о студенческих мозгах. В рамках отрасли ни один язык не обосновался так глубоко, как FORTRAN, Cobol и Basic, в таком широком масштабе областей разработки. В любой отдельной системе, использовавшей эти классические языки программирования, обеспечивалось более или менее пристойное сосуществование между ними. Взаимодействие никогда не было идеальным, и все же оно несомненно было реальным. В зависимости от операционной системы было возможно обращение к Cobol из FORTRAN, и даже к FORTRAN из Basic. Была возможна совместимость на уровне компоновки.
Мощь этого тройственного союза не только прекратила все споры среди сообществ. Она означала, что дорогостоящие бизнес-консультанты, пишущие на Cobol, с определенной вероятностью могли приспособить для своих целей статистический пакет, написанный на FORTRAN. Результат всегда выглядел уродливо, но таково большинство интеграционных проектов в реальном мире. Во всяком случае, группы смогли дополнять друг друга через общее поле, которым в большинстве сред был компоновщик.
Не будем забывать, что у Мас состоялся ранний академический роман с сообществом Pascal, в результате которого родилась конвенция вызова Pascal и пристрастие к строкам Pascal. К счастью, Мас исцелился от этой глупости. Несмотря на все неудобства, С и FORTRAN продолжали взаимодействовать с Мас. Язык программирования С очень естественно подошел для этого маленького, спокойного мирка. В большинстве систем функции С могли вызываться из FORTRAN, и наоборот. В любой конкретной системе С мог занимать доминирующее, подчиненное или равное положение со своими «коллегами» в контексте разработки. Почему это так важно? Потому что для того, чтобы любая новая технология прижилась, она должна успешно интегрировать все существующее наследие, на месте которого она желает доминировать. Другими словами, нельзя требовать у организации, чтобы она переписывала все программы заново. Используйте то, что уже есть, и вы поможете делу.
Так что язык С пришел как помощник. Очарование C++ кроется в том, что при первом появлении он тоже представляется помощником, но при достаточном поощрении превращается в завоевателя, а в конечном счете - в нового владыку, перед которым все должны склониться. Язык C++ намеренно проектировался так, чтобы в нем вместилось как можно больше аспектов существующего языка С. Только самый наблюдательный адвокат C++ сможет выделить те области, в которых совместимость с С не сохранилась.
Что же дает эта «родовая принадлежность»?
Программисты С могут легко, почти незаметно, перейти на компилятор C++ Да, в ту раннюю эпоху существовали различия в быстродействии… да, у компиляторов C++ были свои странности. Многие программисты С принимали слишком близко к сердцу эти педантичные выходки. Непредсказуемые предупреждения о необъявленных функциях снились им по ночам, а если и это не пронимало - от высокопарной болтовни о чудесной силе объектно-ориентированного программирования им становилось стыдно, что они пользуются этим компилятором.
Но в действительности все это означало, что программисты С могли и дальше программировать на С, просто присоединяя несколько новых букв к вызовам компилятора, и мир нисколько не изменился. Вернее, еще не изменился. Но ловушка уже была расставлена.
C++ упростил переход, потому что он легко поглотил всю функциональность в существующей области С. Ничего не надо было переписывать заново. Достаточно было внести единственное изменение: объявить все старые функции с волшебными словами «extern С», и они легко поглощались C++.
За предшествующие годы взаимодействие между функцией С и функцией FORTRAN требовало определенных усилий и понимания того, как устроены эти два мира.
Как передаются вещественные значения? Производится ли передача по ссылке или по значению? Как устанавливается соответствие между логическими возвращаемыми значениями? В C++ все работало иначе. А вернее, просто работало.
Это обстоятельство дало весомые аргументы сторонникам C++, появлявшимся в организациях С. Они могли легко разрабатывать новую функциональность без потери готовой кодовой базы. Они всего лишь добавляли новый уровень в существующую систему. Вдобавок C++ позволял объявлять функции так, что даже ветераны С старой школы могли пользоваться ими. Конечно, старая гвардия С не могла получить доступ к новомодным классам и шаблонам, но это устраивало обе стороны. Преобразованные имена, вводимые компилятором C++, воспринимались как умеренное чудачество.
Поначалу C++ не создавал угрозы для ветеранов. А если организация росла, ветераны постепенно уходили в руководство, поэтому вскоре их мнение перестало быть слышным. Именно здесь наступает поворотный момент, когда C++ начинает играть мускулами. Язык не только задействует возможности существующей кодовой базы, но и предлагает своего рода попурри, «шведский стол», бесконечный источник всевозможных «примочек» и удобных возможностей, которыми может воспользоваться любой разумный разработчик.
Язык C++ никогда никому не навязывал новые возможности. Не будем путать позицию языка с позицией его ревностных последователей в сообществе. Если вы не хотели использовать новые объектно-ориентированные средства - вы их не использовали. Но они были такими соблазнительными, не правда ли? Они отливали золотым блеском, и работать с ними было очень интересно. А вы были молоды. Вы не видели ничего лучше. Вам были нужны деньги. И вообще это было интересно. Казалось, что C++ может исполнить все мечты в области программирования.
Все начинается с мелких изменений. Изменяется стиль комментариев - /* */ превращается в //. Затем объявления переменных свободно расставляются посреди функций. Просто и вроде бы незначительно, но эта возможность пришлась по сердцу многим разработчикам.
Затем начинается неизбежное. Ссылки прокладывают путь в объявления функций. Неопытный разработчик начинает возиться с перегрузкой функций, что приводит к обязательному применению корректировки имен (name mangling). Теперь на пути других языков программирования из прошлого возникает огромная стена. Структуры превращаются в классы с виртуальными функциями. Классы обзаводятся нетривиальными конструкторами, а критические функции высокого уровня начинают генерировать исключения. Затем наступает время головоломных архитектур с множественным наследованием. В этой фазе у «традиционных» языков программирования не остается надежд на участие.
К моменту завершения метаморфозы становится слишком поздно. Возврата к прошлому нет. Красота эволюционного процесса состоит в том, что чем больше кодовая база насыщается специфическими возможностями C++, тем труднее вернуться к прошлому. Код порождает необходимость дальнейшего использования C++, а само его существование служит катализатором процесса.
С учетом трудностей, создаваемых компоновщиками в большинстве современных операционных систем, C++ приходится идти на сверхъестественные выкрутасы, чтобы его перегрузка функций была доступна для простых смертных. Но именно глупость происходящего служит лучшей защитой. Когда в игру вступают скорректированные имена, у остальных классических языков уже не остается возможности «играть на равных». Ловушка захлопнулась. Возврата к прошлому нет. C++ предпринял классический маневр: охватить, расширить, подавить. Троянский конь. C++ использовал проверенный временем метод, чтобы покорить сообщество и направить его на новую миссию.
Слишком часто мы, разработчики, полагаем, что радикальные изменения непременно сопряжены с большими, неделимыми, глобальными событиями, стоящими на развилке пути. Нам представляется, что изменения всегда сопровождаются корпоративными приказами, отраслевыми инициативами, потоками пресс-релизов и тщательно подготовленными презентациями PowerPoint. Но как и в области тектонических сдвигов и эволюции, великие и долгосрочные изменения также могут происходить постепенно в результате тщательно спланированных действий. Эффект дополнительно усиливается, если разработчики могут использовать уже существующую базу.
