views:

201

answers:

4

I am developing a C++ class library containing domain model classes, and I would like to add support for instantiating these classes from various persistence mechanisms, i.e. databases and file. The user of the class library should be given an interface(?) against which to program a class that can transfer the data from/to the persistence mechanism.

I know of the Data Access Object pattern which seems to work for Java, but I'm not exactly sure how to apply it to C++. Are there other solutions?

+1  A: 

Boost Serialization provides some pretty useful stuff for working with serializing C++ types, but how well it will match the interface you desire I don't know. It supports both intrusive and non-intrusive designs, so is pretty flexible.

Simon Steele
A: 

You might like to look at boost serialization. Not having used it I can't say whether to recommend it or not. Boost libraries are typically high quality.

1800 INFORMATION
+1  A: 

C++ supports multiple inheritance so you can have a generic persistence API and inherit a persistence mechanism. This would still have to use introspection to get out the class metadata, but you would still have this issue with any persistence layer.

Alternatively you could do something similar but use the metadata to drive a code generator that fills in the 'Getters' and 'Setters' for the persistence layer.

Any persistence layer will typically use one or the other approach, so your problem is hooking the loading mechanism into the persistence layer. I think this makes your problem little different from a single persistence layer but tackling it from the other direction. Rather than building domain classes onto a persistence framework you are providing a set of domain classes with the hooks for a persistence framework that third parties can plug their data access mechanism into.

I think that once you provide access to class metadata and callbacks the perisistence mechanism is relatively straightforward. Look at the metadata components of any convenient C++ O/R mapping framework and understand how they work. Encapsulate this with an API in one of the base classes of your domain classes and provide a generic getter/setter API for instantiation or persisting. The rest is up to the person implementing the persistence layer.

Edit: I can't think of a C++ library with the type of pluggable persistence mechanism you're describing, but I did something in Python that could have had this type of facility added. The particular implementation used facilities in Python with no direct C++ equivalent, although the basic principle could probably be adapted to work with C++.

In Python, you can intercept accesses to instance variables by overriding __getattr()__ and __setattr()__. The persistence mechanism actually maintained its own data cache behind the scenes. When the functionality was mixed into the class (done through multiple inheritance), it overrode the default system behaviour for member accessing and checked whether the attribute being queried matched anything in its dictionary. Where this happened, the call was redirected to get or set an item in the data cache.

The cache had metadata of its own. It was aware of relationships between entities within its data model, and knew which attribute names to intercept to access data. The way this worked separated it from the database access layer and could (at least in theory) have allowed the persistence mechanism to be used with different drivers. There is no inherent reason that you couldn't have (for example) built a driver that serialised it out to an XML file.

Making something like this work in C++ would be a bit more fiddly, and it may not be possible to make the object cache access as transparent as it was with this system. You would probably be best with an explicit protocol that loads and flushes the object's state to the cache. The code to this would be quite amenable to generation from the cache metadata, but this would have to be done at compile time. You may be able to do something with templates or by overriding the -> operator to make the access protocol more transparent, but this is probably more trouble than it's worth.

ConcernedOfTunbridgeWells
Thanks for the extensive answer. Could you add some example code, or a reference to some public domain examples?
andreas buykx
A: 

I would avoid serialization, IMHO, we implemented this for one of our applications in MFC back in 1995, we were smart enough to use independent object versioning, and file versioning, but you end up with a lot of old messy code around after time.

Imagine certain scenarios, deprecating classes, deprecating members, etc, each presents a new problem. Now we use compreseds "XML type" streams, we can add new data and maintain backward compatibility.

Reading and writing the file is abstracted from mapping the data to the objects, we can now switch file formats, add importers/exporters without modification to our core business objects.

That being said some developers love serialization, my own encounters is that switching code base, platforms, languages, toolkits all bring along a lot of problems, reading and writing your data should not be one of them.

Additionally using a standard data format, with some proprietary key, means its a lot easier to work with 3rd parties.

titanae