DOMAIN SERVICES ARE NOT REPOSITORIES!

2016 05 09

Author: Tomaš Maconko

Many of us like to use Domain service and Repository patterns to split responsibilities to get code look better. But recently I noticed that developers are mixing those patterns and they are implementing them in bad way.

First, lets look into the purpose of those patterns.

Repository pattern purpose is to read or write data into certain storage. It is an adapter between domain and data access layer. Repositories can hide complex queries, mappings and other code-noisy stuff under the implementation, so the domain code is cleaner.

Domain services are used to work with domain entities according to domain rules. It can ask repository for data, make work with it and save it back into storage. Domain services should collaborate with repositories together to make a result.

Lets look at next example (here I reveal the good things I liked):

[csharp]
public interface IBlogPostsRepository
{
IQueryable GetBlogPosts();
BlogPost GetById(int blogPostId);
void Save(BlogPost blogPost);
}

public class BlogPostsService
{
private readonly IBlogPostsRepository _blogPostsRepository;

//...
public void UpdateBlogPostContent(int blogPostId, string content)
{
var blogPost = _blogPostsRepository.GetById(blogPostId);
blogPost.Content = content;
_blogPostsRepository.Save(blogPost);
}

}
[/csharp]

Here we see, that domain service is asking repository for certain entity (or entities) and makes some work with it. That’s all that service should do and it is pretty much the same the pattern definition says.

In application root (web, desktop, whatever) we can can use both repositories and domain services. One is used for showing data or data projections in UI, the second one – for executing commands. That is all about integration of repository and domain services.

But reality is poor. I often see, that services are done in wrong way. People implement them to work as repositories and even more – people wrap repositories using domain services. In my opinion it breaks single-responsibility principle. Service will be getting bigger and it may lead into complexity. Whenever update or fix is needed, developers shall update more and more places. That is a way into bugs world.

Lets get back into examples. At last example I did not reveal the bad things, so lets look at it now:

[csharp]
public class BlogPostsService
{
private readonly IBlogPostsRepository _blogPostsRepository;

//...
public IQueryable GetBlogPosts()
{
var blogPosts = _blogPostsRepository.GetBlogPosts();
//Doing whatever
return blogPosts;
}
//...

}
[/csharp]

As you see, services acts as repository wrapping repository inside. People explain this saying there are things that must be applied after data is loaded from storage. My suggestions is to move those things into repository, because repository is also a part of the domain and you can make data-translation rules before the data is returned.

Structuring repositories and domain services in this way it will lead into smaller classes and more strict responsibilities, so detecting and fixing bugs will be as simple as possible! Enjoy it!