Hi,
I'm also struggling with the "proper" DDD-way of doing things. By proper I mean finding out how it fits into the rest of the world, rather than dogmatically applying everything I find in the net. I think we need to discuss more specific topics to gain a better understanding.
I'm still half-way through the book and here's my take on things:
My understanding is that DDD is all about your business tier. It doesn't mention much (at least as far as I've got) about other aspects such as the presentation/services tier.
I'd expect that writing a DDD application is not so different in those regards, other than the fact that perhaps you've moved some (or a lot) of business logic into the domain and there's less in the services tier.
So here's one concrete question: How do you handle transaction demarcation in DDD?
Let's say you have methods on your domain objects that allow them to (agnostically) access persistence through repositories. Who do you allow to make such calls? Do you make the domain object @Transactional and allow anyone to use them (e.g. even the presentation tier)? After all, what's the point of having an order.save() method if the controller has to go through a service to use it? But isn't that a violation that pollutes the domain model with persistence implementation information? Ok, it's just an annotation, but the domain object suddenly becomes able to define a transaction boundary for some code path that ends up invoking a DB/JMS/... resource that it is unaware of.
Coming from a "traditional" background, I favor clear separation and require that client code (e.g. presentation tier code) goes through some transaction boundary (e.g. a @Service in your services tier). The result of my approach was that after injecting "repositories" into my @Configurable domain objects, I couldn't get to them from my presentation tier unless I violated my principle of starting transactions at a clearly-defined boundary in my application... So I tried to keep the transaction boundary and realized that I must have taken a horribly wrong direction when I started writing stuff like:
Code:
Order order;
// ...
pubic void handleButtonPressInPresentationTier() {
// order.processOrder(); <-- this would fail as it's not @Transactional
orderService.submitOrder(orderDomainObject); // this is @Transactional
}
But then in the services tier:
Code:
// this service class is @Transactional
// ...
pubic void submitOrder(Order orderDomainObject) {
orderDomainObject.save(); // ends up calling repository
}
So then, why not inject the repository into the service and NOT have a save() method in the domain object?
Perhaps a middle ground would be to have domain objects annotated as @Transactional(propagation = MANDATORY). Then you can indirectly use resources at the domain object level (via the repository), while at the same time preventing direct access from any entry path (calling into the repository via the domain object requires that the client has already started a transaction, which is documented in the code via the annotation)...
Then again, perhaps I'm still too "transaction-script-oriented" and am missing the point?
Any comments on the above would be appreciated.