Показаны сообщения с ярлыком Boost. Показать все сообщения
Показаны сообщения с ярлыком Boost. Показать все сообщения

пятница, 20 января 2023 г.

[prog.flame] И долго в Boost будут тащить все, что не попадя?

На включение в Boost претендует библиотека Aedis, ревью идет прямо сейчас. Aedis -- это написанный на Asio клиент для Redis-а.

Определенно нужная для кого-то вещь, спору нет. Автору библиотеки респект и уважуха на полном серьезе. Так что у меня нет никаких сомнений о нужности Aedis-а вообще.

Зато есть вопрос "А что сейчас есть Boost и зачем он нужен?"

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

Но клиент для Redis-а?

Его что, кто-то хочет видеть в стандартной библиотеке C++? Серьезно?

А раз нет, то какой смысл развивать Boost как сборище всякого разного и разнообразного? Зачем весь этот винегрет держать под одной крышей?

Простите мне мой цинизм, но я вижу в этом всего лишь одну цель: паразитирование на известности Boost-а.

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

Boost уже сейчас скопище из более сотни (если не ошибаюсь) библиотек. Причем даже с некоторым дублированием (сколько там сейчас библиотек для работы с конечными автоматами? сколько для парсинга?). Сам по себе вопрос "А вы знаете Boost?", который был актуальным году в 2005-ом, сейчас уже потерял смысл. А человека, который ответит на него "Да" мне будет сложно воспринимать всерьез.

Может быть включение в Boost гарантирует то, что авторов библиотек будут финансировать? Или есть гарантия, что библиотеку автоматически подхватят, когда первоначальный автор перестанет ей заниматься?

И ладно бы Boost задавал какую-то недостижимую планку качества, а библиотеки оттуда не имели бы никаких вменяемых альтернатив за пределами Boost-а.

Так ведь нет.

Какие-нибудь Catch2 или doctest могут быть намного более простыми и удобными альтернативами Boost.Test. А spdlog может быть удобнее и практичнее, чем Boost.Logging. А fmtlib чем Boost.Format.

Т.е. жизнь показала, что и вне Boost-а можно создавать отличного качества библиотеки, которые будут востребованы больше, чем аналоги из Boost-а.

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

Но нет, Boost продолжает вбирать в себя всякую всячину.


PS. Из личного: убежден, что если бы Beast не протолкнули бы в Boost, то ее популярность в C++ мире была бы сильно ниже. Впрочем, если кто-то взял в проект Boost.Beast просто потому, что "это же из Boost-а", то что тут остается сказать? Разве что "полной ложкой, говорю, черпай!"

PPS. Не в первый раз поднимаю эту тему. Но что поделаешь, если время идет, а смысла в существовании Boost в его привычном виде я как не видел, так и не вижу.

понедельник, 8 января 2018 г.

[prog] Не Boost-ом единым...

Разведка донесла, что в slack-канале Boost-а проскочила ссылка на RESTinio-0.4. В ответ на что Винни Фалько, автор Boost.Beast, запостил ссылку на этот issue с предложением задействовать Boost.Beast в реализации RESTinio. И добавил к этой ссылке фразу: "The old "boost bad" canard."

Хочется сказать, что Винни не прав. В том, что мы не стали делать RESTinio на базе Boost.Beast, нет никакого подтекста из категории "Boost -- говно". Попробую объяснить, почему мы не хотим добавлять Boost.Beast в зависимости к RESTinio. Хотя такая идея нами обсуждалась где-то в мае или июне 2017-го, когда стало известно о сроках проведения review для включения Beast-а в Boost.

Первая причина в том, что С++разработчики, как уж сложилось, делятся на тех, кто использует Boost, и на тех, кто Boost не использует. Нам сейчас не важно, по каким причинам кто-то не использует Boost. Важно, что такой факт имеет место быть. И что разработчиков, которые не используют Boost, не так уж и мало. Пусть даже таких, грубо говоря, всего 10%, но это все равно не 0%. Следовательно, если мы сделаем RESTinio на базе Boost.Beast, то эти разработчики просто не будут рассматривать RESTinio. Для нас эти разработчики, как потенциальные пользователи, будут потеряны. Тогда как если RESTinio не будет иметь Boost в зависимостях, то RESTinio смогут использовать и те, кто применяет Boost, и те, кто держится от Boost-а подальше.

Такова се-ля-ви. Если мы заложимся на Boost, то мы отрежем часть потенциальных пользователей. Нам это не нужно. Как бы представители секты "Boost -- это наше все" не выдрачивали на свой любимый фреймворк, вне Boost-а тоже есть жизнь. И нам она так же интересна. Тем более, что представители секты "Boost -- это наше все" крайне не любят смотреть на то, что в Boost не входит. Вот есть в Boost-е Beast, значит встраиваемый HTTP-сервер нужно делать именно на Beast. И похер на то, что это займет больше времени и кода, зато Boost и вот это вот все. Так что даже с точки зрения банального маркетинга в большой аудитории пользователей Boost-а процент тех, кто не удовлетворится Beast-ом и пойдет искать что-то еще, очень невелик. Посему ценность этой аудитории будет не выше, чем ценность аудитории тех, кто Boost не использует. Значит, нам тем более нет смысла терять аудиторию тех, кто не использует Boost.

Вторая причина в том, что Beast берет на себя слишком много. Закладываясь на Beast мы лишаем себя значительной части контроля над тем, что происходит с вводом-выводом и парсингом HTTP-протокола. Тогда как http-parser из nodejs (как и picohttpparser) в этом смысле гораздо менее требовательные. Это позволяет нам, например, встраивать контроль за тайм-аутами операций. И еще, к примеру, у нас остается возможность дать разработчикам выбор между HTTP-парсерами: сейчас поддерживается только nodejs-овский http-parser, но если будут пожелания от пользователей, то мы можем добавить альтернативы. Тот же picohttpparser. Или даже какой-то кастомный, заточенный под одну конкретную задачу.

Т.е. контролируя почти все, что связано с вводом выводом и обработкой прочитанных/записываемых блоков данных, мы имеем большую гибкость. А так же свободу развернуть RESTinio в нужном нам и нашим пользователям направлении. Тогда как с Boost.Beast мы такой гибкости не видим.

Подчеркну еще раз. Мы уже обсуждали тему перевода RESTinio на базу Beast-а. И коллективно решили, что это не в наших интересах. У разработчика Boost.Beast своя задача. У нас своя.

Мы хотим сделать инструмент, который был бы максимально удобен для конечного пользователя. Нужно пользователю создать HTTP-сервер? Пусть напишет всего 10 строк кода. Нужно ему, скажем, добавить какой-то механизм защиты от перегрузки? Пусть допишет еще 2 строки кода. Нужно пользователю убрать какую-то фичу за ненадобностью? Пусть поменяет одну строку из этих двенадцати. Имея собственную реализацию сервера мы можем это сделать. В том числе и потому, что мы можем затачивать под это используемые в реализации структуры данных и даже принципы работы фреймворка.

Тогда как у разработчика Boost.Beast, на мой взгляд, цели совсем другие. Beast представляет из себя низкоуровневый конструктор, из которого, при желании, приложив достаточно сил и времени, можно собрать что угодно. Для каких угодно целей. Но, повторюсь, приложив достаточно времени и сил.

Можно ли в RESTinio совместить то, что хотим мы, с тем, что закладывалось в сам Beast? Может быть и можно. Хотя, как нам представляется, не просто. И, если бы мы начинали делать RESTinio сейчас, после релиза Boost-1.66, вопрос реализации RESTinio на базе Beast-а можно было бы рассматривать более внимательно. Но начали мы делать RESTinio сильно раньше. И переходить на Beast сейчас, с учетом всего вышесказанного, вряд ли разумно.


Если кто-то думает, что мы из тех, кто принципиально не использует Boost, то это зря. Случается, что и используем. Следы этого на публике можно обнаружить, например, в прототипе интеграции SObjectizer-а и libmosquitto. Но когда речь заходит о библиотеке, предназначенной для широкого использования, то вопрос помещения Boost-а в список зависимостей перестает быть праздным.

понедельник, 18 декабря 2017 г.

[prog.flame] Тут вот Boost-1.66 подтянулся с Beast-ом...

...и уже пошли восторженные отзывы о том, как же круто иметь поддержку HTTP в Boost-е и как же народу хочется поиграться с Beast-ом.

Ну что сказать? Посмотрим, как много из тех, кто попробует, всерьез возжелает работать с таким низкоуровневым кодом. Ну, чтобы было понятно, вот штатный пример асинхронного сервера на Beast-е. Страшно не стало? Ну тогда попробуйте туда добавить, скажем, контроль тайм-аутов для соединений. Все еще не страшно? ;)

А ведь многие попробовавшие, наверняка, будут довольны. И будут пользоваться таким низкоуровневым API. Ибо копипаста рулит и бибикает.

ЗЫ. Этот пост вовсе не наезд на библиотеку Beast. Сама-то она очень круто сделано. Но надо понимать, что Beast -- это конструктор, который позволяет вам собрать все, что вы захотите. Только вот собирать вам все придется самостоятельно и из очень мелких кусочков. Посему не очень правильно рассматривать Beast как готовый инструмент для конечных прикладных разработчиков. Это набор базовых строительных блоков. Хороший набор. Но только набор. Так что это скорее наезд на восторженных неофитов, которые ждут какого-то чуда уровня Go-шного fasthttp. Чуда не будет ;)

пятница, 23 июня 2017 г.

[prog.c++.flame] Взять бы, да и закрыть Boost...

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

Вот просто взять и закрыть. Что вошло в Boost, то пусть там и остается.

А вот всем остальным нужно учиться жить без Boost-а.

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

Да и смысл Boost-а в настоящее время от меня ускользает. 17 лет назад Boost был полигоном для обкатки того, что хотелось бы включить в стандарт. Boost.Thread, Boost.SharedPtr, Boost.Optional и все такое. Ну OK, тогда это было актуально, когда работа над стандартами C++ велась не слишком быстро.

Но сейчас-то? Какой смысл в Boost-е кроме как в централизованной сборке относительно небольшого количества C++ных библиотек, которые совместно тестируется перед релизом? Ну кроме протекционизма?

Кстати о протекционизме. Вот есть в Boost-е библиотеки Boost.Test, Boost.Log, Boost.Format. Для которых существуют не менее достойные, мягко говоря, аналоги в виде Catch, Spdlog и Fmtlib. С какой стати старые и неудобные монстры, вроде Boost.Test и Boost.Log, должны иметь преференции в современном мире перед теми библиотеками, которые в Boost не входят? Ведь не так уж и редко от сторонних аналогов люди отказываются потому, что дальше Boost-а и не заглядывают. Но даже если и заглядывают, то иногда предпочитают Boost, потому что Boost к проекту уже подключен, а подтаскивание еще одной библиотеки в C++ный проект -- это боль для многих.

В общем, Карфаген должен быть разрушен Boost сделал свое дело, Boost должен уйти.

PS. Пост написан под влиянием боли, которая появляется, когда в зависимостях кросс-платформенного проекта оказывается достаточно свежая версия Boost-а.

пятница, 7 октября 2011 г.

[prog.flame] Наткнулся на свой старый список претензий к Boost

Будучи некоторое время активным RSDN-ером написал там множество комментариев. Через которые ко мне в блог и сейчас попадают люди. Интересно бывает перечитывать то, что писал N лет назад. Вот как в данном случае.

Так уж получилось, что на Boost я смотрел года с 2001-го, но в серьезную эксплуатацию никогда не брал. Самое большое – это использование Boost.Test в нескольких мелких проектах (откуда он теперь выпиливается). Почему так произошло – тема долгого разговора. Вкратце список того, что мне не нравится(лось) в Boost-е я описал вот в этом комментарии. Позволю себе его процитировать, поскольку прошло уже больше трех лет, а список до сих пор актуален:

1. Реализация boost-а исключительно сложна. Ну т.е., когда все идет гладко и в исходники библиотеки заглядывать не нужно, то нет проблем. Но, тем не менее, здесь есть два момента, которые мне не нравятся:
— ни в одном другом языке (а мне приходилось лазить в библиотеки Ruby, Eiffel, D, немного Java) мне не приходилось видеть такой разительной разницы в сложности реализации библиотек и прикладных приложений. По мне, это некий признак того, что что-то где-то не так;
— всегда приятно иметь увереность в том, что твоих знаний хватает для того, чтобы при необходимости разобраться в деталях с происходящим в твоем приложении. По крайней мере у меня не было проблем с тем, чтобы залезть во внутренности MFC, Qt, FOX, ACE. В случае с boost ситуация обратная -- тот же boost.variant сразу же отбивает желание понять, как же он устроен.

2. Некоторые вещи в boost-е направлены на предоставление разработчику инструментов, которые, по хорошему, должны были быть в языке. Пример: boost.lambda. Да и, насколько я понимаю, boost.mpl так же использует различные трюки для того, чтобы обойти существующие недостатки языка. По-моему мнению, это не нормально. Должен развиваться язык, а недостатки языка не должны скрываться за библиотеками, сложность реализации которых слишком высока (см.предыдущий пункт).

3. Некоторые библиотеки boost-а (тот же boost.lambda, а так же boost.spirit), на мой взгляд, являются примерами того, что не нужно делать. При этом у меня складывается впечатление, что наличие подобных вещей создает у C++программистов "головокружение от успехов" -- т.е. программирование на шаблонах в C++ становится модным направлением. Именно "модным", когда шаблоны применяются и к месту, и не к месту.

4. Boost велик. Слишком велик. 22Mb в tar.bz2 версии 1.35 -- это занадто. Имхо, для C++ поздно создавать одну большую стандартную библиотеку. Можно понять Sun с JDK и MS с .NET Framework, которые держат большие штаты программистов, поддерживающих JDK/.NET Framework. А кто будет поддерживать OpenSource-ный boost? Что произойдет, если кому-то из авторов включенных в boost библиотек надоест сопровождать и развивать свое творение? Или как разработчикам каких-то библиотек выпускать новые релизы вне графика выхода версий самого boost-а?

Далее, включение библиотеки в boost осуществляется по результатам review, в которых, обычно, едва набирается несколько десятков отзывов. Т.е. заявляется что-нибудь типа boost.egg и что? Находятся несколько ценителей прекрасного, которые присылают положительные review и egg в boost-е. И что из того, ценность буста повысилась? В то же время вне буста есть, например, crypto++, botan или cryptlib, которыми пользуются сотни, если не тысячи программистов, но которые никаким боком к boost-у не относятся.

Еще один момент. Библиотеки, которые являются альтернативными boost-овским, они что, уже второго сорта? Бустовская сериализация -- она лучше, чем s11n? Бустовские регулярные выражения лучше, чем PCRE? Бустовские юнит-тесты намного лучше CppUnit? Не получится ли так, что когда разработчику понадобиться что-то, то он просто возмет реализацию из boost-а даже не глядя на альтернативы? Т.е. выбор будет строится не на возможностях, а на репутации. Как бы в результате boost не стал монополистом, который своей массой будет просто давить конкурентов.

Отмечу так же, что время не стоит на месте. И Boost, при сохранении вышеперечисленных недостатков, все-таки за прошедшее время обзавелся рядом полезных библиотек, которых мне в нем не хватало изначально (в первую очередь Boost.Asio). Так что если бы сейчас встал вопрос брать или не брать Boost для совсем нового проекта, я бы сделал новую попытку оценки уместности использования Boost-а.

суббота, 3 апреля 2010 г.

[prog.thoughts] Развернутый ответ SleepyDrago по поводу наезда на Boost-оводов

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

2Евгений:
наезды на бюст не понятны. Они нам ничего не должны ;)
Я вот могу сказать что я рад что я вообще не смотрел на bjam, несколько spirit'ов, кучу мета-, boost.preprocess и кучу мелких. Ну и ? это не значит что кому-то оно не пригодилось. Более того я рад что ничего не знаю про poco,ace, rubygems :)
а из комментария jazzer'а мне понятно что я ничего не узнаю про этот риппл ))

ps Про bjam например стало очевидно когда те, кому надо билдить много, померяли и обсудили его перформанс.

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

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

И это не касается языка (т.е. язык накладывает свои ограничения, но это уже просто исходные условия для решения задачи) – это касается инструментов, которых почему-то нет. Хотя лично мне они нужны. И, думаю, нужны они не только мне. Ну а если инструмент нужный, то должен же он когда-то появится.

А теперь представим, что какие-то инструменты для дистрибуции C++ных библиотек появились. Штуки три. От Васи Пупкина, Джона Смита и Кумара Гашишовава. О каждом из которых знает человек двадцать-тридцать друзей и коллег авторов данных инструментов. Какие шансы у этих разработок, даже если они удобны и качественно сделаны, стать настоящим мейнстримом в C++ коммунити? Очень маленькие, имхо.

Совсем другое дело, если бы велосипед по дистрибуции библиотек появился в составе Boost-а. Это как iPhone от Apple – как телефон фигня, зато какой ажиотаж! Еще пример: я слышал, что многим не нравится qmake из Qt. Но им пользуются, поскольку это штатный инструмент для Qt.

Так вот, если бы Boost выпустил что-то вроде RubyGems для C++ – это было бы очень и очень знаковое событие. Что радует, Boost-оводы сами осознали необходимость такого инструмента. Кроме того, Boost-оводы позиционируют себя как активные развиватели C++ – это же их цель – отбирать новые библиотеки для включения в следующий стандарт C++. Ну так почему бы не заложить в стандарт и систему пакетов/библиотек для C++ (тот же RubyGems уже входит в стандартную комплектацию Ruby 1.9)?

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

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

PS. Чувствую себя обязанным ответить на вопрос “А самому слабо?” Честно скажу – слабо. Я пытался изобрети такой велосипед. Но на его воплощение в жизнь не было ресурсов. Оказалось проще воспользоваться средствами Subversion, о чем я рассказал когда-то в статье. С тех пор именно этим способом мы и пользуемся. Даже сторонние проекты в репозитории укладываем и стараемся адаптировать их к нашей системе сборки (ACE, POCO, PCRE, Crypto++, libcurl и пр.). Но все это не работает, когда приходится публиковать SObjectizer и сопутствующие ему библиотеки. Пока мы мало их публикуем и эта проблема не сильно меня волнует. Но теперь появляются ресурсы для дальнейшего развития SObjectizer и проблема вновь оказывается актуальной. Нужно что-то искать или делать. Может быть, будем что-то делать. Но это уже не только от меня зависит.

среда, 3 февраля 2010 г.

[comp.prog] Вышел Boost 1.42.0

Вышел очередной релиз Boost-а – 1.42.0 (периодичность выходов новых релизов радует). Добавлена новая библиотека – uuid для генерации UUID-ов. Приятно, Boost начинает обрастать действительно полезными вещами ;)

среда, 4 ноября 2009 г.

[comp.prog.thoughts] Почему мне не нравится подход Boost.Serialization

Нашлось время чтобы еще раз перечитать документацию по Boost.Serialization, поэтому выполняю свое давнее обещание рассказать о том, почему я не считаю подход Boost-а к сериализации правильным.

Причина проста – в Boost.Serialization программист сам пишет код, декларирующий сериализацию/десериализацию, и в этом коде возможности для оформления каких-то метаописаний сильно ограничены.

Например, решил разработчик использовать простой текстовый/бинарный архив и написал код:

class gps_position
{
    friend class boost::serialization::access;
    friend std::ostream & operator<<(std::ostream &os, const gps_position &gp);

    int degrees;
    int minutes;
    float seconds;

    template< class archive >
    void serialize(Archive & ar, const unsigned int /* file_version */){
        ar  & degrees
            & minutes
            & seconds;
    }
    ...

В этом случае он получает сериализацию, основанную на порядке следования атрибутов. Проходит какое-то время и разработчику становится необходимо сделать в дополнение к этой сериализации еще и XML-сериализацию. Какой у него выход? Только править собственный код:

template< class archive >
void serialize(Archive & ar, const unsigned int /* file_version */){
    ar  & BOOST_SERIALIZATION_NVP(degrees)
        & BOOST_SERIALIZATION_NVP(minutes)
        & BOOST_SERIALIZATION_NVP(seconds);
}

Теперь он может сериализовать данные как в простую, так и в XML-форму. Но что ему делать, если со временем ему потребуется еще и сериализация на основе TLV (Tag-Length-Value)? А если ему затем захочется делать опциональные атрибуты (т.е. такие, которые присутствуют только при выполнении каких-то условий)? Если ему потребуется в каком-то архиве хранить uint32-поле в четырехбайтовом представлении, а в другом архиве – в компактном (чтобы, скажем, значение 12 хранилось с помощью всего одного байта)? В конце-концов, что ему делать, если бинарный архив потребуется прочитать из программы на другом языке?

На мой очень предвзятый взгляд все это решается гораздо проще при наличии метаописаний, из которых специальными трансляторами генерируется вспомогательный код для сериализации/десериализации.

Для демонстрации своей мысли я буду использовать синтаксис метаописаний своей библиотеки сериализации ObjESSty, т.к. его я знаю хорошо (в отличии от ASN.1, Google Protocol Buffers, Facebook Thrift).

Итак, пусть все начинается с простого случая – бинарной сериализации gps_position. Для нее описание данных будет иметь вид:

{type gps_position
  {attr degrees {of oess_1::int_t}}
  {attr minutes {of oess_1::int_t}}
  {attr seconds {of oess_1::single_t}}
}

Если возникает потребность использовать XML-сериализацию так, чтобы имена XML-тегов совпадали с именами атрибутов, то ничего больше изменять не нужно. Поскольку транслятор DDL-описания и так знает имена атрибутов. Если же нужно использовать для атрибутов minutes и seconds имена min и sec, то это описывается, скажем, так:

{type gps_position
  {attr degrees {of oess_1::int_t}}
  {attr minutes {of oess_1::int_t} {xml {element "min"}}}
  {attr seconds {of oess_1::single_t} {xml {element "sec"}}}
}

Если затем возникает необходимость в TLV-сериализации, то это так же описывается в DDL:

{type gps_position
  {attr degrees {of oess_1::int_t}
    {tlv {tag 0x01}}
  }
  {attr minutes {of oess_1::int_t}
    {xml {element "min"}}
    {tlv {tag 0x02}}
  }
  {attr seconds {of oess_1::single_t}
    {xml {element "sec"}}
    {tlv {tag 0x03}}
  }
}

С XML-элементами и TLV-тегами может произойти неприятная ситуация: со временем имена элементов и значения тегов могут меняться, но нужно будет читать и старые архивы. Поэтому при десериализации нужно будет уметь распознавать несколько имен/тегов. В DDL-описании это сделать не сложно:

{type gps_position
  {attr degrees {of oess_1::int_t}
    {xml {element "d"}}
    {tlv {tag 0x51} {compat-tag 0x01}}
  }
  {attr minutes {of oess_1::int_t}
    {xml {element "m"} {compat-element "min"}}
    {tlv {tag 0x52} {compat-tag 0x02}}
  }
  {attr seconds {of oess_1::single_t}
    {xml {element "s"} {compat-element "sec"}}
    {tlv {tag 0x53} {compat-tag 0x03}}
  }
}

Далее, пусть потребовалось для бинарных архивов одного типа хранить атрибуты degrees и minutes в компактном виде, а для бинарных архивов другого типа – в четырехбайтовом представлении, чтобы экономить время распаковки. В DDL-описании можно оформить и такие условия:

{type gps_position
  {attr degrees {of oess_1::int_t}
    {xml {element "d"}}
    {tlv {tag 0x51} {compat-tag 0x01}
      {default-image-size compact}
      {archive-type "max-speed" {image-size 32bit}}
    }
  }
  ...
}

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

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

Общий принцип сериализации таких атрибутов в бинарное представление состоит в том, что в архив помещается флаг, который показывает наличие/отсутствие атрибута (для TLV- или XML-представления ситуация проще). Данный флаг может сохраняться в архиве несколькими способами: в виде отдельного бита в “большой” битовой маске или в виде байта/бита, предшествующего значению атрибута. Конкретный способ – это делали работы архива, программист не должен об этом задумываться. О чем должен думать программист – это о том, чтобы объявить каким-то способом атрибут опциональным. В случае с внешним метаописанием это не сложно:

// Подлежащие сериализации C++ классы.
class compression_info_t
  {
  ...
  public :
    bool is_default() const { ... }
    static compression_info_t default_value() { ... }
    ...
  };
class data_package_t
  {
  ...
    compression_info_t m_compression_info;
  };

// Метаописание.
[type deta_package_t
  ...
  {attr m_compression_info {of compression_info_t}
    {default
      || Значение, которое должен получить атрибут при
      || десериализации, если он не был сериализован.
      {c++ compression_info_t::default_value() }

      || Логическое условие, которое указывает, будет ли
      || атрибут сериализоваться.
      {present_if {c++ !m_compression_info.is_default() }}
    }
  }
}

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

Как тоже самое сделать для текстовых и бинарных архивов в Boost.Serialization – я не очень представляю. Можно, например, вручную управлять флагами:

class data_package_t
  {
    friend class boost::serialization::access;
    BOOST_SERIALIZATION_SPLIT_MEMBER()
// Способ первый: общая битовая маска.
    template< class Archive >
    void save( Archive & ar, const unsigned int version ) const
      {
        bit_mask_t opt_flags;
        if( !m_compression_info.is_default() )
          opt_flags.set_bit( COMPRESSION_INFO );
        ...
        ar & opt_flags;
        ...
        if( opt_flags.is_bit_set( COMPRESSION_INFO ) )
          ar & m_compression_info;
        ...
      }
    template< class Archive >
    void load( Archive & ar, const unsigned int version )
      {
        bit_mask_t opt_flags;
        ar & opt_flags;
        ...
        if( opt_flags.is_bit_set( COMPRESSION_INFO ) )
          ar & m_compression_info;
        else
          m_compression_info = compression_info_t::default_value();
        ...
      }

// Способ второй: булевое поле, предшествующее атрибуту.
    template< class Archive >
    void save( Archive & ar, const unsigned int version ) const
      {
          if( !m_compression_info.is_default() )
            {
              ar & true;
              ar & m_compression_info;
            }
          else
            ar & false;
        ...
      }
    template< class Archive >
    void load( Archive & ar, const unsigned int version )
      {
        bool compression_info_present;
        ar & compression_info_present;
        if( compression_info_present )
          ar & m_compression_info;
        else
          m_compression_info = compression_info_t::default_value();
        ...
      }

Но, во-первых, я не уверен, что для всех типов архивов Boost.Serialization гарантирует запись/чтение значения сразу после выполнения operator&() (ведь для XML-архивов порядок следования атрибутов может быть произвольным). И, во-вторых, как только программист начинает писать подобный код, работа с разными типами архивов (текстовыми, бинарными, XML, TLV) сразу же превращается в т.н. hardcoding. Тогда как в случае с метаописанием всеми этими деталями занимается не разработчик, а транслятор метаописания во вспомогательный код.

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

PS. В ObjESSty нет поддержки TLV- и XML-сериализации. XML-формат никогда не был мне нужен, а TLV-сериализация однажды понадобилась. Упомянутые выше формы описания TLV-тегов в DDL как раз тогда и рассматривались. Развития эта идея пока не получила, т.к. оказалось проще сделать поддержку TLV для десятка атрибутов вручную, чем модифицировать ObjESSty.