пятница, 18 января 2019 г.

[prog.thoughts] "C++ vs others" через призму "поддерживающих" и "подрывных" технологий

В комментариях к предыдущей заметке "О чем не нужно забывать бросаясь какашками в C++" у меня с Григорием Демченко развернулся спор. Полагаю, что следует обозначить контекст, на который я опирался в этом споре. В противном случае некоторые тезисы (например, о том, что 5 лет -- это небольшой срок для ИТ) выглядят странно, если не сказать больше.

Контекст продиктован вот этой замечательной книгой: "Дилемма инноватора: Как из-за новых технологий погибают сильные компании". Одна из идей, которая лежит в ее основе, такова: есть "поддерживающие" технологии, которые плавно и постепенно улучшают качество уже существующих товаров/услуг/сервисов. А есть "подрывные" технологии, которые сразу после своего появления на свет не могут составить конкуренцию уже существующим технологиям. Поэтому "подрывные" технологии сперва используются в каких-то маргинальных рыночных нишах, там обкатываются, совершенствуются, постепенно проникают на старые рынки и вытесняют оттуда технологии, которые считались устоявшимися.

Яркий пример, который можно привести -- это цифровая и пленочная фотография. К 1980-м годам пленочная фотография была доминирующей технологией. Вокруг которой существовала целая индустрия. При этом сами фотопленки постоянно улучшались, как и пленочные фотокамеры. Развитие пленочной фотографии в конце XX и самом начале XXI-го веков -- это и есть поддерживающие технологии.

Но в 1980-х, когда пленочной фотографии, казалось бы, ничего не угрожало, появляется технология цифровой фотографии. Которая была на тот момент настолько дорогой и несовершенной, что замена пленочной фотографии на цифровую выглядела совершенной фантастикой. Поэтому до начала XXI-го века цифровая фотография была маргинальной технологией, которая применялась эпизодически в каких-то узких нишах и на конкурента массовой пленочной фотографии никак не тянула.

Но технология цифровой фотографии непрерывно развивалась, появлялись ниши, в которой только она и могла быть использована (в частности, камеры для мобильных телефонов). И, постепенно, цифровая фотография проникла и в те сегменты где пленочная фотография ранее властвовала безраздельно. Сперва цифровые фотокамеры были гораздо дороже, чем их пленочные аналоги, производили фотографии намного худшего качества, да еще и не предназначенные для печати в большом формате. Но зато у них были качества, которые в принципе не могла обеспечить пленочная фотография. И эти качества стали двигателем развития цифровой фотографии. Из-за чего буквально за 10 лет (на моей памяти это период с 2002-го по 2012-й) цифровая фотография буквально обратила пленочную фотографию в прах. Теперь уже пленочная фотография является маргинальной технологией, которая ушла в узкие ниши, которые неинтересны/невыгодны производителям цифровых фотокамер.

Для ИТ-шников ярким примером, демонстрирующим это же явление, является появление в конце 1970-х и начале 1980-х такой штуки, как персональные компьютеры. Которые тогда мало кем рассматривались более чем игрушки. И которые, в принципе, не могли составить конкуренцию тогдашним большим и средним ЭВМ. Но прошло где-то 15-20 лет и такого явления, как средние ЭВМ, не осталось. Большие ЭВМ остались, но они стали маргинальной технологией, тогда как доминирующие позиции занимают персоналки и их производные (к коим можно отнести современные многопроцессорные сервера). Но при этом и позиции самих персоналок в последние 10 лет подрываются смартфонами и планшетами, которые сами еще лет 10-15 назад были в зачаточном состоянии и рассматривались скорее как игрушки, чем серьезные инструменты.


Так вот, после столь длинного лирического вступления, можно вернутся к разговору про C++, про период застоя в его развитии и про то, насколько изменилась бы судьба C++, если бы этого периода не было.

На мой взгляд, реальным периодом застоя в развитии C++ стал период с 1998-го по 2003-й год, т.е. промежуток между принятием стандартов C++98 и С++03. Тогда как период с 2003-го по 2011-й назвать периодом застоя не получается, т.к. работа над C++0x шла, шла она достаточно напряженно, а результатом явился уже совсем другой C++. Кроме того, к 2003-му году уже стало понятно, что C++ неизбежно должен будет сдать свои доминирующие позиции.

Т.е., на мой взгляд, если бы C++ принципиально изменился уже в стандарте C++03 (например, в язык добавили бы move-semantic, auto, lambdas, variadic templates, enum class), то у него было бы чуть-чуть побольше шансов побороться за место под Солнцем. Но разве что чуть-чуть. Принципиально картинка бы все равно не изменилась бы.

Теперь попытаюсь пояснить, почему я так думаю.

Дело в том, что в момент своего появления в 1985-ом году C++ оказался в категории "подрывной" технологии. Фактически, C++ показал, как можно бороться со сложностью за счет использования ООП, но при этом иметь эффективность языка C. Что и привело к тому, что C++ за 10 лет стал настоящим мейнстримом и доминирующей технологией для разработки, скажем, десктоп-приложений.

Но затем C++ перешел в категорию "поддерживающей" технологии. И развитие С++, которое мы, к счастью, наблюдаем до сих пор, -- это есть плавная эволюция которая постепенно и последовательно улучшает разработку софта на C++. Но сама разработка на C++ становится маргинальной и уходит в те узкие ниши, где это оправдано и где невыгодно использовать другие технологии, в том числе и доминирующие сейчас.

В 1990-е мы могли наблюдать появление и развитие "подрывных" технологий, которые со временем стали доминирующими и существенно потеснили язык C++.

В первую очередь это Java. Которая изначально целилась в очень узкую и специфическую нишу апплетов. И за пределами которой в 1995-1996 годах, когда Java вышла в мир, эту самую Java было сложно представить. Как из-за крайней убогости первых версий языка Java, так и из-за производительности первых JVM.

В эту же историю можно записать и C# с .NET-ом, который, на мой взгляд, всего лишь попытка сделать "правильную Java для Windows".

Еще одна интересная история с другой "подрывной" технологией -- это JavaScript. Опять же, изначально это был совершенно примитивный язык для очень узкой ниши. В которой, однако, не было других серьезных конкурентов, из-за чего JavaScript сумел развиться. И спустя 20 лет после своего появления JavaScript является языком для разработки всего приложения, а не только для добавления элементов динамики на статические Web-странички.


Почему же Java и C# (и, отчасти, JavaScript) подорвали доминирующие позиции C++?

Потому, что эти языки обладали качествами, которыми в принципе не обладал C++. За счет чего Java и C# вначале прощались их недостатки.

Во-первых, это продуктивность разработчика для решения обыденных бизнес- и около-бизнес-задач. Повышению продуктивности способствовало множество факторов.

Например, Java/C# были языками с гораздо более простым синтаксисом и семантикой, что привело к появлению мощных IDE с подсказками, рефакторингами, анализаторами кода и пр. плюшками. Рискну предположить, что мощные IDE, массово появившиеся в конце 1990-х, очень сильно изменили подходы к разработке ПО.

Еще один пример: наличие GC и объемной стандартной библиотеки. За счет чего существенно упрощается написание сторонних библиотек. А так же использование сторонних библиотек. В результате чего количество сторонних библиотек для Java и C# (не говоря уже про JavaScript) стало расти такими темпами, которые для C++ и не снились.

Еще один пример: количество способов, которым можно решить задачу. Плюс отсутствие пресса высокой производительности и низкой ресурсоемкости. Это в C++ перед разработчиком стоит выбор: решать ли задачу в стиле Cи, в стиле "Си с классами" или же обмазаться шаблонами по заветам Александреску? Сколько это будет стоить? Как избежать лишних аллокаций и т.д. Java и C# разработчики, в большинстве случаев о производительности и ресурсоемкости могут не думать.

Еще один пример: хорошее абстрагирование от особенностей ОС. C++ был слишком близок к железу и ОС, из-за чего написать код, который одинаково хорошо работает и на Linux-е, и на Solaris-е, и под Windows -- это была та еще задачка. В которой нужно было заморочится и разрядностью, и порядком следования байт, и особенностями выравнивания данных, и API конкретной ОС, и особенностями компиляторов.

В общем, в Java и C# рядовой разработчик мог просто взять и начать писать конкретный прикладной код, да еще в удобной и умной IDE.

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

Так вот, ключевыми и очевидными все эти факторы для большого количества разработчиков стали как раз в конце 1990-х и начале 2000-х. А в это время C++ толком и не развивался :(

Вот если бы в 1998-2003 годах в C++ завезли что-нибудь, что смогло бы серьезно увеличить продуктивность разработчика на C++, тогда у C++ могли бы быть шансы побороться. Но вряд ли большие. Поскольку принципиально C++ язык из совсем другой категории, нежели Java и C#, не говоря уже про JavaScript и пр. динамически-типизированные языки.

Кстати говоря, язык Go так же можно рассматривать как "подрывную" технологию. Которая стартовала в узкой нише. И которая обладает качествами, которых нет у ближайших конкурентов, претендующих на ту же нишу: крайняя простота, высокая скорость, компиляция в нативный код и отсутствие "тяжелого" рантайма. Плюс очень простой, удобный и понятный способ решения проблем многопоточного программирования: встроенная в язык поддержка модели CSP.

Теперь пару слов о том, является ли период в 5-6 лет для ИТ коротким или длительным сроком.

Это зависит от того, про какую технологию мы говорим. Если про "поддерживающую", то 5-6 лет -- это немного. Взять, например, C++11. Появился восемь лет назад. Но до сих пор огромное количество проектов не могут использовать С++11 в полной мере. Тоже самое можно увидеть и в мире Java: насколько сильно Java изменилась за последние 5 лет? Как много проектов на Java за эти 5 лет смогли перейти на использование современных версий Java?

Но вот если мы говорим про "подрывные" технологии, то для них 5 лет может быть очень большим сроком. Скажем, Go за пять лет смог стать достаточно широко используемым языком. Какие-нибудь Ruby-On-Rails и Docker через пять лет после своего появления вообще стали доминантами в своих областях.

Другое дело, насколько "подрывная" технология способна оказать влияние на всю ИТ-индустрию. Вот, скажем, язык Java оказал такое влияние. Но для достижения тотального доминирования Java потребовалось лет 10. Тогда как Ruby-On-Rails, не смотря на свою взрывную популярность в 2006-2008 годах не стал доминирующей технологией для разработки Web-приложений: PHP, Java, C#, Python и другие языки как применялись, так и применяются.

Ну и добавлю сюда то, что сама история ИТ становится все длиннее и длиннее. Скажем, в 1990-ом история ИТ насчитывала, грубо говоря, 45 лет. И на этом фоне 10 лет бурного развития персоналок (с 1980-го по 1990-й) -- это был просто гигантский кусок истории ИТ. Тогда как в 2019-ом история ИТ -- это уже почти 75 лет. И на этом фоне 12-ти летняя история iPhone (с 2007-го по 2019-й) воспринимается уже не так драматично. Хотя iPhone, как родитель современных смартфонов, отъедающих рынок у традиционных персоналок, оказал серьезное влияние на развитие ИТ.


Некоторые вещи я затрудняюсь однозначно классифицировать в качестве "подрывных" или "поддерживающих" технологий.

Например, появление Delphi в середине 1990-х. Вроде как это был прорыв. Но, с другой стороны, это был результат 10-ти летней истории развития как языка ObjectPascal, так и линейки продуктов Turbo Pascal.

Или тот же iPhone, который и создал рынок "смартфонов". Хотя этому предшествовали и неудачный Newton от Apple, за которым последовал мегауспешный Palm, умерший из-за недальновидного менеджмента под влиянием WinCE и iPhone. А так же WinCE-устройства. И BlackBerry. Т.е. iPhone стал мегауспешной компиляцией лучшего, что было до него.


О некоторых вещах удается судить только по прошествии времени. Например, сейчас я пишу о достоинствах Java и C#, которые позволили этим языкам подорвать доминирование C++ в начале 2000-х. Хотя сам я в то время не понимал этих достоинств и считал их несущественными. Как и не осознавал десять лет назад, что убогая примитивность Go и является его основной киллер-фичей.

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

Комментариев нет: