Nov 9, 2008

Persistence Ignorance and ORM

The purpose Of Persistence Ignorance is to keep your domain model decoupled from your persistence layer. Nilsson establishes the following characteristics as things you should not have to do in persistence ignorance

Inherit from a certain base class (besides the object)

A common pattern in ORM solutions is to force consumers to inherit from a provider-specific base class. The reason for this is dependent on the provider, but typically the base class has some sort of attribute or method required for persistence. This is not a significant problem if you’re designing a system from the ground up, but if you already have a domain model and you’re trying to add persistence, this can be a pain because .NET supports only single inheritance.

Instantiate only via a provided factory

Domain Driven theory supports the use of factories when building domain models. We don’t want to have to use a provider-specific factory implementation to create our persistent classes. This couples our model to the ORM instead of keeping it independent, and is usually required by ORM solutions for object tracking and notifications.

Use specially provided data types, such as for collections

This is another pretty typical situation that you’ll see in ORM tools in order for them to provide functionality for out-of-the- box lazy loading. This is so common in the ORM solution world that it doesn’t bother me too much, because you can usually design around this functionality to keep your model independent. However, I can understand the desire to have this as a feature of your ORM.

Implement a specific interface

Similar to base class inheritance, this is another situation in which the ORM engine needs a specific implementation in the persistent classes to do its job. This is obviously a better design, to have to implement an interface instead of having to use up your only class inheritance option in .NET, but you are still tightly coupling your domain model to the ORM, making it less portable.

Provide specific constructors

This is common in ORM solutions so the engine can create instances of your domain model type or reconstitute a particular value. My personal opinion is that having to implement a default constructor doesn’t really violate any major design law. However (and I have yet to see an example this), anything beyond the default constructor implementation would be a significant irritation.

Provide mandatory specific fields:

Providing specific types on fields (for example, a GUID for an ID) is sometimes mandatory in ORM frameworks. This is often part of an interface or a base class implementation, and is required in many cases for handling associations and relationships.

Avoid certain constructs and forced usage of certain constructs

This criterion can consist of a forced access modifier on a field or method or can be the metadata used for mapping. A good example of this is using get and set functions as you might in Java versus a property in C#. Additionally, as you will see later, this can also be the use of .NET attributes in your model. Attributes, extraneous methods, base classes, and so forth are a big concern of mine when developing a domain model because I don’t like having to change my well-thought- out access modifiers or pollute my model with some garbage in order for the persistence engine to work.