2012-06-05 3 views
3

i^m currenty ищет хороший дизайн OO для сериализации приложения C++/Qt.
Представьте, что классы приложения организованы на основе древовидной структуры, реализованной с помощью Composite-Pattern, как на следующем рисунке.Хороший дизайн для сериализации C++

два возможных принципа я думал:

1.)
Поместите функцию сохранения()/нагрузки() в каждом классе, который должен быть сериализации. Если вы видели это много раз, обычно выполняются с помощью boost. Где-то в классе вы найдете что-то вроде этого:

friend class boost::serialization::access; 
template<class Archive> 
void serialize(Archive & ar, const unsigned int version) 
{ 
    ar & m_meber1; 
} 

Вы также можете отделить это в экономии() и нагрузки(). Но недостатком такого подхода является:
Если вы хотите изменить сериализацию через два месяца (в XML, HTML или что-то очень любопытное, которое не поддерживает), вы должны принять все тысячи классов. Какой, на мой взгляд, не очень хороший OO-дизайн.
И если вы хотите поддерживать разные сериализации (XML, Binary, ASCII, независимо ....) в то же время, что 80% CPP существует только для функций сериализации.

2.)
Я знаю, что повышение также обеспечивает Неинтрузивная версию сериализации

«http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/ tutorial.html»

Так еще один способ заключается в реализации итератора, который перебирает по композиционной структуре дерева и сериализующий каждый объект (и один итератор для десериализации)
(я думаю, что это то, что XmlSerializer-класс .NET-Framework делает, но я не очень хорошо знаком с .NET.)
Это звучит лучше, потому что отдельные save() и load() и только одно пятно меняются, если сериализация изменяется.
Так что это звучит лучше, НО:
- Вы должны предоставить сеттер() и getter() для каждого параметра, который вы хотите сериализовать. (Итак, частных данных нет. (Это хорошо/плохо?)
- У вас может быть длинная наследовательская иерархия (более 5 классов), висящая на составном дереве.
Итак, как вы называете setter()/getter() производных классов? Когда вы можете только вызвать функцию интерфейса базового композитного компонента.

Другой способ - сериализовать данные объектов в отдельный абстрактный формат. Из всех возможных последовательных сериализаций (XML, TEXT, независимо от того, что возможно) получают свои данные. Одна идея заключалась в сериализации ее в QDomNode. Но я думаю, что дополнительная абстракция будет стоить производительности.

Так что мой вопрос:
Кто-нибудь знает хороший OO-Design для сериализации?
Возможно, с других языков программирования, таких как JAVA, Python, C#, независимо от того, что ....

Спасибо.

+4

Буферы протокола Google? –

+1

Вы, кажется, путаетесь с природой _Boost.Serialization_ ... Что вы подразумеваете под «усыновлением всех тысяч классов» или «80% cpp существуют для сериализации»? Вы пишете одну единственную функцию сериализации (две, если разделены сохранение и загрузка), и используйте ее с тем, что хотите, которое поддерживает концепцию «Архивация», будь то XML, JSON, Binary, что угодно .. –

+0

Yep, @ K-ballo is right , И подумайте, что, если через два месяца вам не придется переключать тип архива - это довольно просто, но что, если вам нужно что-то изменить в дереве и данных? Boost :: Serialization выглядит очень хорошо. – Forgottn

ответ

3

Опасайтесь сериализации.

Сериализация касается моментального снимка вашего представления в памяти и последующего восстановления.

Это все замечательно, за исключением того, что он начинает изнашивается по швам, когда вы думаете о загрузке ранее сохраненный снимок с новой версией программного обеспечения (обратной совместимости) или (не дай бог) недавно хранится снимок с более ранняя версия программного обеспечения (Forward Compatibility).

Многие структуры могут легко справляться с обратной совместимостью, однако для обеспечения совместимости в прямом направлении требуется, чтобы ваш новый формат был очень рядом с его предыдущей итерацией: в основном, просто добавьте/удалите некоторые поля, но сохраните ту же общую структуру.

Проблема заключается в том, что сериализация по соображениям производительности имеет тенденцию связывать структуру на диске с представлением в памяти; изменение представления в памяти затем требует либо устаревания старых архивов (и/или утилиты миграции).

С другой стороны, системы обмена сообщениями (и это то, что означает goob protobuf) - это развязка структур обменных сообщений из представления в памяти, чтобы ваше приложение оставалось гибким.

Поэтому сначала необходимо выбрать, будет ли осуществлять сериализации или сообщений.


Теперь вы правы, что можете написать код сохранения/загрузки внутри класса или вне его. Это еще раз компромисс:

  • в своем классе код имеет непосредственный доступ ко всем-членов, как правило, более эффективной и простой, но менее гибкий, так что она идет рука об руку с сериализации
  • для улицы внеклассной код требует косвенного доступа (добытчиков, иерархии посетителей), менее эффективный, но более гибкий, поэтому она идет руку об руке с сообщениями

Обратите внимание, что нет никаких недостатков о скрытого состояния. class не имеет (истинно) скрытое состояния:

  • кэшей (mutable значения) как раз то, что они могут быть потеряны без беспокойства
  • скрытых типов (думает FILE* или другую ручку) обычно извлекаемые другие пути (сериализация имя файла, например)
  • ...

Лично я использую сочетание обоих.

  • Кэши написаны для текущей версии программы и используют быструю (де) сериализацию в v1.Новый код написан для работы как с v1, так и с v2 и записывается в v1 по умолчанию, пока не исчезнет предыдущая версия; затем переключается на запись v2 (при условии, что это легко). Иногда массивный рефакторинг делает обратную совместимость слишком болезненной, мы бросаем ее на пол в этот момент (и увеличиваем основную цифру).
  • С другой стороны, обмен с другими приложениями/услугами и более долговечным хранилищем (blobs в базе данных или в файлах) использует обмен сообщениями, потому что я не хочу привязываться к определенной структуре кода в течение следующих 10 лет.

Примечание: Я работаю над серверными приложениями, поэтому мои советы отражают особенности такой среды. Я полагаю, что клиентские приложения должны поддерживать старые версии навсегда ...

+0

Благодарим вас за подробное заявление. Я думаю, что нашел то, что я искал http://www.riehle.org/computer-science/research/1996/plop-1996-serializer.pdf BTW i^m работает над большим CAD-приложением, где мы должны сериализуйте большой объем геометрии. – grimblegrumble

+0

@grimblegrumble: в этом случае вы можете пожелать повысить производительность по сравнению с гибкостью. Вы также можете построить ленивую загрузку, если вам не понадобится большая часть геометрии сразу: ленивое декодирование может дать вам более быстрые ответы. (обратите внимание: шаблон в ссылке очень похож на реализацию Visitor) –

+0

@ grimblegrumble Кроме того, в случае, если программист должен проверить данные и решил выполнить проверку во время де-сериализации, превращается в ад - _sometimes_, небезопасно частично загружать данные, пропустить что-то, потому что деструкторы могут что-то вызывать, что-то, что не готово к использованию (например, еще не де-сериализовано). У меня была эта проблема – user24601

Смежные вопросы