Software with Agility
Do you really need an ORM?
July 25, 2011Posted by on
An Object-Relational Mapping (ORM) is necessary only when you have 1) an object model, and 2) a need to persist this object model to a Relational Database Management System (RDBMS).
The latter may be a given, especially in web-based scenarios. However, the former is not always so clear-cut.
You have an object model if you have a collection of fully-fledged classes with both data and behavior.
Object Oriented Design (OOD) is predicated on the tight coupling between an object’s data and the methods that operate on that data. Without the associated behavior you are left with an anemic domain model. What you have is an object graph with relationships and data that map to the problem domain, but the fine-grained behavior is limited to getters and setters for the data.
Often, the ‘business logic’ is extracted into a service layer which orchestrates the objects at a much more coarse-grained level.
The UML diagram shown is a very simple blog class diagram. Notice that there are objects, with names matching the nouns in the problem domain. However, there is no behavior on any of the objects. User is missing verbs like Login, CreateCategory and SubmitComment. Post is missing verbs like SaveDraft and Publish. Comment is missing verbs like Accept and Flag.
These are the fine-grained behaviors that will probably end up rolled into a service layer’s higher-level functionality. There is nothing wrong with this, providing that there is not an ORM sitting between this object graph and persistent storage (as opposed to just serializing the object graph).
As blogs are typically online, it is reasonable to assume that there would be an RDBMS used as the persistent storage. This covers one half of the prerequisites of using an ORM. But there is definitely no need for an ORM here because there is no domain model.
So, what are the alternatives?
Rather than enumerate the high-level patterns that Martin Fowler has already suggested, I’ll jump into technology choices instead. Assuming that the ORM of choice was originally NHibernate, you could just choose a simpler ORM such as Entity Framework. This will certainly make generating the mapping code far simpler than learning NHibernate’s configuration files. But, even that could be argued as overkill.
Perhaps Active Record would be a good fit, but again this is also a suitable alternative when there is behavior inside the objects, thus potentially overkill.
The simplest solution that I would advocate when there is no behavior in the domain model is a Typed DataSet. First of all, a typed dataset can be generated from an existing database and this yields the CRUD operations for all of the tables, as well as locally maintaining referential integrity without having to hit the database again.
Furthermore, if deemed necessary, the messy auto-generated code can be hidden behind neat interfaces for each domain object by adding a partial definition for each class generated – as long as the properties match the type and name of those generated.
What we are creating with this pattern is merely Data Transfer Objects (DTOs) – which is pretty much what we started with because DTOs are objects without any behavior. We’re just admitting the fact and making design decisions based on that admission.
Perhaps you may think that there will be a future requirement for behavior in your domain model which merely hasn’t yet been fulfilled. Perhaps, but until that day comes, you would save a lot of effort by starting with the simplest thing that works.