Today I was inspired by Scott Hanselman to get my blogging act together. It’s been awhile, maybe nine months or more. It’s way overdue.
I’ve been helping a colleague on a (currently confidential) project for the NYSE. The goal is to introduce Domain-Driven Design in some incremental steps. He posed a few questions today. The discussion starts with this background: “PROJECT_NAME has both service ‘domain’ objects and data ‘domain’ objects (mostly called the same names and they give it the domain namespace, not I). The transport mechanism delivers “service” objects from the UI and other services. When they are ready to be Hibernate persisted they get transformed via Dozer to a data ‘domain’ object. For instance, while some service is dealing with an order object, it is a service ‘order’ object. When the service throws it over the wall to the Repository, the service Dozers it to a data ‘order’ object and shovels it into the queue channel for delivery to the DAL.”
He continues: “If I understand you properly, as a rule of thumb for a rich domain model given this architectural world-view, we would generally replace setters on the ‘domain’ objects with business-type methods (what we’ve been doing for ages). But the Hibernated data ‘domain’ objects, well, I don’t see much need for them to have getters and setters either given that Hibernate no longer needs them. That is, given Dozer.”
In a nutshell, this is his question: “What is your world-view without Dozer? Just one domain model with Hibernate annotations also (given that the client is using annotations and not xml)? Or do you split the model as they do and just get-set? Or other?”
This is a pretty typical question among those unfamiliar with the DDD “world view.” So don’t feel shy about having similar quandaries. If you are familiar with DDD, what might your response be? Here’s what I had to say…
You gave the right answer. It’s just dozing data around. So in the end, what really is the difference between the “service object” and the “domain object”? Probably not much difference. It’s just mapping attributes around. And Dozer covers over any business intent what so ever. Everything is reduced to anemia. Like my Chapter 1 [of Implementing Domain-Driven Design] says, it’s “Anemia Everywhere.”
So two months from now, bring in someone who knows nothing about PROJECT_NAME and tell them to go explain to you what the business value is of a given use case. It will probably take them hours to explain it because they will have to start at the source of the data, in some other system, and trace it all around. In fact they may never be able to tell you exactly because there may be deep insight hidden in the data mappings that only a conversation with a specific group of desk traders could reveal.
However, if using DDD you would have one simple place in the model where you’d go and look at a single line of code and say: “Oh, that’s what’s going on here.” It’s because the model would capture exactly the intent — not of the developer — but of the specific group of desk traders who originally spec’d the system that they wanted.
That’s the difference. In the end you may choose not to use getters and/or setters of any kind, because as you state, Hibernate doesn’t need them.
If you really need to cover Chapter 1 again to understand that clearly, I’d highly recommend that that’s where the real answer to your question is found. It’s not really clearly Chapter 7 that reveals that. Domain Services are just one tactical tool to help you model in a specific situation. But it’s the Ubiquitous Language in and explicitly Bounded Context (an application or business service with a domain model) that addresses this.
If my answer highlights the need to refresh your resolve for stick with the DDD Ubiquitous Language rather than technical solutions that usually lead to Anemia Everywhere, take a refresher here: Implementing Domain-Driven Design; Chapter 1, Getting Started with DDD.