Поскольку я зарекся вступать в публичные споры на LOR/RSDN/Habr, а в Интернете, как водится, кто-то неправ, то попробую разместить свою ремарку здесь, в уютненьком ;)
В этот раз дело касается вот этой ветки обсуждения на RSDN. Кратко, насколько я понял, там речь шла о том, хорошо ли в C++ иметь отдельные классы для представления сетевых пакетов какого-то протокола. Как водится, информации для предметного обсуждения ни у кого нет, но все приводят собственные доводы ;)
Там даже кусок кода всплыл, типа образчик на который имеет смысл посмотреть.
Как мне показалось, одна из проблем данного спора в том, что некоторые товарищи путают представление данных в рамках некого условного протокола обмена данными и сам протокол.
Представление данных -- это всего лишь конкретный механизм сериализации. Скажем, использование принципа TLV (Tag-Length-Value), как в ASN.1 BER. Или плотная побитовая упаковка как в ASN.1 PER. Или же тегированное текстовое представление, вроде JSON или XML (должны сдохнуть в муках оба, шутка).
Кусок кода, который привели в обсуждении на RSDN, он как раз про представление данных.
Тогда как есть еще одна важная часть, когда мы говорим о каких-то протоколах обмена данными -- это из каких сообщений (PDU -- protocol data unit) состоит сам обмен.
Типа того, что есть сообщение handshake и ответное сообщение handshake_ack. Есть сообщение subscribe и есть ответы sub_ack и sub_nack. Есть сообщение publish и есть ответные pub_ack и pub_nack, а также сопутствующее delivery_report. И т.д., и т.п.
Так вот, представление данных определяет то, как содержимое PDU сериализуется.
Но представление данных не есть удобный способ работать с самими PDU в коде.
Достаточно часто в наше время встречается ситуация, когда PDU представляется в виде JSON. Входящий пакет парсится, у нас в коде появляется что-то вроде nlohman::json или RapidJson::Value. И дальше программисты любятся с этими JSON-объектами как умеют. А умеют практически никак 😣 Например, если в PDU есть поле priority, то из JSON-объекта запрашивают это поле вручную по строковому имени. Если это поле нуждается в какой-то валидации (хоть при извлечении, хоть при сохранении), то это тоже делают вручную. Если делают.
Мне же думается, что работать с PDU в программе гораздо удобнее, когда PDU представляется в виде конкретного C++ного класса с нужными методами getter-/setter-ами. И когда в эти самые методы вставлена валидация значений. Более того, такие классы могут (и должны, когда есть возможность) проверять корректность значений при сериализации/десериализации. Например, если поле A в PDU имеет вот такое значение, то поле B не может быть пустым, а поле C, напротив, должно быть пустым.
Проблема в том, что написание таких классов то еще удовольствие, особенно когда PDU не два-три-четыре, а каждый PDU содержит не одно-два поля, и даже не десять-двадцать.
Однажды в прошлом с чем-то таким столкнулся. Даже рассказывал об этом на RSDN и упоминал в блоге. То решение на Ruby оказалось удобным. Если доведется еще раз с подобной задачей, то буду смотреть в ту же сторону (не важно, Ruby будет использоваться для кодогенерации, Python или еще что-то). Хотя современный C++ в области шаблонной магии далеко ушел от C++03, но все равно не думаю, что подобная задача будет хорошо решаться в рамках C++20 или C++23.
PS. Еще раз по поводу кода, который показали на RSDN. Как раз тот случай, когда смотришь в код, внутренний голос спрашивает "а что так навороченно то, нельзя ли пропроще?", но без вдумчивого изучения ответа на этот вопрос нет. А вдумчиво изучать нет желания ;)
PPS. Мораль всего поста: не беритесь судить без глубокого погружения.