I was asked to produce some templates for generating (or alter some existing ones if I could find them) an ActiveRecord enabled domain model from an existing database schema. It got me thinking… I don’t agree with code generation in the domain model.
Why I hear you ask?
Unit Testing & TDD
Generating the domain model in one fell swoop means you need to go back and retrofit your tests. This approach sucks for several reasons…
- Assumes you know enough about the domain to be making all your design decisions up front
- The process of TDD ensures OO principles are adhered to (or at least easier to adhere to). Code generation assumes a certain amount of inflexibility in the produced code. You don’t get the chance to special case and drive out design by actually consuming the code during design
- It generally doesn’t get done. Show me a developer who said they would “add the tests later” and actually did
The learning process
The code is being generated to make up for a lack of understanding of domain driven design and more importantly ActiveRecord/NHibernate by some team members. This is simply throwing more wood on the fire. I’ve said it before, nothing beats experiential learning. Give those developers the guidance and support they need to enable them to make design decisions and understand the technologies they’re using. As Ayende said:
…if you need to invest a week in your developers, you will get your investment several times over when they produce better code, easier to maintain and extend and with fewer bugs
Backwards thought process
I might not articulate this point particularly well, but still I sense there’s something not quite right about producing a domain model from a database. The object model should facilitate the relational model. Sure, not every system has the luxury of a green-field relational data source… But those that do are better served by a relational model that serves the domain model. Told you I wouldn’t articulate this very will didn’t I? 🙂
I’m not saying I don’t advocate code generation. It just needs to be applied liberally. Generation implicitly (and by its very definition) produces boiler-plate code. Boiler-plate code has no place in the domain model.