类库,支持多种持久性策略

时间:2020-03-06 14:31:46  来源:igfitidea点击:

我正在开发一个包含域模型类的C ++类库,并且我想添加对从各种持久性机制(即数据库和文件)实例化这些类的支持。应该为类库的用户提供一个接口(?),可通过该接口对一个类进行编程,该类可以将数据从持久性机制传输到持久性机制。

我知道似乎适用于Java的数据访问对象模式,但是我不确定如何将其应用于C ++。还有其他解决方案吗?

解决方案

Boost序列化提供了一些非常有用的东西,可用于序列化C ++类型,但是它将与我们不希望的接口匹配的程度如何。它支持侵入式和非侵入式设计,因此非常灵活。

我们可能想看一下Boost序列化。没有使用它,我不能说是否推荐它。 Boost库通常是高质量的。

C ++支持多重继承,因此我们可以拥有通用的持久性API并继承持久性机制。这仍然必须使用自省来获取类元数据,但是任何持久层都仍然会出现此问题。

或者,我们可以执行类似的操作,但使用元数据来驱动代码生成器,以为持久层填充" Getters"和" Setters"。

任何持久层通常都会使用一种或者另一种方法,因此问题是将加载机制挂接到持久层中。我认为这使问题与单个持久层几乎没有什么不同,但从另一个方向进行了解决。我们不是在持久性框架上构建域类,而是提供了一组带有持久性框架挂钩的域类,第三方可以将其数据访问机制插入其中。

我认为,一旦提供对类元数据和回调的访问,持久性机制就相对简单了。查看任何方便的C ++ O / R映射框架的元数据组件,并了解它们的工作方式。使用API​​将其封装在域类的基类之一中,并提供用于实例化或者持久化的通用getter / setter API。其余的取决于实现持久层的人。

编辑:我想不出具有我们所描述的可插拔持久性机制类型的C ++库,但是我在Python中做了一些可能添加了这种类型的功能的事情。尽管基本原理可能适用于C ++,但该特定实现使用的Python工具没有直接的C ++等效项。

在Python中,我们可以通过覆盖__getattr()____setattr()__来拦截对实例变量的访问。持久性机制实际上在后台维护了自己的数据缓存。当将功能混合到类中(通过多重继承完成)时,它将覆盖成员访问的默认系统行为,并检查要查询的属性是否与其词典中的任何内容匹配。在发生这种情况的地方,调用将被重定向以获取或者设置数据高速缓存中的项目。

缓存具有自己的元数据。它知道其数据模型中实体之间的关系,并且知道要拦截哪些属性名称才能访问数据。这种工作方式将其与数据库访问层分开,并且可能(至少在理论上)已允许将持久性机制与其他驱动程序一起使用。没有内在的理由,例如,我们无法构建将其序列化为XML文件的驱动程序。

用C ++进行类似的工作会有些麻烦,并且可能无法像在此系统中那样使对象缓存访问透明。最好使用显式协议将对象的状态加载并刷新到缓存中,这是最好的。从缓存元数据生成代码非常适合此操作,但这必须在编译时完成。我们可能可以使用模板或者通过重写->运算符来使访问协议更透明,从而做到这一点,但这可能比它值得的麻烦更多。

我会避免序列化,恕我直言,我们早在1995年就在MFC中为我们的一个应用程序实现了这一点,我们足够聪明,可以使用独立的对象版本控制和文件版本控制,但是随着时间的流逝,我们最终会得到很多旧的混乱代码。

想象一下某些场景,弃用的类,弃用的成员等,每个场景都带来一个新问题。现在,我们使用压缩的" XML类型"流,可以添加新数据并保持向后兼容性。

读写文件是从将数据映射到对象中抽象出来的,我们现在可以切换文件格式,添加进口商/出口商而无需修改我们的核心业务对象。

话虽这么说,一些开发人员喜欢序列化,但我自己遇到的是,切换代码库,平台,语言,工具包都会带来很多问题,读写数据不应该是其中之一。

此外,使用带有某些专有密钥的标准数据格式,意味着与第三方的合作更加容易。