Using Domain-Driven Design(DDD)in Golang
Tags: go, ddd, redis, postgres
Published: 2020-02-22 17:49:07

---
title: Using Domain-Driven Design(DDD)in Golang
published: true
description: This is a DDD sample code
tags: #go #ddd #redis #postgres 
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/0vrpsp8ggdtlm1enmsb4.jpg
---

Domain-Driven Design pattern is the talk of the town today. 
Domain-Driven Design(DDD) is an approach to software development that simplifies the complexity developers face by connecting the implementation to an evolving model.

###**Note**
**This is not an article that explains the "ideal" way to implement DDD in Golang because the author is no way an expert on it. This article is rather the author's understanding of DDD based on his research. The author 
will be very grateful to contributions on how to improve this article.**
Check the github repo for the updated code:
https://github.com/victorsteven/food-app-server


Why DDD?
The following are the reasons to consider using DDD:
* Provide principles & patterns to solve difficult problems
* Base complex designs on a model of the domain
* Initiate a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses domain problems.


The idea of Domain-Driven Design was inverted by [Eric Evans](https://twitter.com/ericevans0). He wrote about it in a book which you can find some of the highlights [here](https://www.goodreads.com/work/quotes/173058-domain-driven-design-tackling-complexity-in-the-heart-of-software)

DDD comprises of 4 Layers:
1. Domain: This is where the domain and business logic of the application is defined.
2. Infrastructure:  This layer consists of everything that exists independently of our application: external libraries, database engines, and so on.
3. Application: This layer serves as a passage between the domain and the interface layer. The sends the requests from the interface layer to the domain layer, which processes it and returns a response.
4. Interface: This layer holds everything that interacts with other systems, such as web services, RMI interfaces or web applications, and batch processing frontends.


![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/zxy4sge2vsk0pv53ik9v.jpg)
To have a thorough definition of terms of each layer, please refer to [this](http://dddsample.sourceforge.net/architecture.html)

###**Let's get started.**

We are going to build a food recommendation API.

You can get the code if you don't have all the time to read.
Get the API code [here](https://github.com/victorsteven/food-app-server).
Get the Frontend code [here](https://github.com/victorsteven/food-app-client).

The very first thing to do is to initialize the dependency management. We will be using **go.mod**. From the root directory(path: food-app/), initialize **go.mod**:
```go mod init food-app```

This is how the project is going to be organized:

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/603kx3hs78n8s7aopood.png)


In this application, we will use **postgres** and **redis** databases to persist data. We will define a .env file that has connection information.
The **.env** file looks like this:
{%gist https://gist.github.com/victorsteven/156ce071c10ea91639c84ee827865f6b %}
This file should be located in the root directory(path: food-app/)


###**Domain Layer**
We will consider the domain first. 
The domain has several patterns. Some of which are:
Entity, Value, Repository, Service, and so on.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/l8ux2zry0gpcf3moy16o.png)


Since the application we are building here is a simple one, we consider just two **domain** patterns: **entity** and **repository**. 

####**Entity**
This is where we define the "Schema" of things.
For example, we can define a user's struct. See the **entity** as the blueprint to the domain.

{%gist https://gist.github.com/victorsteven/fc67e9e5d1ae7b9b98dda4373b0f55b5 %}

From the above file, the user's struct is defined that contains the user information, we also added helper functions that will validate and sanitize inputs. A Hash method is called that helps hash password. That is defined in the  **infrastructure** layer. 
[Gorm](http://gorm.io) is used as the ORM of choice.

The same approach is taken when defining the food entity. You can look up the [repo](https://github.com/victorsteven/food-app-server).

####**Repository**
The repository defines a collection of methods that the infrastructure implements. This gives a vivid picture of the number of methods that interact with a given database or a third-party API.

The user's repository will look like this:
{%gist https://gist.github.com/victorsteven/148db4c216eea67fa200eb35aadef09e %}

The methods are defined in an interface. These methods will later be implemented in the infrastructure layer.

Almost the same applies to the food repository [here](https://github.com/victorsteven/food-app-server).


###**Infrastructure Layer**
This layer implements the methods defined in the repository. The methods interact with the database or a third-party API. This article will only consider database interaction.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/as8nb3zr2oq46tjsrgjq.png)


We can see how the user's repository implementation looks like:

{%gist https://gist.github.com/victorsteven/3648ca477ee13ba05a5d81b843512ae7 %}

Well, you can see that we implemented the methods that were defined in the **repository**. This was made possible using the **UserRepo** struct which implements the **UserRepository** interface, as seen in this line:
```
//UserRepo implements the repository.UserRepository interface
var _ repository.UserRepository = &UserRepo{}
```

You can check the repository on how the food repository was implemented [here](https://github.com/victorsteven/food-app-server).

So, let's configure our database by creating the **db.go** file with the content:

{%gist https://gist.github.com/victorsteven/ca4df1180d36f52759f98c16754aecf1 %} 
From the above file, we defined the **Repositories** struct which holds all the repositories in the application. We have the user and the food repositories. The Repositories also have a db instance, which is passed to the "constructors" of user and food(that is, NewUserRepository and NewFoodRepository). 


###**Application Layer**
We have successfully defined the API business logic in our **domain**. The **application** connects the **domain** and the **interfaces** layers.

We will only consider the user's application. You can check out that of the food in the [repo](https://github.com/victorsteven/food-app-server).

This is the user's application:
{%gist https://gist.github.com/victorsteven/9443bae123072b47cc2723a61a946adc %}

The above have methods to save and retrieve user data. The UserApp struct has the **UserRepository** interface, which made it possible to call the **user repository** methods.



###**Interfaces Layer**
The **interfaces** is the layer that handles HTTP requests and responses. This is where we get incoming requests for authentication, user-related stuff, and food-related stuff.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/o6uj342ppcc7wu232xge.png)

####**User Handler**

We define methods for saving a user, getting all users and getting a particular user. These are found in the **user_handler.go** file.
{%gist https://gist.github.com/victorsteven/33a9b3b67f140d2023ad9d0d98b66419 %}

I want you to observe that when returning the user, we only return a **public user**(which is defined in the entity). The public user does not have sensitive user details such as email and password.


####**Authentication Handler**
The **login_handler** takes care of **login**, **logout** and **refresh** token methods. Some methods defined in their respective files are called in this file. Do well to check them out in the repository following their file path.

{%gist https://gist.github.com/victorsteven/85728317207c4ef40941978a447f6e53 %}


####**Food Handler**
In the **food_handler.go** file, we have methods for basic **food** crud: creating, reading, updating, and deleting food. The file has explanations of how the code works.

{%gist https://gist.github.com/victorsteven/55c0b66eebfc17e1dffaf5093dd89d87 %}

Please note, when testing creating or updating food methods via the API using **postman**, use **form-data** not **JSON**. This is because the request type is multipart/form-data.

###**Running the Application**

So, let's test what we've got. We will wire up the routes, connect to the database and start the application.

These will be done in the **main.go** file defined in the directory root.

{%gist https://gist.github.com/victorsteven/79882dc0581c9ff887d649b318099930 %}

The **router(r)** is of type **Engine** from the [gin](https://github.com/gin-gonic) package we are using.


####**Middleware** 
As seen from the above file, Some routes have restrictions. The **AuthMiddleware** restricts access to an unauthenticated user. The **CORSMiddleware** enables data transfer from different domains. This is useful because VueJS is used for the frontend of this application and it points to a different domain.
The **MaxSizeAllowed** middleware stops any file with size above the one the middleware specifies. Since the **food** implementation requires file upload, the middleware stops files greater than the specified to be read into memory. This helps to prevent hackers from uploading an unreasonable huge file and slowing down the application. The **middleware package** is defined in the **interfaces** layer. 

{%gist https://gist.github.com/victorsteven/d29d578c21bd88a161dd52bac9a3af0b %}

We can now run the application using:
```
go run main.go
```


###**Bonus**
* Vue and VueX are used to consume the API. Get the repository [here](https://github.com/victorsteven/food-app-client), You can also visit the [url](https://food-app-ddd.netlify.com) and play with it.
* Test cases are written for most of the functionality. If you have time, you can add to it. To achieve **unit testing** for each of the methods in our handler, we created a mock package(in the **utils** directory) that mocks all the dependencies that are used in the handler methods.
* Circle CI is used for Continuous Integration.
* Heroku is used to deploy the API
* Netlify is used to deploy the Frontend.


##**Conclusion**
I hope you didn't have a hard time following this guideline on how to use DDD in when building a golang application. If you have questions or any observations, please don't hesitate to use the comment section. As said early, the author is not an expert on this. He simply wrote this article based on his use case.
Get the API code [here](https://github.com/victorsteven/food-app-server).
Get the Frontend code [here](https://github.com/victorsteven/food-app-client).
You can also visit the application [url](https://food-app-ddd.netlify.com) and play with it.

Check out other articles on medium [here](https://medium.com/@victorsteven).

You can as well follow on [twitter](https://twitter.com/stevensunflash)

Happy DDDing.