воскресенье, 19 марта 2017 г.

[prog.thougts] В очередной раз о нотации (в применении к C++)

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

Дело в том, что в C++ нет общепринятого и стандартизированного соглашения о стиле оформления кода. На мой взгляд, это есть хорошо, но это мое личное мнение. Важнее то, что в C++ сообществе спокойно сосуществуют и активно используются совершенно разные стили именования. В STL и Boost-е, как мне кажется, традиционный C/C++ стиль. В Qt, wxWidgets и в POCO -- более привычный для Pascal/Delphi/VisualBasic/Java/C#. В библиотеке ACE вообще свой собственный, неповторимый стиль, заимствующий хорошие элементы как из snake_case, так и из CamelCase.

Мы же уже очень давно используем snake_case стиль, но с некоторыми очень важными дополнениями. В частности, у нас для имен типов используются суффикс _t. Например, у нас тип агента называется agent_t, а не agent. А тип сообщения называется message_t, а не message.

К суффиксу _t в мире C++, как мне думается, отношение довольно своеобразное. Давным-давно от суффикса _t стремились отказываться, т.к. это выглядело темным наследием plain old C. В C-шном коде суффикс _t давали, как правило, именам typedef-ов. Например, писали что-то вроде typedef struct my_type {...} my_type_t;.

Но в последние годы, после выхода C++11 и, особенно, после выхода C++14, суффикс _t в C++ опять возвращается, но уже в специфической роли. Например, начиная с C++14 в стандарт языка добавляются сокращенные определения, вроде enable_if_t<C,T> вместо enable_if<C,T>::type. Так что теперь в C++ для суффикса _t появляется вполне определенная нише. И использование данного суффикса для других целей способно запутать стороннего разработчика (разорвать шаблон, так сказать).

Чтобы быть "ближе к народу", мы у себя попробовали провести небольшой натурный эксперимент. И для одной своей новой разработки попробовали отказаться от _t в пользу традиционного для STL/Boost стиля именования сущностей.

Результат нам не понравился. И если при написании кода отсутствие суффикса _t хоть и мешает, но приспособиться можно, то вот при чтении кода имена типов без привычного уже суффикса _t крайне тяжело выделять из кода. Так что читать чужой код написанный в стиле STL/Boost значительно тяжелее, чем код в нашей привычной нотации. Посему эксперимент был признан неудачным, код мы вернули к старому оформлению. Причем решение вернуться назад мы приняли намного легче, чем решение провести этот самый эксперимент :)

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

PS. Если бы мне сейчас предстояло выбирать нотацию для C++ного кода, я бы взял уже привычную нотацию со snake_case, с использованием префиксов m_ для полей структур/классов и g_ для глобальных переменных. А вот для пространств имен и имен типов сделал бы небольшое изменение: первая буква в таких именах должна была бы быть заглавной. Получилось бы что-то вроде So_5::Impl::Simple_mtsafe_st_env_infrastructure_details::Actual_elapsed_timers_collector вместо текущего so_5::impl::simple_mtsafe_st_env_infrastructure_details::actual_elapsed_timers_collector_t (имена, кстати говоря, реальные).

Отправить комментарий