Recently, I had a heated discussion in a .Net list about ORM tools that are centered around code-generation, like Subsonic. (Okay, okay, SubSonic is more than ORM). While SubSonic has a very decent ORM solution, I can’t agree that code-generator produces decent ORM.
First of all, code-generator *conveniently* produces all entity’s properties as public getters and setters. This conveniency is exactly what I refer to as violation of encapsulation notion in OO principles. When an entity exposes all of its states, it becomes very easy for layers above it to change them. And this easiness is not a good thing. It leads into the an unmanagable code where making a small change would involve poring over thousands of lines of code. By letting anyone to freely mutate entity’s states, we allow business logic to be just dumped into a class and be called.
Second problem is that all auto-generated classes are practically owned by the auto-generator. They steal them from you. Remember, if we somehow attempt to change the autogenerated code, we will lose it the next time we run auto-generation. We no longer own the classes. If we can’t add any behavior to the entities, then they will be nothing more than a mere dumb data cargo. Anemic Model, the same problem that I had before. It’s just CLR version of databse table. Then someone will need to give me a good reason why I still should call it Object Relational Mapping?
The argument about productivity advantage offered by code-generation is not entirely valid either. Now there are 2 parts of a typical business application (among others): domain objects and database. Subsonic autogenerates domain objects from database structure. The others (like NHibernate) generates database structure from domain objects. None can generate both, which is good news for us, software developers, since we apparently are still worth some salary.
The question left is now which one you want to write yourself, and which one you want the machine to do for you.
If you’re writing an business application that involves complex business logic, then you will find domain objects as the heart of your application. And you will want to write them yourself. The tedious part of managing persistence can then be delegated to our fool auto-migration. This is the most common approach in NHibernate.
Now if you’re working in data-centric application, particularly thus involving complex data structure, then you will find your database as the heart of your application. You spend most of your time on tables and SQL scripts. In this case, domain object is just a boring part that merely sits there to bridge your data to presentation. Let code-generator does the brainless job for you. And SubSonic is really good on this. Castle AR and NHibernate also provide this approach.
Having the codebase owned by the tool is not necessarily a bad thing. If we don’t own the code, then we don’t have to spend the cost of maintaining it. The tool owns the code, the tool nurtures it for you.
Another arguably good situation where you should use code-generation for ORM is when you’re working on legacy database, typically when you are rewriting legacy code. This is probably true, but I would only use the auto-generated entities as datastructures, not as objects. Pretty much to treat them as dataset, where you need to add an adapter layer to map them into domain objects that will be the only things used by the rest of the application.
Either way, most people wouldn’t classify code-generations (like Linq2Sql and Subsonic) as ORM, because, quite obvious, there is no mapping going on there. It’s just a strongly typed interface to database tables. To bridge impedance gap between the 2 worlds, you will have to write your own mapping from auto-generated *table-object* into your own domain entity.