Sep 29, 2014
Table of contents:
An important concept in Domain Driven Design is the modelling of domain logic in Entities and Value Objects.
As we’ve seen over the last couple of weeks, we can use Value Objects and Entities to model and protect the business logic of our applications.
However not every action or piece of functionality will fit neatly into this theoretical workflow. Inevitably we will have a requirement that doesn’t quite belong as a method on any of the existing Entities or Value Objects.
This is where Domain Services come in. A Domain Service is taken directly from the Ubiquitous Language, but doesn’t naturally fit on any existing Domain Object.
In today’s article we are going to be looking at exactly what Domain Services are, when to use them, when not to use them, and how to implement them in your applications.
Service is a very loaded term in computer programming that has all sorts of different meanings and connotations depending on the context you are using it in.
A Service in Domain Driven Design is simply a stateless object that performs an action.
For example, an
AuthenticationService would have the sole responsibility for authenticating users into your application.
An important characteristic of a Service is that it should not have state. So the
AuthenticationService should be used to perform an action such as
authenticate() but it should not hold any references to stateful data such as the current authenticated users.
The architecture of a Domain Driven Design project is split into three different layers.
The Application layer is how the outside world communicates with the model. This could be through HTTP requests, an API or through an automated messaging service.
The Infrastructure layer is how the actions of the model are executed. This could include persisting data to a database, queuing jobs, or sending email notifications.
And finally the Domain layer is where the business logic of the application resides. As we’ve seen over the last couple of weeks, this is where you have Domain Objects such as your
User Entity or
Username Value Objects.
Each of these different layers also require Service objects and so we have three different types of services for the Application, Infrastructure and Domain layers.
An Application Service is typically used to orchestrate how the outside world interacts with your application. For example
AuthenticationService would be an Application Service that co-ordinates how a user should be authenticated.
An Infrastructure Service is used for dealing with the technical details of the infrastructure. For example you might have a
MailGunMessenger service that enables you to send email notifications using the MailGun API.
And finally a Domain Service is used for encapsulating domain logic that does not naturally fit on any existing Domain Object. For example you might have a
RegisterUserService that co-ordinates how a user is registered within your application.
Whilst the differences between these three types of service seems pretty straightforward, it’s extremely important that the division of responsibility does not bleed into the wrong area of concern.
Domain Services are a great way to model a particular aspect of your business logic. However over-use of Domain Services leaves you vulnerable to the Anaemic Model problem.
The Anaemic Model problem is where Domain Objects are void of domain logic because it has been abstracted to a service class.
For example, you might have a
User entity that is basically just an empty class with getters and setters and a
RegisterUser service class that actually registers the user within the application.
The domain logic of registering a user has been robbed from the natural home of the
User entity and put into a service.
In essence the problem with anaemic domain models is that they incur all of the costs of a domain model, without yielding any of the benefits.
It is therefore extremely important that when modelling a particular bit of domain logic, you scrutinise whether it belongs on a Domain Object or as a separate Domain Service.
More often than not, you probably don’t need a Domain Service. You only need a Domain Service if the piece of domain logic you are modelling does not naturally fit on any Domain Object. A common scenario for this is when the responsibility of the action does not naturally fit on any particular object or if it requires multiple Domain Objects in order to co-ordinate the action.
An important bit of functionality that we are going to need whilst registering users is the ability to hash passwords. Storing plaintext passwords in the database would be a massive security concern, and so our business logic requires us to ensure that passwords are hashed before they are persisted.
Password hashing is a classic example of a Domain Service, but we will walk through the steps to determine why this is so.
Firstly, our domain explicitly states that passwords should be hashed before they are persisted to the database. Our business rules care about the security of passwords, and so “hashing passwords” comes directly from our ubiquitous language.
Secondly, it’s clear that the functionality of hashing a password is stateless. If you think about hashing as an input / output operation, no matter what string you put in, you will always get a hashed password out. The service itself does not store a copy of those passwords and so it is stateless.
User entity requires a password to be hashed, but it is not the responsibility of the
User to hash the password. The
User entity only cares about accepting a hashed password, it is not concerned about how the password is actually hashed.
We therefore have a piece of business logic that:
I would say that this is therefore an excellent candidate for a Domain Service.
We’ve established that hashing a password is indeed a Domain Service, but does the actual implementation of hashing a password belong in the Domain Model?
A Domain Service is derived from the Ubiquitous Language and it encapsulates business logic, so there is no doubting that it belongs within the Domain Model.
However, Domain Services often use functionality that really does not belong in the Domain.
In the case of hashing a password, our business logic dictates that this is important, but how the password is actually hashed is not the concern of the Domain.
Therefore we should not have the actual implementation of hashing a password inside of the Domain.
So should this service be in the Domain or not?
To model this functionality correctly we need to define a
HashingService interface within the Domain Model and an implementation that sits within the Infrastructure layer of our application.
This provides the clean separation of the domain requirement from the specific implementation, and it allows us to easily switch the hashing algorithm we use by simply using a different implementation.
The first thing we need to do is to write the
HashingService interface that is going to sit within our Domain Model:
<?php namespace Cribbb\Domain\Services\Identity;
* Create a new hashed password
* @param Password $password
* @return HashedPassword
public function hash(Password $password);
Note: I’ve renamed the
Users namespace to the more descriptive
I’ve placed this class in a new
Services namespace that sits under the
Domain namespace. This is simply for code organisation.
So as you can see the
HashingService has a single
hash() method that accepts an instance of the
Password Value Object.
You will also notice that the return value should be an instance of
HashedPassword. This is another Value Object that will allow me to type hint to ensure that we only accept hashed passwords. I won’t cover the implementation of the
HashedPassword class because it is basically exactly the same code that we already covered in Encapsulating your application’s business rules.
Next we can write the concrete class that will implement the
Create a new file under
BcryptHashingService.php and copy the following code:
<?php namespace Cribbb\Infrastructure\Services;
class BcryptHashingService implements HashingService
* @var Illuminate\Hashing\BcryptHasher
* Create a new BcryptHashingService
* @param BcryptHasher $hasher
* @return void
public function __construct(BcryptHasher $hasher)
$this->hasher = $hasher;
* Create a new HashedPassword
* @param Password $password
* @return HashedPassword
public function hash(Password $password)
return new HashedPassword($this->hasher->make((string) $password));
As you can see I’m injecting an instance of
Illuminate\Hashing\BcryptHasher as the hashing library. I’m also implementing the
hash() method to accept an instance of
Password and return an instance of
You could very easily replace this class with a different implementation that used a different hashing algorithm.
The test for this service is very simple because we only need to ensure that an instance of
HashedPassword is returned:
<?php namespace Cribbb\Infrastructure\Services;
class BcryptHashingServiceTest extends \PHPUnit_Framework_TestCase
/** @test */
public function should_make_new_hashed_password_instance()
$service = new BcryptHashingService(new BcryptHasher());
$hashed = $service->hash(new Password("my_super_secret_password"));
Domain Services are a very important component of Domain Driven Design as they allow you to co-ordinate Domain Objects and protect Entities and Value Objects from assuming too much responsibility.
However it is extremely important that you refrain from over-using Domain Services. A Domain Service seems like a neat solution to a problem, but you can very quickly find yourself in a situation where you have robbed the domain logic from the very objects that need it most.
Services as a whole are also very important to Domain Driven Design. As I touched upon in this article, we have services for each layer of our application. In the coming weeks we will be taking a deeper look into writing more of these services to build out the functionality of Cribbb.