14

Should I always go through the services when I try to follow DDD?

Or can I use a repository directly to get a domain object?

jgauffin
  • 99,844
  • 45
  • 235
  • 372

3 Answers3

14

Personally, I don't like seeing repositories in controllers, or in the presentation layer in general. But I've seen it many times and there's nothing wrong with it in the context of DDD.

I think the answer is that it depends on how big your project is. A service layer is more often found in more complex projects. Whereas simpler MVC websites for example just use repositories directly.

autonomatt
  • 4,393
  • 4
  • 27
  • 36
  • 1
    "I don't like seeing repositories in controllers" => can you elaborate on why and what intermediate layer you'd add between the controller and repository ? – guillaume31 Jan 23 '12 at 13:04
  • 4
    Controllers tend to get bloated very quickly. One of the reasons for this is because devs end up sticking business logic in their controllers. Business logic should only live in the domain layer primarily, and then in the service layer - not in the controller, and not in the repository. By using an (Application) Service in your controller you avoid this. So for example you would call accountService.GetUserByEmail(email), or catalogueService.GetProductViewModel. Your controller stays nice and lean and your application service coordinates talking to various repositories. – autonomatt Jan 27 '12 at 12:27
  • 4
    Just because you get an object from a repository doesn't mean you deal in business logic. It's just about *getting the object across* from the domain layer to be used in another layer. And I can't see how a single-line userRepository.GetUserByEmail(email) bloats the controller more than accountService.GetUserByEmail(email). – guillaume31 Jan 27 '12 at 15:32
  • If you tell me your Service transforms the domain object into a ViewModel object, then maybe it's useful, but this can be typically done in the Controller as well, and it doesn't justify such a definitive assertion as "you shouldn't use repositories in controllers". Apart from that I can't see the benefit of such an additional layer of indirection. – guillaume31 Jan 27 '12 at 15:33
  • 3
    You've turned my "I don't like seeing..." into "you shouldn't use ...". The former implies preference. I'm not trying to tell you what to do. Your question will always yield a subjective answer, and there is no right or wrong here. I'm saying as someone who has dealt with very large controllers, I prefer and recommend keeping as much code as possible out of controllers. I also use the Specification Pattern to keep my queries in my domain layer. See [this answer](http://stackoverflow.com/questions/8234068/in-which-layer-should-specification-pattern-objects-be-newed-up/8244451#8244451) for more. – autonomatt Jan 30 '12 at 11:11
3

Or can I use a repository directly to get a domain object?

You definitely can. It's precisely the goal of repositories. I wonder what kind of a service you'd otherwise use for that (except in the specific context of an SOA or web service based architecture).

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • My (intended) question was if I can bypass the services and get domain entities directly from the repositories (for instance in a MVC controller) – jgauffin Jan 23 '12 at 13:06
  • Well I got it right and the answer is yes :) It's funny to see that something considered perfectly normal and common if you look at the original DDD book and movement now seems to scare people... – guillaume31 Jan 23 '12 at 13:17
  • 1
    I'm not scared. I just wanted to know what the best practice is. The book was released nine years ago and there might have happened one or two things since then.. – jgauffin Jan 23 '12 at 13:32
  • There's no best practice, only practices that are suitable *in a given context*. Now the 2 lines you wrote don't give us much of a context... – guillaume31 Jan 23 '12 at 13:48
0

After completing my first project structured using the DDD principles :D, I found that it is useful to have both domain services and repositories that are available for the application layer to consume.

KEY POINT: The application layer may be your WCF services or the code in your web services if you're using that architecture. It all depends on your implementation. If it suits your implementation, your application layer may be the same as your presentation layer, thus having the application layer code in your contollers or web forms code behind.

Repositories function like in-memory collections. To the application layer, the code should look like you're just using any old collection.

Domain Services function more like processors or accessors to information that will never be updated, maybe processed, but not updated directly. To the application layer, the code should look like you're just using any old web service.

That being said, I will explain more with some examples:

Repositories

My repositories actually inherit from a generic collection typed with an implementation object I created that encapsulates the database key and the business model together. Using this approach, I can define an indexer in my interface such as

BusinessObject this[int index];

and I can have a getter that will return the business object based on the index of the underlying collection and a setter that will lookup the data key from the underlying collection and save the object to the database. This makes the application code extremely simple, for example

IBusinessObjectRepository repository = new SqlBusinessObjectRepository(sqlString);
BusinessObject obj = repository[0]; //Get first object in the list.
//Make some changes to the business object by setting properties or calling methods to process business logic.
repository[0] = obj; //Save the object back to the database.

Services

I use services to retrieve lists of entities and value objects that I am not going to edit individually and, in my case, are only used as available selections or values when calling methods on the aggregate root. Generally, I cache this information on the web server. This is not the only use for a domain service, just my example. The application layer code still remains relatively simple.

IBusinessService service = new ImplBusinessService(implementationArgs);
List<BusinessObject> objsToCache = service.GetBusinessObjects();
//cache the objects on the web server.

In conclusion and from my understanding of DDD principles, the application layer should be able to access business objects from either services or repositories. The choice between them comes down to what fits best within the domain model.

Aaron Hawkins
  • 2,611
  • 1
  • 20
  • 24