Domain-Driven Design in Go

Windi Chandra
LEARNFAZZ
Published in
4 min readMar 31, 2019

“The heart of software is its ability to solve domain-related problems for its user.”
- Eric Evans, Domain-Driven Design: Tackling Complexity in the Heart of Software

Domain-Driven Design (DDD) — I first heard the term before we started to code in LEARNFAZZ. Given not too much time, instead of learning from the book by Eric Evans, I went with Domain-Driven Design Quickly instead.

For those unfamiliar with DDD, DDD is a term introduced by Eric Evans in his book. It is an approach to software development based on a universal language between software developers and domain experts. It is also what we implemented in LEARNFAZZ.

Learning DDD in a short time, I wouldn’t claim to be an expert so my explanation or the implementation in our project might not be 100% DDD. But let’s see how we implemented it.

http://dddsample.sourceforge.net/architecture.html

DDD has 4 layers in the architecture:

  1. Interface: This layer responsibles for the interaction with user, whether software presents information or recieves information from user.
  2. Application: This is a thin layer between interface and domain, it could call domain services to serve the application purposes.
  3. Domain: The heart of the software, this layer holds domain logic and business knowledge.
  4. Infrastructure: A supporting layer for the other layers. This layer contains supporting libraries or external services like database or UI supporting library.

Quite straightforward, the four layers are created directly as modules in our project. e.g:

root/
| application/
| domain/
| infrastructure/
| interface/

Let’s go through each layer with examples, we’ll start from domain layer.

In the domain layer we know several more terms. To limit the scope in this post, we’ll only discuss some of them:

  1. Entity: an object that has an identity, identity could be a row in a database table or other type of identity that differs one entity and the other.
  2. Value object: an object which we are only interested in its attributes not the identity. Value objects do not have identities and creation/modification of these objects should not be a problem. Thus it is better to be implemented as immutable objects.
  3. Repository: Entities are usually stored in database, but we would not want to expose our domain logic to database logic so we could have a ‘virtual’ storage for our entities — Repositories.
  4. Service: Business logic sometimes would involve more than one different objects. When it doesn’t feel right to put a function in either object, we would use a service.

Moving to the code examples, the code shown here is also inspired by takashabe’s sample code.

Let’s say we want to create a “find a match” application for ducks, we’ll call it Tinduck. First we would want to create the duck object, this should be an entity. We would also want location for our matching service, we only need the coordinates so location should be a value object.

We could then proceed to create our repository and add several useful functions.

This repository interface is pure domain logic, the implementation could be in the infrastructure layer since it handles database logic. Notice the (flawed) singleton pattern used here, we intend not to create cyclic dependency between domain and infrastructure layer, part of the reason is also because we need to mock it for doing test on the upper layer.

Then we could add our implementation of the repository in infrastructure layer. For this example we would just use map as our database. There we finished our repository implementation, let’s then create a service for finding a match for a duck.

Singleton pattern used here is for testing reason, all other singleton patterns found later are also for the same reason.

Now that we have finished our domain logic and the infrastructure to support it, we could move to the next layer — application.

Basically what our application layer does is using domain repositories or services to serve application purposes. This layer is also important since we wouldn’t want interface layer to be filled with too much application flow that doesn’t affect our interaction with user. We then build the interface layer.

We use gin for the web framework

Finally we have finished our sample project, in the end your code structure should look like this:

application/
| tinduck.go
domain/
| entity/
| | duck.go
| repository/
| | duck_repository.go
| service/
| | matching_service.go
| value/
| | location.go
infrastructure/
| persistence/
| | duck_repository.go
interface/
| web/
| | tinduck.go
| | handler.go

We have come so far, you might notice that we do not have our main function yet, the one where we initialize database connection, web router, or our singletons. Since main might communicate with each layer and also control infrastructures, we could put it in the infrastructure layer.

That’s it folks! I hope this post could help those wanted to start a DDD project in Go, further reading could be found in the references or you could check out the book by Eric Evans.

References:

  1. Avram, A., Marinescu, F. (2006). Domain-Driven Design Quickly. InfoQ.com: C4Media. ISBN: 978–1–4116–9591–7
  2. https://github.com/takashabe/go-ddd-sample
  3. http://dddsample.sourceforge.net/architecture.html

--

--