Wednesday, January 5, 2011

Your enterprise domain model should not be represented in code

I blame Hibernate and Spring in the javaspace as well as a number of enterprise architecture astronauts who don't know how to communicate the difference between a conceptual model and a physical model (yeah, I'm probably one of them). Any number of java projects I've been on over the last 10 years or so seems to have followed what is now a fairly predictable anti-pattern. I'll call it the massively brittle domain model (MBDM).

The pattern goes like this: Build an java (C#?) data model representing all of the business "things" you think the business needs (extra points for spending a couple years building that). Usually this ends up being a funhouse mirror image of a bunch of relational database tables. Then you expose those objects via some sort of service layer, and build a binary package for all the clients to communicate with the business services. If you really want to make things complicated, use some sort of complicated xml serialization mechanism that requires configuration files or generating stubs and other fun stuff.

I can only imagine this working when the following are true: IF your domain model is perfect the first try, and IF your business doesn't change, and IF there is only one developer and IF there is only 1 server and IF there is only 1 client application.

Let me explain why this will not work in other situations:

First off, because the domain model is distributed as a binary package, the most typical pitfall is to rely on a serialization mechanism that fails the minute you change ANY of the domain entities. This essentially means that any project that uses your services will need to be recompiled every time someone changes the anything in the domain. This has the effect of coupling every client project to the back-end project. This causes a large amount of complexity in coordinating which version of the domain various clients need.

Second, because of #1 your development will inherently resist changes to the domain model. This means that you will descend into a serious of arguments with your business partner that essentially translate "we didn't model it that way and it's a fundamental change to our domain model which will break other systems".

Third, because of #1 and #2 coordinating which version of which domain entity you actually need will become a full time job. In addition, if you have multiple servers and services that are interconnected you will tie up multiple resources trying to keep things in sync.

If you find yourself in this mess, your first step is to remove the binary dependency. Note, this may be very difficult because invariably someone will have introduced secondary and ternary dependencies, most likely via the ubiquitous "utility" package that binds domain model to the binary service implementation. The key thing to do is to forget about the underlying database and binary representation when building services.

Put another way, build services around "things that need to get done and the information necessary to do it". While semantically, this means you will likely build a model for each service, that is better than trying to shoehorn everything into a one size fits all model of reality.

If you're building a new system and someone tells you they're going to build a "enterprise domain model" that "everybody can use" and it'll be "reusable", tell them it's probably a bad idea and point them to this blog post.


Bill Christian said...

Amen. I have been preaching this same idea for a few years internally to no success. The worst offender are the SOAP advocates using marketicure white papers from tool vendors on the benefits of data binding. Data binding is the devil. It makes change with clients impossible.

Anonymous said...

How do you handle aggregating and working with data that has been spread across multiple services as mentioned toward the end of your post? Do you create a new service to wrap around this aggregation or do you pull from all of the services and merge them in the new layer?

Mainguy said...

I'd say it's normally reasonable to have something act as a facade or composite that represents the combination of two (or more) services. On the other hand, it might be that the two independent services should be refactored.

I'd further say that there MIGHT be a need for a master data model, but that should be a logical abstraction used for communicating ideas between humans, NOT something that should be implemented in software.