C ++序列化的优秀设计

时间:2012-06-05 17:46:02

标签: c++ serialization architecture

目前正在寻找一个好的OO设计来序列化C ++ / Qt应用程序 想象一下,应用程序的类是基于树结构组织的,使用Composite-Pattern实现,如下图所示。

我想到的两个可能的原则:

1.)
将save()/ load()函数放在每个必须可序列化的类中。 如果已经多次看过,通常用boost来实现。 在课堂的某个地方你会发现这样的事情:

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

您也可以将其分为save()和load()。 但这种方法的缺点是:
    如果你想在两个月之后改变序列化(对于XML,HTML或者非常好奇的东西,这会增加不支持),你必须采用所有数千个类。     在我看来,这不是一个好的OO设计     如果你想同时支持不同的序列化(XML,二进制,ASCII,等等......),那么只有80%的cpp存在于序列化函数中。

2。)
我知道boost还提供了序列化的非侵入式版本
“http://www.boost.org/doc/libs/1_49_0/libs/serialization/doc/tutorial.html”

另一种方法是实现迭代复合树结构并序列化每个对象的Iterator(以及用于反序列化的一个迭代器)
(我认为这是.NET-Framework的XmlSerializer-Class所做的,但我不熟悉.NET) 这听起来更好,因为单独的save()和load()以及序列化更改时只有一个点可以改变 所以这听起来更好,但是:
- 你必须为你要序列化的每个参数提供一个setter()和一个getter()。 (所以,不再有私人数据。(这好/坏吗?)) - 你可以在复合树上挂一个长继承hirarchy(超过5个类)     那么如何调用派生类的setter()/ getter()?     当你只能调用基础Composite-Component的接口函数时。

另一种方法是将对象数据序列化为单独的抽象格式。 从中可以获得所有可能的后续序列化(XML,TEXT,无论可能)以获取其数据。 一个想法是将其序列化为QDomNode。 但我认为额外的抽象会降低性能。

所以我的问题是:
有没有人知道一个好的OO-Design进行序列化?
也许来自其他编程语言,如JAVA,Python,C#,等等......

谢谢。

1 个答案:

答案 0 :(得分:2)

小心序列化。

序列化是关于拍摄内存中表示的快照并稍后恢复它。

这一切都很棒,只是当你考虑使用较新版本的软件(向后兼容性)或(上帝禁止)加载以前存储的快照时,它会开始磨损接缝使用较旧版本的软件存储快照(向前兼容性)。

许多结构可以轻松处理向后兼容性,但是向前兼容性要求您的新格式非常接近其先前的迭代:基本上,只需添加/删除一些字段但保持相同的整体结构。

问题在于,出于性能原因,序列化往往会将磁盘上的结构与内存中的表示联系起来;更改内存中表示然后需要弃用旧存档(和/或迁移实用程序)。

另一方面,消息传递系统(这就是google protobuf)是关于将交换的消息结构与内存中表示分离,以便您的应用程序保持灵活性。

因此,您首先需要选择是否实施序列化消息


现在你可以在课堂内或课堂外编写保存/加载代码。这又是一次权衡:

  • 类内代码可以立即访问所有成员,通常更高效,更直接,但灵活性更低,因此它与序列化密切相关
  • 类外代码需要间接访问(getter,访问者层次结构),效率低,但更灵活,因此它与消息传递密切相关

请注意,隐藏状态没有任何缺点。 class没有(真正)隐藏状态:

  • 缓存(mutable值)就是这样,它们可以毫无顾虑地丢失
  • 隐藏类型(思考FILE*或其他句柄)通常可通过其他方式恢复(例如序列化文件名)
  • ...

我个人使用两者兼而有之。

  • 为当前版本的程序编写缓存,并在v1中使用快速(反)序列化。编写新代码以与v1v2一起使用,默认情况下在v1中写入,直到先前版本消失为止;然后切换到写v2(假设这很容易)。偶尔,大规模的重构会使向后兼容性太痛苦,我们此时将其丢弃在地板上(并增加主要数字)。
  • 另一方面,与其他应用程序/服务的交换以及更持久的存储(数据库或文件中的blob)使用消息传递,因为我不希望在接下来的10年中将自己束缚到特定的代码结构。 / LI>

注意:我正在处理服务器应用程序,因此我的建议反映了这种环境的细节。我想客户端应用程序必须永远支持旧版本......