views:

118

answers:

3

Take this simple, contrived example:

UserRepository.GetAllUsers(); UserRepository.GetUserById();

Inevitably, I will have more complex "queries", such as:

//returns users where active=true, deleted=false, and confirmed = true
GetActiveUsers();

I'm having trouble determining where the responsibility of the repository ends. GetActiveUsers() represents a simple "query". Does it belong in the repository?

How about something that involves a bit of logic, such as:

//activate the user, set the activationCode to "used", etc.
ActivateUser(string activationCode);
A: 

These are all excellent questions to be asking. Being able to determine which of these you should use comes down to your experience and the problem you are working on.

I would suggest reading a book such as Fowler's patterns of enterprise architecture. In this book he discusses the patterns you mention. Most importantly though he assigns each pattern a responsibility. For instance domain logic can be put in either the Service or Domain layers. There are pros and cons associated with each.

If I decide to use a Service layer I assign the layer the role of handling Transactions and Authorization. I like to keep it 'thin' and have no domain logic in there. It becomes an API for my application. I keep all business logic with the domain objects. This includes algorithms and validation for the object. The repository retrieves and persists the domain objects. This may be a one to one mapping between database columns and domain properties for simple systems.

I think GetAtcitveUsers is ok for the Repository. You wouldnt want to retrieve all users from the database and figure out which ones are active in the application as this would lead to poor performance. If ActivateUser has business logic as you suggest, then that logic belongs in the domain object. Persisting the change is the responsibility of the Repository layer.

Hope this helps.

Joel Cunningham
In response to your last paragraph: What if "persisting the change" IS the only logic. e.g. ActivateUser() simply updates one record in the User table and one record in the ActivationCode table. Does that constitute "logic"? If not, what does?
betitall
+1  A: 

Repositories are responsible for the application-specific handling of sets of objects. This naturally covers queries as well as set modifications (insert/delete).

ActivateUser operates on a single object. That object needs to be retrieved, then modified. The repository is responsible for retrieving the object from the set; another class would be responsible for invoking the query and using the object.

Bryan Watts
+1  A: 

When building DDD projects I like to differentiate two responsibilities: a Repository and a Finder.

A Repository is responsible for storing aggregate roots and for retrieving them, but only for usage in command processing. By command processing I meant executing any action a user invoked.

A Finder is responsible for querying domain objects for purposes of UI, like grid views and details views.

I don't consider finders to be a part of domain model. The particular IXxxFinder interfaces are placed in presentation layer, not in the domain layer. Implementation of both IXxxRepository and IXxxFinder are placed in data access layer, possibly even in the same class.

Szymon Pobiega