EDIT: I missed something the first time around. If some persistence tool makes it so that I can only put business logic in my domain models using a partial class, that’s an automatic FAIL!
My latest article in the Patterns in Practice column is in the June edition of MSDN Magazine. This time around I continued the discussion about persistence patterns with the Unit of Work Pattern and some (very watered down) discussion about Persistence Ignorance. Granted, this isn’t my favorite article I’ve ever written, but these are important topics that I think everyone needs to consider as part of their persistence strategy. For you folks out there that say “bah, humbug, I don’t need no POCO,” I think you need to at least consider the issues before you blow it off.
To summarize, *I* think Persistence Ignorance is important for these reasons in descending order of importance (you can argue whether 3, 4, or 5 is more important):
- Can I exercise my business logic and user interface without having to drag in the database? This is crucial for efficient unit testing. With the way the Entity Framework v1 did lazy loading, the answer is no. With NHibernate and maybe EF v4, the answer is yes.
- Can I design my object structure and database model independently? In other words, don’t make the database model dictate the shape of the object model. As the complexity of the system grows beyond dirt simple, codegen’ing the object model from the database tables is teh suck.
- How easy is it to make small incremental or evolutionary changes to my domain model? Again, I think code generation schemes that start from a complete database model and generate the object model are optimized for BDUF and become unwieldy in the face of small changes. Solutions that require change tracking to be coded directly into the domain model make incremental changes harder because of the extra weight of changing or adding new properties to the model.
- What strictures does my persistence tooling place on my object model? Marking properties as virtual just to enable lazy loading is annoying. Having to expose public properties of inner collections like Lists or Sets destroys encapsulation and is completely unacceptable to me. My persistence tool shouldn’t force me to compromise encapsulation. I really don’t want to have to inherit from a base class in the framework. It’s very valuable to use my own Layer Supertype for my domain model rather than blowing my one superclass on infrastructure goo.
- Lastly, I don’t want persistence methods cluttering up the public interface of my domain model classes. Interface Segregation Principal baby!
For the record, it does look like from a shallow reading that the new EF v4 looks much better than EF v1 did — but still falls well short of NHibernate. It all depends on how much you really care about this stuff. *I* care deeply about the ability to design continuously and incrementally, clean separation of concerns, and test driven development. To me, the object model is the main player in the application and the database is nothing but a persistence mechanism. If you don’t care about those things, or are just simply too engrained in data centric orthodoxy to change, then you can happily ignore that list.
Go ahead and argue away I suppose. I’m offline for the next 3-4 days, so you automatically get the last word in;)