Clean Architecture in Practice
Tags: go, codenewbie
Published: 2020-12-03 07:46:37

Organizing your project can be as important as the business logic of your app, especially in the long run. Ease of maintenance and integrating new functionality are core parts of the software development lifecycle. So it makes sense to organize your project in such a way that it welcomes change instead of opposing it.
> Full example code can be found [here](https://github.com/thetinygoat/go-clean-arch).

## Clean Architecture (CA)
> This is my take on clean architecture, you don’t have to agree with me :)

Clean architecture lays out a set of rules to allow your apps to be easily extensible. Following these rules, you can build systems that are:

 - Independent of frameworks. You can easily swap one framework for another without rewriting your whole app.
 - Testable.
 - Independent of the database. You can swap PostgreSQL for MySQL or a NoSQL database.

## Layers in CA
CA is a layered architecture, the diagram below tries to show various layers. 

![CA Layers](https://dev-to-uploads.s3.amazonaws.com/i/seo8n252x4ygqh4wj2yt.png)

>There can be more than 4 layers depending upon your project and the complexity.

### Models
Think of a model as an object or data-structure that contains a blueprint of an entity in your business logic.

```go
package user

type User struct {
    Name    string
    ID      int64
    Email   string
}
```
In the code example above, the `User` struct contains the blueprint for the user. The same structure applies to all the entities in your business logic.

### Repository
The repository is responsible for talking with the persistence layer. We are abstracting it with an interface.

```go
package user

// ...snip

type UserRepository interface {
    GetByID(id int64) (*User, error)
    Update(u *User) error
    Delete(id int64) error
}
```
Whatever persistence layer you are using in your system be it [PostgreSQL](https://www.postgresql.org/) or [MongoDB](https://www.mongodb.com/), must satisfy this interface. This way we have decoupled the database from our system.
### Usecase
This layer implements business-specific logic and communicates with the repository. We are abstracting away the usecase layer with the help of an interface.

```go
package user

// ...snip

type UserUsecase interface {
    GetByID(id int64) (*User, error)
    Update(u *User) error
    Delete(id int64) error
}
```
> The Usecase and the repository happen to be same, it's not a rule.

### Delivery
The delivery layer is responsible for the exchange of data between your system and the clients. The communication can take place with the help of a REST API or RPC or any other protocol or many protocols at the same time. the delivery layer is also responsible for serialization/de-serialization of data.

> The data should be passed between the layers using only data-structures or as function parameters.

## Dataflow

![CA Dataflow](https://dev-to-uploads.s3.amazonaws.com/i/sme1db90g1u9ptnj55ey.png)

Understanding how the data flows in CA can be a bit confusing at first but it's quite simple in practice.

The client makes a request using a delivery protocol supported by your system. The delivery layer de-serializes the data from the request and passes it to the usecase layer. The usecase layer processes the data and talks to the repository if necessary. The processed data is sent up the chain to the delivery layer where it's serialized and sent back to the client.

## Useful Links
 - [The Clean Architecture by uncle bob](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html)