databases as life-support for domain objects

In his article Domain-Centric Programming J.B.Rainsberger tells a very nice story about how a project was improved by leaving the database development to the very last.

“The last thing I did was to build a simple, four-table database schema and a small component that read from and wrote to the live database. Since I had practiced test-driven development … I had high confidence that I had implemented everything correctly. Since I had focused on the domain, rather than the database, I was even more confident that I had gotten the database right the first time.”

(Thanks to Brian Marick for bringing the article to light, via the agile-testing group on Yahoo.)

By pure coincidence I’ve been telling very similar stories on a project I’m coaching at the moment. We’re currently investigating approaches for the architecture of a new product line, and the group thinks that we might gain a lot by thinking in terms of a hexagonal architecture. During the last couple of weeks I’ve been thinking a bit more about such models, and I’ve come to a rather remarkable conclusion: the database is not on the outside. I now believe that the database is merely one of the technologies that together create the nutrient environment supporting the objects in the middle hexagon.

As J.B. said in his article, the database exists solely to bring persistent state to the domain (and application) objects. Logically, then, it isn’t part of the “outside world”, to be connected by an adapter to the domain objects. Instead, it’s part of the memory model in which the action takes place. It’s one of the tools used to build the middle hexagon. (I feel instinctively that the adapters shouldn’t have persistent state. I’m probably wrong.)

Think of the domain objects as being “always there”. When the adapters are talking to them, they’re in primary memory. But when no-one is interested in them they may be archived out to secondary storage. If someone needs one of them again, the middle hexagon arranges to “re-inflate” any archived objects. This may show up as a slight delay – just as when you re-access an application that was paged out by your operating system. The delay in opening a connection to any particular domain object depends on “how far away” it has been archived: instantaneous when it’s active in memory, slightly longer when it has to be awakened from a database, longer still if it was archived to an old guy in a back room with a quill pen. Whatever the technology used, though, it’s still just technology. Still nothing more than the life-support environment in which the domain objects ply their business.

I discovered during our workshops last week that this is a huge topic. I’ve only scratched the surface here, and I haven’t had the time to work through all of the consequences in practice. But the ideas do seem to hang together, at least in this person’s head if nowhere else. More to come, I expect…

6 thoughts on “databases as life-support for domain objects

  1. I disagree. If you make the domain objects dependant on the database then you are effectively back to a layered architecture. To me, the big draw to hexagonal architecture is the ability to use the domain objects anywhere in the system, especially in a rich-client. But if your domain objects are dependent on the database you can not use them from a rich client without reverting to a two-tier design, with smart ui’s connecting directly to the database.

    In my experience, the best way to build your domain model for a hexagonal architecture is to start with verb-oriented “command” or “service” objects, and factor out domain objects as they are needed to avoid duplication. For example, you might have a class called CreateAccount which contains all the data needed to create a new user account on the system. You might also have an “UpdateAccount” command, and you might find that they both need the same information, then you would create a class “Account”. Iff you have complex account related domain logic (as opposed to presentation or persistence logic) you should add it to your account class.

    It sounds a little like you are headed back to the layered, or even client-server architecture if you don’t keep your persistence code at a good distance from your domain logic.

  2. Hi Brian,
    I think we’re mostly in agreement. I too would want to make the domain objects independent of the database – just as they are independent of the garbage collector. I guess the article is trying to say that I regard these two things as being of the same kind. Both are technologies we’ve used in building our application.

    Where we do perhaps differ is in how we perceive the contents of the middle hexagon. By putting the database into the middle hexagon I am not implying that the domain objects will necessarily depend on it. There will be many clusters (to use a nice Eiffel term) of objects in the middle hexagon, with many and varied dependencies among them. I’m arguing that the persistence mechanism will be one such cluster, and I would hope that solid use of TDD will render it replaceable with mocks.

    In persistence stories arrive late I note that the persistence model is naturaly something we’ll add fairly late (assuming we’re following the agile way and developing in order of decreasing value). It seems to me that this – and TDD – will naturally lead to the domain objects being independent of their persistence architecture.

  3. Pingback: persistence stories arrive late « silk and spinach

  4. Pingback: 2005 silk and spinach top ten « silk and spinach

  5. Pingback: Where is the database? | silk and spinach

  6. Pingback: Hexagonal architecture – Alistair Cockburn

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s