пятница, 30 марта 2018 г.

[prog.thoughts] Тяпничное про оглядки на старые версии C++ компиляторов

В последнее время довелось прилично порефлексировать на тему того, как C++ развивается в последние годы. Какие последствия это может иметь вообще для разработки на C++. И для нас, небольшой софтверной компании, которая активно занимается OpenSource библиотеками для C++.

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

Возможно, на заре моей программерской деятельности это было не совсем так, поскольку тогда и C++ весьма активно развивался, и сами платформы активно развивались и вытесняли друг друга (например, многие ли помнят, как 16-битовый Windows пытался бороться с 16-битовым MS-DOS, а всех их уделывала 32-х битовая OS/2, которая затем не смогла устоять перед Windows-95 и Windows-NT?). Ну и плюс к тому, мы сами тогда работали над новыми, перспективными проектами и не сильно были знакомы с понятием legacy (под "мы" здесь понимаются те небольшие коллективы, в которых мне довелось поработать в 1990-х).

Но вот года с 1998 или 1999-го оглядываться на то, что у тебя самого или у кого-то из твоих клиентов может быть далеко не самый новый C++ компилятор, и что у этого компилятора могут быть какие-то заскоки по части поддержки той или иной части C++... Вот на это оглядываться уже приходилось. Отлично помню момент, как на рубеже 2000-го года под каким-то из Linux-ов довелось поработать с gcc версии, кажется, 2.95, который не умел нормально ловить исключения при использовании наследования. Т.е. если у тебя есть базовый тип Exception, и есть наследник FileNotFoundException, ты бросаешь FileNotFoundException, а ловишь его по ссылке на Exception, то исключение просто не ловилось. Пришлось тогда в каком-то проектике отказываться от иерархии исключений.

Да, так вот с конца 90-х и до сего времени приходится задумываться о том, что кто-то может еще сидеть на каком-то специфическом Linux-е с проплаченной на 10-ть лет коммерческой поддержкой. А там, дай Бог, если gcc-4.8, а то может быть и какой-нибудь gcc-4.4. И, что самое печальное, я сам до недавнего времени считал, что такие оглядки -- это вполне себе нормально и забота о потенциальных пользователях, которые не могут переходить на новые версии компиляторов -- это разумно и оправдано.

Но в последние дни мое отношение к этой ситуации начало меняться. Не то, чтобы это произошло внезапно. В общем-то с SObjectizer-ом мы ограничились поддержкой на уровне gcc-4.8 и msvc-12.0. Была попытка опуститься до gcc-4.7, но там уж совсем все было грустно, поэтому плюнули. Ну и для RESTinio мы сразу решили ограничиться только C++14 на уровне где-то gcc-5.4 и msvc-14.0. Там, однако, был расчет на то, что пока мы будем доводить RESTinio до версии 1.0, пройдет ну очень много времени. И минимум на уровне C++14 к тому времени будет казаться вполне себе нормальным. Пока что этот расчет оправдывается, т.к. прошел уже год с момента начала работ над RESTinio и скоро будет год с первого публичного релиза, а мы еще только на уровне версии 0.4 и впереди еще прорва работы.

Сейчас же я прихожу к мысли, что C++ с 2011-го года вышел на совсем другой темп развития. Мало того, что бумажные стандарты выходят каждые три года, так еще и основные компиляторы в последние годы очень быстро подтягиваются с поддержкой самых свежих стандартов. Это делает ситуацию совершенно не похожей на то, что было до C++11. В 2008-ом году, например, было вполне нормально оглядываться на то, что умеет поддерживать, скажем, VC++6.0. Потому, что в 2008-ом был только C++98 и VC++6.0 в изрядной степени C++98 поддерживал. Но в 2018-ом году оглядываться на то, что поддерживает VC++12.0, наверное, уже не разумно. Жизнь слишком коротка для того, чтобы ждать, пока плюшки и вкусности из C++17 станут тебе доступны потому, что уже прошло 10-15 лет после принятия 17-го стандарта и практически никто уже не использует VC++12.0 (хотя я уверен, что в 2028-ом еще найдется какой-нибудь ынтерпрайз, который будет завязан на 12-ю версию VC++). Плюс к тому, конкурирующие технологии развиваются еще быстрее. И в таких условиях сложно находить для себя убедительные объяснения того, почему я не могу использовать std::optional из C++17, если его аналоги уже много лет как есть в стандартных библиотеках каких-нибудь Scala или Rust.

Еще один веский довод -- это постоянно возрастающий объем и сложность наших OpenSource проектов. Тот же SObjectizer за прошедший 2017-й год увеличился в объеме и сложности более чем прилично (если считать вместе с so_5_extra). Что уж говорить про RESTinio. Соответственно, добавление новой функциональности в OpenSource-проекты требует все больше и больше усилий. И не так-то просто оправдать те усилия, которые тратятся на поддержку старых компиляторов. Особенно с учетом того, что OpenSource-проекты распространяются бесплатно.

В связи с этим я думаю, что в современных условиях, особенно с поправкой на то, как развивается C++ и какие изменения нас ждут в C++20, мне кажется вполне разумным для своих проектов ограничится поддержкой всего двух стандартов C++: самого последнего и предпоследнего. Т.е. на данный момент это C++17 и C++14. Соответственно, когда появится C++20, поддержка C++14 закончится. А для новых проектов, которые еще только-только стартуют и достигнут стабильности лишь в отдаленной перспективе, можно ограничится вообще только последним стандартом.

К чему это может привести на практике?

SObjectizer-5.5 будет требовать не более чем gcc-4.8 до апреля следующего года. Мы пару лет назад пообещали, что SObjectizer-5.5 будет привязан к gcc из Ubuntu 14.04 LTS. И от этого обещания мы не отказываемся. С поддержкой VC++12.0 сложнее. Скорее всего, мы на нее забьем после выхода очередной VisualStudio. Т.е. как только появится VisualStudio-2018, так мы сразу же перестанем оглядываться на VC++12.0.

Другой вопрос -- это насколько активно будет дальше развиваться SO-5.5? Сейчас мы работаем над версией 5.5.22. Затем, возможно, будет еще и 5.5.23. И, может быть, после этого ветка 5.5 перейдет в режим поддержки. А развиваться будет новая, нестабильная ветка 5.6, в которой мы будем закладываться уже на C++17. Но тут мы посмотрим еще на то, что за gcc будет в Ubuntu 18.04 LTS и на то, когда у нас появятся ресурсы для начала работ над 5.6.

RESTinio, по крайней мере, в этом году, будет требовать C++14. В следующем году посмотрим, выгодно ли нам держаться за C++14 или же проще и дешевле ограничится только C++17.

Вот как-то так. Имхо, времена изменились. И сейчас местами даже C++14 уже может быть слишком старым, чтобы ориентироваться на него. Что уж говорить про C++11 и, тем более, C++98/03.

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