25 Сериализация: за и против

      Комментарии к записи 25 Сериализация: за и против отключены

Помечено: , ,

В этой теме 0 ответов, 1 участник, последнее обновление  Васильев Владимир Сергеевич 4 мес., 2 нед. назад.

  • Автор
    Сообщения
  • #3603

    В этой статье я не буду рассматривать детали реализации сериализации (…выдра бодро ядра кедра…). Скорее, это будут простые рассуждения на тему «за» и «против».

    Вообще говоря, отношение общества к сериализации довольно неоднозначное. В этом вы можете легко убедиться — попробуйте остановить десять случайных прохожих и спросить их, как они относятся к сериализации. Уверен, мнения будут самые разнообразные. И на это есть определенные причины. Сериализация как паттерн (если ее можно назвать паттерном), действительно, имеет массу как хороших свойств, так и плохих. Я постараюсь рассказать и о том и о другом максимально объективно.

    Хорошо

    Сериализация позволяет отображать практически любые пользовательские данные, выраженные типами C++, в любые внешние пространства данных.

    Сериализация, при соответствующей реализации, позволяет четко разделить обязанности на логическую и физическую интерпретации данных. Одной и той же логической интерпретации (например — XML) можно дать любое физическое обличье. Например, сохранение на диск, вывод на консоль или передача по сети. Верно и обратное. Логическая и физическая интерпретация полностью независимы друг от друга и могут прекрасно уживаться в любых комбинациях.

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

    Плохо

    Половина всех неприятностей, доставляемых сериализацией, обязаны тому, что язык C++ не имеет такого механизма как «reflection». Сериализацию невозможно автоматизировать. Во время компиляции вы не располагаете достаточным количеством информации о пользовательских типах данных, чтобы автоматизация была возможна. Да, можно ввести вспомогательные макросы, проверки уровня компиляции на полноту сериализации типа, и так далее, однако, это все не более чем «полуавтомат». При изменении структуры пользовательского типа, придется внести изменение по крайней мере в одном дополнительном месте. Это плохо, хотя от этого никуда и не деться.

    Вообще говоря, деться можно. Сериализацию можно полностью автоматизировать, если все сериализуемые типы будут представлять собой tuple (например, boost::tuple). Но согласитесь, хранить все данные в туплах — полный ахтунг.

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

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

    Кодогенерация в C++ это вообще тема, заслуживающая отдельного внимания и требующая более детального рассмотрения. Когда-нибудь в будущем я обязательно вернусь к теме кодогенерации в C++.

    Вердикт

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

    Могу сказать точно, что не нужно использовать сериализацию для данных, работа с которыми не является критичной с точки зрения производительности. Например, аутентификация по протоколу kerberos предполагает структурирование пакетов данных по спецификации ASN1. Аутентификация по kerberos — это обмен несколькими пакетами размером несколько сот байт. Ничего критичного с точки зрения производительности в ней нет. Вместо того, чтобы использовать сериализацию для отображения типов C++ в формат ASN1, гораздо удобнее написать конвертор из XML в ASN1 и обратно, и работать через XQuery и XPath. Это значительно упростит и клиентский код и отладку приложения, поскольку все средства для работы с XML уже давно изобретены.

    Другое дело, если обработка данных критична с точки зрения производительности, и этих данных у вас очень много. Предположим, вам нужно рассчитать упругую деформацию при столкновении двух объемных тел, представленных несколькими миллионами (или миллиардами) полигонов. Конечно, никакой XML + XQuery/XPath здесь не канает. В этом случае сериализация вроде бы и имеет право на существование. Но стоит запомнить, что в данном случае сериализация — это лишь одно из возможных решений, ни в коем случае не являющееся наилучшим.

    Постарайтесь не использовать сериализацию для полиморфных типов. Ограничьтесь сериализацией базовых типов, открытых структур в стиле Plain C, а также STL- и boost-контейнеров. Эти типы данных наиболее близки к универсальным. В противном случае ваша программа обрастет такой гадостью как фабрики, и прочими излишествами нехорошими.

    boost::serialization? Да, есть такая библиотека. Да, она умеет сериализовать все подряд. Да, стоит разобраться, как она работает. Но не стоит сразу же хвататься за нее обеими руками и использовать везде, где это только возможно. Если вы научитесь обходиться без сериализации, не потеряв при этом изящества кода и скорости разработки, то это будет гораздо более ценное умение, нежели умение использовать boost::serialization.

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

    Как говорится, «семь раз отмерь, один раз отрежь». Лично я стараюсь избегать использования сериализации. По мере сил.

Для ответа в этой теме необходимо авторизоваться.