вторник, 15 января 2019 г.

[prog.c++] О чем не нужно забывать бросаясь какашками в C++

Конец 2018-го года и начало 2019-го сопровождалось каким-то невиданным количеством критики в адрес языка C++. Что лично у меня, как нехило вложившегося в разработку инструментария для C++, вызвало тяжелые ощущения. Как-то не очень приятно, когда на полянку, которую ты много лет тщательно расчищал и облагораживал, какие-то странные люди вываливают несколько тележек дерьма, а потом еще и начинают радостно разбрасывать его во все стороны.

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

Но позволю себе немного старческого брюзжания и морализаторства на тему того, что современная молодежь (а, временами, и не молодежь), не обладая должным кругозором и опытом, не может или хочет, видеть картину во всем ее многообразии. Посему попробую перечислить несколько важных факторов, которые нужно принимать во внимание, разговаривая о C++ и его проблемах.


Начнем с того, что C++ сложно считать универсальным языком программирования. Он универсальный в том плане, что на C++ можно решать задачи из разных предметных областей. Но при этом C++ создавался, по-моему мнению, как нишевый язык. С достаточно узкой нишей применения: сложные задачи, в которых нужно выжимать максимум из оборудования. Т.е. либо максимальная производительность, либо хороший контроль за ресурсоемкостью. Либо и то, и другое. При высокой изначальной сложности решаемой задачи.

Но исторически сложилось так, что когда C++ появился на широкой публике, техника была слабой, потребности в разработке нового софта -- большими, а опыт массового софтостроения был никакой. И так уж вышло, что из массы языков подобного толка (Ada, Eiffel, Objective-C, Modula-2, Oberon, Modula-3, ObjectPascal) именно C++ оказался наиболее востребованным массами.

Со временем компьютеры стали мощнее, появилась возможность писать софт на безопасных языках с GC. Был накоплен опыт для организации производства софта. Характер решаемых задач изменился, прикладного софта сейчас пишется сильно больше, чем инфраструктурного, сам прикладной софт стал другим (пришествие Web-а и вот это вот все).

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


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

Это привело к нескольким архиважным последствиям.

Во-первых, в C++ сообществе произошел интересный перекос. Пользователей языка можно, условно, разделить на тех, кто пишет прикладной код и тех, кто разрабатывает библиотеки, на базе которых первая категория пользователей как раз прикладной код и пишет. Так вот, в C++ есть сильный перекос в плане "значимости" или "авторитетности" в пользу второй категории, т.е. в сторону писателей библиотек/инструментов.

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

Как следствие сперва получаются книги вроде "Modern C++ Design", а потом библиотеки вроде Boost.Hana и ranges.v3. Которые оказывают огромное воздействие на C++ сообщество. Но в самом сообществе лишь небольшой процент разработчиков способен разобраться в коде этих самых библиотек.


Далее перейдем к тому, что C++ в настоящий момент -- это такой же "зонтичный" термин, как и Lisp. Насколько я знаю, самого по себе Lisp-а не существует, есть разные его диалекты: Scheme, Common Lisp, Clojure и т.д. И можно рассуждать о Lisp-е вообще, но когда дело доходит до конкретного кода, то нужно серьезно сужать предмет разговора: о коде на Scheme ли мы говорим или о коде на Common Lisp-е.

Вот так же и с C++. Есть стандарт языка. А есть куча программ, написанных на своих подмножествах этого языка.

Есть отдельный мир Qt-разработчиков. Есть мир реального времени и gamedev-а. Есть мир высокопроизводительных вычислений. Вроде как там один и тот же язык, но используется этот язык сильно по-разному. Настолько, что нельзя просто так взять большой кусок кода из программы для одной из этих ниш и 1-в-1 переиспользовать его в программе для другой ниши.


Ну и нельзя не отметить тот факт, что сам по себе прецедент C++ для индустрии софтостроения уникален. Язык развивается более 30 лет и он действительно развивается. При этом оставаясь весьма себе востребованным.

Не так-то просто вспомнить другие подобные образчики. Скажем, COBOL. В принципе, он развивается и активно используется. Но увидеть COBOL в "дикой природе" дано далеко не каждому. Или Fortran. Так же развивается и так же используется. Но за пределами научных вычислений про Fortran мало кто знает. Да и сам Fortran там не нужен.

Наиболее близок, имхо, пример языка Ada. Так же развивается, так же может использоваться в разных нишах. В принципе может. Только вот C++ применяется гораздо шире.

Проблема с этой ситуацией в том, что для нас, т.е., для людей, вполне естественной выглядит сценарий, когда что-то появляется, развивается, затем ветшает, разрушается и исчезает. Вот, скажем, появился язык Modula-2. Развился, заявил о себе. Использовался и об этом было известно. Потом постепенно он исчез с радаров и для большинства разработчиков этот язык умер.

А вот с C++ не так. Он должен был бы повторить судьбу Modula-2 и еще кучи других языков. Но не повторил. Это ломает наш шаблон. Мы понятия не имеем, как дело пойдет дальше. Для нас было бы естественно ожидать, что C++ должен умереть и исчезнуть. Но этого не происходит. Более того, этого не может произойти в ближайшие годы, т.к. сейчас значимость для C++ индустрии слишком велика.

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

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


Напоследок же нужно сказать пару слов про практическую значимость набросов на C++.

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

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

Если же попытаться дать какую-то практическую рекомендацию, то она будет такой: язык C++ нишевый, он предназначен для решения специфических задач. Если вы такие не решаете или не видите, как C++ может упростить вам вашу работу, то просто не берите C++. Альтернатив сейчас как никогда много.

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


Ну и на правах рекламы: мы делаем OpenSource инструментарий для C++, который упрощает жизнь обычного C++ разработчика (например, RESTinio и SObjectizer). Не сомневайтесь, упрощает, проверено неоднократно. Так вот, если в наших продуктах вам чего-то не хватает, то дайте знать, чего именно. Постараемся сделать. И ваша жизнь с C++ станет еще проще ;)

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