Professional Documents
Culture Documents
Clean architecture
Created @June 28, 2022 10:46 AM
Created By ế
khi t cao
Tags
Table of contents
Table of contents
References
Overview
The dependency rule
General layers (top→ down)
Layers
Models
Repository
Usecase / interactor
Presenter
Delivery
Flow layer
Common question
Communication between layer
In Ahamove project
Conclusion
Implementation of Clean Go
Controllers and presenters
Implementation in official Go-clean-architect
References
Clean architecture 1
Try clean architect and how to test for each layers: https://hackernoon.com/golang-
clean-archithecture-efd6d7c43047
https://github.com/bxcodec/go-clean-arch
Specific implement Go Clean: https://manakuro.medium.com/clean-architecture-with-
go-bce409427d31
http://www.plainionist.net/Implementing-Clean-Architecture-Controller-Presenter/
Quite details, should read, summary some key points: https://github.com/evrone/go-
clean-template
How to organize package-layout: https://medium.com/@benbjohnson/standard-
package-layout-7cdbc8391fc1
Go-clean-mircoservices series: https://medium.com/@jfeng45/go-microservice-with-
clean-architecture-a08fa916a5db
Sample code and test, layers: delivery, usecase and datastore:
https://medium.com/swlh/developing-a-web-application-in-go-using-the-layered-
architecture-8fc13209c808
Organize layers: https://threedots.tech/post/introducing-clean-architecture/
Hexagonal-onion-clean architecture detail
https://herbertograca.com/2017/11/16/explicit-architecture-01-ddd-hexagonal-onion-
clean-cqrs-how-i-put-it-all-together/
Clean architecture 2
Overview
Domain objects and rules doesn’t change often. On the other hand, frameworks,
middlewares, DB change more frequently. So for a long time, we need to separate the
domain logic from technology. Your domain class should never be dependent on the
classes you use technology and libraries for.
Clean architecture 3
Domain services (Use Cases): Business logic consists of codes such as creating,
updating, processing, sharing between services
Uncle Bob’s architecture has 4 layers (no need to have 4 layers, depend on your
project)
Entities
Usecase
It’s a entry point for business logic. Each business feature is implemented by a
usecase. So no other layers depend on it, but it depends on others layers.
Usecases contain application business rules using a domain model and have
input port and output port
Clean architecture 4
Output port: handling data from use cases to the outer layer
Is a set of adapters that convert data from format most convenient for use
cases and entities, to the format most convenient for some external agency
such as DB or the Web (whatever framework is being used). In this layer, will
wholly contain the MVC architecture. The presenters, Views and Controllers all
belong in here. The models are likely data structure that are passed from the
controllers to the use cases, and then back from the use cases to the
presenters and views
Also in this layer is any other adapter necessary to convert data from some
external form, such as an external service, to the internal form used by the use
cases and entities.
Models
Repository
The use case is only layer communicate with datastore. This way each layer
can be tested independently
If the app grows to have gRPC support, only the delivery layer will change.
Datastore and usecase remain the same. This way, it’s easy to isolate any
bugs, maintain code and grow the application
Usecase
Delivery
Clean architecture 5
The delivery layer will received the request and parse anything that is required
from the request. It calls the use case layers, ensures that response is the
required format and writes it to the response writer
Layers
Models
Same as Entities, will used in all layers. Store any struct type and its method. For
instance
Clean architecture 6
type Article struct {
ID int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
}
Repository
Repository store any Database handler, including query, create/insert into database, act
as a CRUD to DB, only plain function to Database
This layer have responsibility for choose what DB will used in app. If using ORM, this
layer will control the input, and give it directly to ORM services
If calling micro-service, will handled here. Create HTTP request to other services, and
sanitize data. This layer must fully act as a repository
Usecase / interactor
Act as a business process handler (which contains business logic). Any process will
handle here. It decide which repository layer will use. And provide data to serve into
delivery.
Usecase layer will accept any input from delivery layer, that already sanitized, then
process the input could be storing into DB, or Fetching from DB
Clean architecture 7
Presenter
It doesn’t contain business logic, main job is map the data structure returned by use
case interactor into structure most convenient for view
Delivery
This layer act as a presenter, decide how data will be presented. Could be as a REST
API, or HTML File, or gRPC. This layer also accept input from user. Sanitize the input
and sent it to Usecase layer
For instance, using REST API as the delivery method. Client will call the resource
endpoint over network, and the Delivery layer will get the input or request, and sent it to
Usecase Layer.
This layer will depends to Usecase Layer.
Flow layer
main.go
↓
router.go・・・Infrastructure
↓
user_controller.go・・・Interfaces
↓
user_interactor.go・・・Use Cases
↓
Clean architecture 8
user_repository.go ・・・Use Cases
↓
user.go ・・・Domain
Common question
A: Because we want to avoid God objects that deals with both presentation logic
and dataflow logic. We also want the dataflow logic to be reusable across
different ViewModels.
Q: Why should I have a Use Case that does nothing other than just
calling a Repository, isn’t this an overkill for my app?
A: Not always, but for sure you need at least a repository method for each Use
Case.
Clean architecture 9
package repository
Usecase layer will communicate to Repository using this contract, and Repository
layer MUST implement this interface so can used by Usecase
Example of Usecase’s Interface
package usecase
import (
"github.com/bxcodec/go-clean-arch/article"
)
Same with Usecase, Deliver layer will use this contract interface. And Usecase layer
must implement this interface.
In Ahamove project
we will inject repository and service interface into usecase. And inject usecase into
handlers.
Conclusion
Clean architecture 10
No matter of your library, architecture is clean and testable also independent
Implementation of Clean Go
.
├── domain
│ └── model
│ └── user.go
├── infrastructure
│ ├── datastore
│ │ └── db.go
│ └── router
│ └── router.go
├── interface
│ ├── controller
│ │ ├── app_controller.go
│ │ ├── context.go
│ │ └── user_controller.go
│ ├── presenter
│ │ └── user_presenter.go
│ └── repository
│ └── user_repository.go
├── main.go
├── registry
│ ├── registry.go
Clean architecture 11
│ └── user_registry.go
├── usecase
│ ├── presenter
│ │ └── user_presenter.go
│ ├── repository
│ │ └── user_repository.go
│ └── interactor
│ └── user_interactor.go
Directory Layer
domain Entities
Clean architecture 12
Flow of user interact with a system
3. The controller converts the request into a request model and passes it to the use
case interactor through its input port.
4. The use case interactor processes the request model and creates a response
model which is passed through the output port to the presenter.
5. The presenter converts the response model to view model which is then passed to
the view.
The left (blue) section where the frameworks live (e.g. an HTML/JavaScript view)
The middle (green) section where the adapters live (controllers and presenters)
Clean architecture 13
The right (red) section where the business logic (use case interactors) live
models
├── article.go
├── author.go
└── errors.go
article
├── delivery
│ └── http
│ ├── article_handler.go
│ └── article_test.go
├── mocks
│ ├── ArticleRepository.go
│ └── ArticleUsecase.go
├── repository //Encapsulated Implementation of Repository Interface
│ ├── mysql_article.go
│ └── mysqlarticle_test.go
├── repository.go // Repository Interface
├── usecase //Encapsulated Implementation of Usecase Interface
│ ├── articleucase_test.go
│ └── artilce_ucase.go
└── usecase.go // Usecase Interface.
Domain-Driven Design
Clean architecture 14