Building Microservices in Go: Services in Domain Driven Design
Tags: go, microservices, ddd
Published: 2021-05-22 00:27:49

There are cases when according to our business domain, and the rules governing it, some concepts can not be modeled as part of existing entities; in those cases there's the need to introduce _Services_.

Although a really overloaded term, _a Service_, in the context of [Domain Driven Design](https://mariocarrion.com/2021/03/21/golang-microservices-domain-driven-design-project-layout.html), defines assertions in the ubiquitous language of a specific bounded context.

In [Domain Driven Design](https://amzn.to/3s8OAf3) **Ubiquitous Language** is defined by Eric Evans as (emphasis mine):

> _A language structured around the domain model and **used by all team members within a bounded context** to connect all the activities of the team with the software._

And **Bounded Context** as: 

> _A description of a boundary (typically a subsystem, or the work of a particular team) within which a particular model is defined and applicable._

> **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.

---

## How does a service look like in practice?

If we look at [our code](https://github.com/MarioCarrion/todo-api-microservice-example/tree/54a5a405e687cd893a5e7c78ae5006c055b941e9) for our "To Do Microservice", we implemented a [`service.Task`](https://github.com/MarioCarrion/todo-api-microservice-example/blob/54a5a405e687cd893a5e7c78ae5006c055b941e9/internal/service/task.go) that looks like:

```go
// Task defines the application service in charge of interacting with Tasks.
type Task struct {
	repo TaskRepository
}

// Create stores a new record.
func (t *Task) Create(ctx context.Context, description string, priority internal.Priority, dates internal.Dates) (internal.Task, error) { /* ... */ }

// Task gets an existing Task from the datastore.
func (t *Task) Task(ctx context.Context, id string) (internal.Task, error) { /* ... */ }

// Update updates an existing Task in the datastore.
func (t *Task) Update(ctx context.Context, id string, description string, priority internal.Priority, dates internal.Dates, isDone bool) error { /* ... */ }
```

This service references a [Repository](https://mariocarrion.com/2021/04/04/golang-microservices-repository-pattern.html) called `TaskRepository` which eventually gets assigned via _Dependency Injection_ [in main](https://github.com/MarioCarrion/todo-api-microservice-example/blob/54a5a405e687cd893a5e7c78ae5006c055b941e9/cmd/repository-example/main.go#L27-L28).

Services in this form usually represent _Aggregates_ that in the end are meant to represent a cluster of domain objects to be treated as a single unit. In future iterations of this code we will see how that comes in to place when _Task_ also include other things like `SubTasks` and `Categories`.

## Parting words

Implementing _services_ is useful to indicate interactions between domain objects and some external dependencies, like persistence layers. One of the difficult parts about implementing services is to know when those should be implemented, to determine that we should think about those cases where our business has specific processes that should be modeled a single unit.

Although in our "To Do Project" we are using `Task` as the service name what this means is not the database table or model _task_ but rather the process of interacting with Tasks and other entities, and all of that being handled as a single thing.

When defining services think in those terms, ask the question "What's the business process we are trying to model and what entities should be involved?" Answering that question should give you the name of the process we can model as a service.

**Keep it up**. I will talk to you next time.