I'm currently consulting on two banking projects, which provide translation, validation and distribution of various data feeds from various mainframe based systems. It's almost a BizTalk system, but BizTalk is too heavy in terms of infrastructure requirements and licensing costs, even the Microsoft representative suggested that a roll your own solution would be better. We've currently discussing object persistence and where it should happen.
There are two distinct camps, with one group who believe that objects should have an understanding of their own persistence mechanisms and the other camp, where I am commandant, believes persistence should be in a separate logical and optionally physical layer.
If an object is responsible for its own persistence it does not have to expose every property that needs stored, however this approach does, to my mind, break the domain model as now an object, no matter what logical layer it's in, needs to access the data access layer directly.
If persistence is separated into its own assembly, logical or physical layer then the object which needs persistence must either expose all its properties (going against the grain of an object should hide its internal data) or reflection comes into play if you try to write a generic persistence layer and you have end up writing custom attributes to drive the layer, which again means an object must have some knowledge of the persistence mechanisms in place. However I see the following advantages to separation;
- Object hydration could be done on a separate tier/app domain. e.g. going down the SOA route you would have a web service somewhere which will load a user from a database and return a populated option. This could also lead to fun scalability, where a load balanced cluster of web servers will populate your data for you, provide caching and so on. I'm ignoring remoting here, but the thoughts are equally valid, even if remoting is going the way of the dodo and those darned events just never work right.
- Paranoid security. For example, if I have my paranoid hat on, I would have a business tier somewhere which has access to the underlying database. Users would not have access to the database, and the app domain would run in the context of the only user with access to the data store, be it access via web services, remoting, or a simple configured assembly.
- Cargo culting. If you look at .net's serialization it is in a separate namespace, and arguably is not part of an object. It is a separate part of the framework, and a separate IFormatter() is responsible for persistence. Thus by separating out object persistence you're mirroring the .net framework
If I want to add lazy loading into the picture then it's very easy to end up with circular references.
Is there a single answer regarding this? Fowler attempts to present a common vocabulary for all this in his book "Patterns of Enterprise Application Architecture", documenting Lazy Load and separate persistence layers becoming Table Data Gateways, but no answers are presented for the circular reference problem. I doubt it. ORM fits nicely into this, but it's not an answer, it simply hides the question. I guess it will be a case of try it and see.