views:

47

answers:

1
  • In the consumer code? (like a controller)
  • In repositories?
  • In services?
+3  A: 

For starters, that's a pretty controversial question, so you are bound to get many different answers.

My own take on this is that (ACID) transactions are a feature of certain storage mechanisms (most notably relational databases), so I consider the concept technology-specific. Before anyone protests that this is only a theoretical argument consider that there are several conceivable cases where the data store (Repositories) would not be transactional:

  • Many large-scale enterprise (such as e.g. Amazon) don't use transactions for performance reasons. Instead, they have an architecture that enables them to deal with failures
  • REST-based data services
  • Test Doubles

Since Domain Models should be decoupled from specific implementations, I find it logical that they know nothing about transactions. However, this also means that the Repositories must expose operations of the right granularity so that they, themselves, can manage transactions, should they so desire, and an operation is guaranteed to either success or fail in its entirety.

In other words, Repositories should manage transactions (if applicable).


There are, however, situations where this may require the Repositories to have too much Domain knowledge, so the Unit of Work design pattern provides a good abstraction for the cases where you truly need a (potential) transaction to span multiple operations on several different Repositories.

Mark Seemann
+1 for repositories. I'm inclined to agree with you that transactions are technology-specific. However, units of work are application-specific, so I'm wondering how you decouple the technology from your units of work. Does the repository really have to have knowledge of your business domain?
Robert Harvey
@Robert Harvey: Thank you. Unit of Work is a very relevant pattern and I don't know how I managed to momentarily forget about it while writing my answer... The Repository need to have some knowledge of the Domain Model unless you want to decompose all input and output into primitive types (not a good idea IMO), but I agree that knowledge shouldn't extend to the business logic. I'll update my answer.
Mark Seemann
It seems reasonable that in most cases, transactional logic should reside in repositories. However, using a unit of work, would IMO shift the responsability up a notch. Where would you see it fit better, application level or service ? I can't think of a good reason to vouch for one or the other without a specific context...?
julien