Building Microservices in Go: Repository Pattern
Tags: go, microservices
Published: 2021-05-16 00:42:15

Continuing with the theme of using [Domain Driven Design](https://mariocarrion.com/2021/03/21/golang-microservices-domain-driven-design-project-layout.html) for building Microservices in Go, today let's talk about the **Repository Pattern**.

> **Disclaimer:** This post includes Amazon affiliate links. If you click on one of them and you make a purchase I'll earn a commission. Please notice your final price **is not** affected at all by using those links.

---

## What is the Repository Pattern?

According to [Martin Fowler](https://martinfowler.com/eaaCatalog/repository.html) in [Patterns of Enterprise Application Architecture (1st Edition)](https://amzn.to/3sa1TLN) a _Repository_:

> _Mediates between the domain and data mapping layers using a collection-like interface for accessing domain objects._

He continues (emphasis mine):

> _Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of **achieving a clean separation and one-way dependency between the domain and data mapping layers.**_ 

In [Domain Driven Design](https://amzn.to/3s8OAf3) the Repository Pattern relates another DDD term called **Aggregate**, [Martin Fowler](https://martinfowler.com/bliki/DDD_Aggregate.html) defines it as:

> _... a cluster of domain objects that can be treated as a single unit._

He continues (emphasis mine):

> _Aggregates are the basic element of transfer of data storage - you request to load or save whole aggregates. Transactions **should not cross aggregate boundaries.**_

_Repositories_ **go hand in hand with** _Aggregates_ and are usually enforced one to one, as stated by [Microsoft](https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design#define-one-repository-per-aggregate) (**emphasis mine**):

> _It's important to emphasize again that you should only define one repository for each aggregate root. To achieve the goal of the aggregate root to maintain transactional consistency between all the objects within the aggregate, **you should never create a repository for each table in the database**._ 

All of this is important to call out because the code we are going to be implement follows those ideas.

---

## Repository implementation for our "To Do" Domain

> The code used for this post is [available on Github](https://github.com/MarioCarrion/todo-api-microservice-example/tree/ccc21e67047827c12ecd31798a60d968cac26f48).

Our "To Do Microservice" implements a _To Do Domain_ and requires persisting data. We will define a type in charge of interacting directly with the persistence layer that also happens to represent a domain entity, this type will implement methods representing **concrete business interactions**.

The methods to implement depend on the entity we are working on and the aggregate we are trying to represent. In this case we will focus on `Task`, the repository will define 3 methods:

```go
// TaskRepository defines the datastore handling persisting Task records.
type TaskRepository interface {
	Create(ctx context.Context, description string, priority internal.Priority, dates internal.Dates) (internal.Task, error)
	Find(ctx context.Context, id string) (internal.Task, error)
	Update(ctx context.Context, id string, description string, priority internal.Priority, dates internal.Dates, isDone bool) error
}
```

Above, I mentioned _concrete business interactions_ but what the `TaskRepository` defines is literally `CRU` actions, **this is expected** for our _To Do Domain_ however the important thing to always remember is to think in terms of our Business Domain and how it is meant to handle those actions, if the _CRUD_ style works for what we are trying to implement that should be fine but, like we mentioned before, **we need to make sure** we don't start adding CRUD-like repositories that don't represent the domain we are implementing.

Our type implementing the `TaskRepository interface` type is going to be defined as [`postgresql.Task`](https://github.com/MarioCarrion/todo-api-microservice-example/blob/54a5a405e687cd893a5e7c78ae5006c055b941e9/internal/postgresql/task.go).  The named used for representing the package containing this this type is following the guideline we [described before](https://mariocarrion.com/2021/03/21/golang-microservices-domain-driven-design-project-layout.html) where we the technology name is used, in this case: `postgresql`.

Behind the scenes `postgresql.Task` uses the code generated by [`sqlc`](https://mariocarrion.com/2021/02/23/tips-building-microservices-in-go-golang-databases-postgresql-sqlc-squirrel.html) to actually interact with the PostgreSQL database to correctly `CREATE`, `SELECT` and `UPDATE`.

## Parting words

The Repository Pattern is a powerful way separate the Business Domain Layer and the Persistence Layer, it allows us to indicate exactly how our data moves from and to our datastore while hiding the possibly complexity that this layer could bring.

It's important to keep in mind that **not all** entities will require a repository but rather only those that represent a collection of domain entities that happen to need to work as a single unit.

I will expand more about this in future posts, until then, **keep it up**. I will talk to you next time.