diff --git a/README.md b/README.md index 56a55fc7..082b977b 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@  # Go Clean template -[π¨π³δΈζ](README_CN.md) + +[π¨π³ δΈζ](README_CN.md) +[π·πΊ RU](README_RU.md) Clean Architecture template for Golang services @@ -11,7 +13,9 @@ Clean Architecture template for Golang services [](https://codecov.io/gh/evrone/go-clean-template) ## Overview + The purpose of the template is to show: + - how to organize a project and prevent it from turning into spaghetti code - where to store business logic so that it remains independent, clean, and extensible - how not to lose control when a microservice grows @@ -21,13 +25,16 @@ Using the principles of Robert Martin (aka Uncle Bob). [Go-clean-template](https://evrone.com/go-clean-template?utm_source=github&utm_campaign=go-clean-template) is created & supported by [Evrone](https://evrone.com/?utm_source=github&utm_campaign=go-clean-template). ## Content + - [Quick start](#quick-start) - [Project structure](#project-structure) - [Dependency Injection](#dependency-injection) - [Clean Architecture](#clean-architecture) ## Quick start + Local development: + ```sh # Postgres, RabbitMQ $ make compose-up @@ -36,17 +43,21 @@ $ make run ``` Integration tests (can be run in CI): + ```sh # DB, app + migrations, integration tests $ make compose-up-integration-test ``` ## Project structure + ### `cmd/app/main.go` + Configuration and logger initialization. Then the main function "continues" in `internal/app/app.go`. ### `config` + Configuration. First, `config.yml` is read, then environment variables overwrite the yaml config if they match. The config structure is in the `config.go`. The `env-required: true` tag obliges you to specify a value (either in yaml, or in environment variables). @@ -59,15 +70,18 @@ reading the entire config from ENV. It is assumed that default values are in yaml, and security-sensitive variables are defined in ENV. ### `docs` + Swagger documentation. Auto-generated by [swag](https://github.com/swaggo/swag) library. You don't need to correct anything by yourself. ### `integration-test` + Integration tests. They are launched as a separate container, next to the application container. It is convenient to test the Rest API using [go-hit](https://github.com/Eun/go-hit). ### `internal/app` + There is always one _Run_ function in the `app.go` file, which "continues" the _main_ function. This is where all the main objects are created. @@ -89,19 +103,24 @@ $ go run -tags migrate ./cmd/app ``` ### `internal/controller` + Server handler layer (MVC controllers). The template shows 2 servers: + - RPC (RabbitMQ as transport) - REST http (Gin framework) Server routers are written in the same style: + - Handlers are grouped by area of application (by a common basis) - For each group, its own router structure is created, the methods of which process paths - The structure of the business logic is injected into the router structure, which will be called by the handlers #### `internal/controller/http` + Simple REST versioning. For v2, we will need to add the `http/v2` folder with the same content. And in the file `internal/app` add the line: + ```go handler := gin.New() v1.NewRouter(handler, t) @@ -113,11 +132,14 @@ Instead of Gin, you can use any other http framework or even the standard `net/h In `v1/router.go` and above the handler methods, there are comments for generating swagger documentation using [swag](https://github.com/swaggo/swag). ### `internal/entity` + Entities of business logic (models) can be used in any layer. There can also be methods, for example, for validation. ### `internal/usecase` + Business logic. + - Methods are grouped by area of application (on a common basis) - Each group has its own structure - One file - one structure @@ -126,20 +148,25 @@ Repositories, webapi, rpc, and other business logic structures are injected into (see [Dependency Injection](#dependency-injection)). #### `internal/usecase/repo` + A repository is an abstract storage (database) that business logic works with. #### `internal/usecase/webapi` + It is an abstract web API that business logic works with. For example, it could be another microservice that business logic accesses via the REST API. The package name changes depending on the purpose. ### `pkg/rabbitmq` + RabbitMQ RPC pattern: + - There is no routing inside RabbitMQ - Exchange fanout is used, to which 1 exclusive queue is bound, this is the most productive config - Reconnect on the loss of connection ## Dependency Injection + In order to remove the dependence of business logic on external packages, dependency injection is used. For example, through the New constructor, we inject the dependency into the structure of the business logic. @@ -178,23 +205,28 @@ It will also allow us to do auto-generation of mocks (for example with [mockery] > If the new component implements the interface, nothing needs to be changed in the business logic. ## Clean Architecture + ### Key idea + Programmers realize the optimal architecture for an application after most of the code has been written. > A good architecture allows decisions to be delayed to as late as possible. ### The main principle -Dependency Inversion (the same one from SOLID) is the principle of dependency inversion. + +Dependency Inversion (the same one from SOLID) is the principle of dependency injection. The direction of dependencies goes from the outer layer to the inner layer. Due to this, business logic and entities remain independent from other parts of the system. So, the application is divided into 2 layers, internal and external: + 1. **Business logic** (Go standard library). 2. **Tools** (databases, servers, message brokers, any other packages and frameworks).  **The inner layer** with business logic should be clean. It should: + - Not have package imports from the outer layer. - Use only the capabilities of the standard library. - Make calls to the outer layer through the interface (!). @@ -203,6 +235,7 @@ The business logic doesn't know anything about Postgres or a specific web API. Business logic has an interface for working with an _abstract_ database or _abstract_ web API. **The outer layer** has other limitations: + - All components of this layer are unaware of each other's existence. How to call another from one tool? Not directly, only through the inner layer of business logic. - All calls to the inner layer are made through the interface (!). - Data is transferred in a format that is convenient for business logic (`internal/entity`). @@ -217,12 +250,14 @@ The communication between them is carried out through `usecase` (business logic) usecase < repository (Postgres) HTTP < usecase ``` + The symbols > and < show the intersection of layer boundaries through Interfaces. The same is shown in the picture:  Or more complex business logic: + ``` HTTP > usecase usecase > repository @@ -237,13 +272,14 @@ Or more complex business logic: ``` ### Layers +  ### Clean Architecture Terminology + - **Entities** are structures that business logic operates on. They are located in the `internal/entity` folder. In MVC terms, entities are models. - - **Use Cases** is business logic located in `internal/usecase`. The layer with which business logic directly interacts is usually called the _infrastructure_ layer. @@ -251,6 +287,7 @@ These can be repositories `internal/usecase/repo`, external webapi `internal/use In the template, the _infrastructure_ packages are located inside `internal/usecase`. You can choose how to call the entry points as you wish. The options are: + - controller (in our case) - delivery - transport @@ -260,6 +297,7 @@ You can choose how to call the entry points as you wish. The options are: - input ### Additional layers + The classic version of [Clean Architecture](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) was designed for building large monolithic applications and has 4 layers. In the original version, the outer layer is divided into two more, which also have an inversion of dependencies @@ -267,21 +305,23 @@ to each other (directed inward) and communicate through interfaces. The inner layer is also divided into two (with separation of interfaces), in the case of complex logic. -_______________________________ +--- Complex tools can be divided into additional layers. However, you should add layers only if really necessary. ### Alternative approaches + In addition to Clean architecture, _Onion architecture_ and _Hexagonal_ (_Ports and adapters_) are similar to it. Both are based on the principle of Dependency Inversion. _Ports and adapters_ are very close to _Clean Architecture_, the differences are mainly in terminology. - ## Similar projects + - [https://github.com/bxcodec/go-clean-arch](https://github.com/bxcodec/go-clean-arch) - [https://github.com/zhashkevych/courses-backend](https://github.com/zhashkevych/courses-backend) ## Useful links + - [The Clean Architecture article](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) - [Twelve factors](https://12factor.net/ru/) diff --git a/README_RU.md b/README_RU.md new file mode 100644 index 00000000..139d4164 --- /dev/null +++ b/README_RU.md @@ -0,0 +1,325 @@ + + +# Go Π§ΠΈΡΡΠ°Ρ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° + +Π¨Π°Π±Π»ΠΎΠ½ Π§ΠΈΡΡΠΎΠΉ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠΎΠΉ Π΄Π»Ρ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ Π½Π° Golang + +[](https://goreportcard.com/report/github.com/evrone/go-clean-template) +[](https://github.com/evrone/go-clean-template/blob/master/LICENSE) +[](https://github.com/evrone/go-clean-template/releases/) +[](https://codecov.io/gh/evrone/go-clean-template) + +## ΠΠ±Π·ΠΎΡ + +Π¦Π΅Π»Ρ ΡΡΠΎΠ³ΠΎ ΡΠ°Π±Π»ΠΎΠ½Π° - ΠΏΠΎΠΊΠ°Π·Π°ΡΡ ΠΏΡΠΈΠ½ΡΠΈΠΏΡ Π§ΠΈΡΡΠΎΠΉ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ Π ΠΎΠ±Π΅ΡΡΠ° ΠΠ°ΡΡΠΈΠ½Π° (Π΄ΡΠ΄ΡΡΠΊΠΈ ΠΠΎΠ±Π°): + +- ΠΊΠ°ΠΊ ΡΡΡΡΠΊΡΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΏΡΠΎΠ΅ΠΊΡ ΠΈ Π½Π΅ Π΄Π°ΡΡ Π΅ΠΌΡ ΠΏΡΠ΅Π²ΡΠ°ΡΠΈΡΡΡΡ Π² ΡΠΏΠ°Π³Π΅ΡΡΠΈ-ΠΊΠΎΠ΄ +- Π³Π΄Π΅ Ρ ΡΠ°Π½ΠΈΡΡ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΡ, ΡΡΠΎ Π±Ρ ΠΎΠ½Π° ΠΎΡΡΠ°Π²Π°Π»Π°ΡΡ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎΠΉ, ΡΠΈΡΡΠΎΠΉ ΠΈ ΡΠ°ΡΡΠΈΡΡΠ΅ΠΌΠΎΠΉ +- ΠΊΠ°ΠΊ Π½Π΅ ΠΏΠΎΡΠ΅ΡΡΡΡ ΠΊΠΎΠ½ΡΡΠΎΠ»Ρ ΠΏΡΠΈ ΡΠΎΡΡΠ΅ ΠΏΡΠΎΠ΅ΠΊΡΠ° + +[Go-clean-template](https://evrone.com/go-clean-template?utm_source=github&utm_campaign=go-clean-template) ΡΠΎΠ·Π΄Π°Π½ ΠΈ ΠΏΠΎΠ΄Π΄Π΅ΡΠΆΠΈΠ²Π°Π΅ΡΡΡ [Evrone](https://evrone.com/?utm_source=github&utm_campaign=go-clean-template). + +## Π‘ΠΎΠ΄Π΅ΡΠΆΠ°Π½ΠΈΠ΅ + +- [ΠΡΡΡΡΡΠΉ ΡΡΠ°ΡΡ](#Π±ΡΡΡΡΡΠΉ-ΡΡΠ°ΡΡ) +- [Π‘ΡΡΡΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ°](#ΡΡΡΡΠΊΡΡΡΠ°-ΠΏΡΠΎΠ΅ΠΊΡΠ°) +- [ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ](#Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅-Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ) +- [Π§ΠΈΡΡΠ°Ρ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°](#ΡΠΈΡΡΠ°Ρ-Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ°) + +## ΠΡΡΡΡΡΠΉ ΡΡΠ°ΡΡ + +ΠΠΎΠΊΠ°Π»ΡΠ½Π°Ρ ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ°: + +```sh +# Postgres, RabbitMQ +$ make compose-up +# ΠΠ°ΠΏΡΡΠΊ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΉ +$ make run +``` + +ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΎΠ½Π½ΡΠ΅ ΡΠ΅ΡΡΡ (ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΎ Ρ CI): + +```sh +# DB, app + migrations, integration tests +$ make compose-up-integration-test +``` + +## Π‘ΡΡΡΠΊΡΡΡΠ° ΠΏΡΠΎΠ΅ΠΊΡΠ° + +### `cmd/app/main.go` + +ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΈ Π»ΠΎΠ³Π³Π΅ΡΠ°. ΠΠ΄Π΅ΡΡ Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ ΠΎΡΠ½ΠΎΠ²Π°Π½Π°Ρ ΡΠ°ΡΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΈΠ· `internal/app/app.go`. + +### `config` + +ΠΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ. Π‘Π½Π°ΡΠ°Π»Π° ΡΠΈΡΠ°Π΅ΡΡΡ `config.yml`, Π° Π·Π°ΡΠ΅ΠΌ ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ. +ΠΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ ΠΈΠΌΠ΅ΡΡ Π±ΠΎΠ»ΡΡΠΈΠΉ ΠΏΡΠΈΠΎΡΠΈΡΠ΅Ρ, ΡΠ΅ΠΌ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ ΠΈΠ· yaml ΡΠ°ΠΉΠ»Π° +ΠΈ ΠΏΡΠΈ ΡΠΎΠ²ΠΏΠ°Π΄Π΅Π½ΠΈΠΈ ΠΊΠ»ΡΡΠ°, Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ Π±Π΅ΡΠ΅ΡΡΡ ΠΈΠ· ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΠΎΠΊΡΡΠΆΠ΅Π½ΠΈΡ. +Π‘ΡΡΡΠΊΡΡΡΠ° ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΎΠ±ΡΡΠ²Π»Π΅Π½Π° Π² ΡΠ°ΠΉΠ»Π΅ `config.go`. +Π’Π΅Π³ `env-required: true` ΡΠΊΠ°Π·ΡΠ²Π°Π΅Ρ, ΡΡΠΎ Π·Π½Π°ΡΠ΅Π½ΠΈΠ΅ ΠΎΠ±ΡΠ·Π°ΡΠ΅Π»ΡΠ½ΠΎ. (Π»ΠΈΠ±ΠΎ Π² yaml, Π»ΠΈΠ±ΠΎ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ΡΡΠ΅Π΄Ρ). + +ΠΠ»Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΌΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΠΌ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ [cleanenv](https://github.com/ilyakaznacheev/cleanenv). +ΠΠ½Π° ΠΏΡΠΎΡΡΠ°Ρ ΠΈ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΡΠ΅Ρ Π²ΡΠ΅ΠΌ Π½Π°ΡΠΈΠΌ ΡΡΠ΅Π±ΠΎΠ²Π°Π½ΠΈΡ. + +Π§ΡΠ΅Π½ΠΈΠ΅ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΠΈ ΠΈΠ· yaml ΡΠ°ΠΉΠ»Π° ΠΏΡΠΎΡΠΈΠ²ΠΎΡΠ΅ΡΠΈΡ ΠΈΠ΄Π΅ΠΎΠ»ΠΎΠ³ΠΈΠΈ `Twelve-Factor App`, Π½ΠΎ Π½Π° ΠΏΡΠ°ΠΊΡΠΈΠΊΠ΅ ΡΡΠΎ Π±ΠΎΠ»Π΅Π΅ ΡΠ΄ΠΎΠ±Π½ΠΎ, +ΡΠ΅ΠΌ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΠ΅ Π·Π½Π°ΡΠ΅Π½ΠΈΠΉ ΠΈΠ· ENV. +ΠΡΠ΅Π΄ΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ, ΡΡΠΎ Π² yaml ΡΠΊΠ°Π·ΡΠ²Π°ΡΡΡΡ Π·Π½Π°ΡΠ΅Π½ΠΈΡ ΠΏΠΎ ΡΠΌΠΎΠ»ΡΠ°Π½ΠΈΡ, Π° ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΠ΅, ΡΡΠ²ΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΠΊ Π±Π΅Π·ΠΎΠΏΠ°ΡΠ½ΠΎΡΡΠΈ +Π·Π°Π΄Π°ΡΡΡΡ Π² ΠΏΠ΅ΡΠ΅ΠΌΠ΅Π½Π½ΡΡ ENV. + +### `docs` + +ΠΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Swagger. ΠΠ΅Π½Π΅ΡΠΈΡΡΠ΅ΡΡΡ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΈ Ρ ΠΏΠΎΠΌΠΎΡΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ [swag](https://github.com/swaggo/swag). +ΠΠ°ΠΌ Π½Π΅ Π½ΡΠΆΠ½ΠΎ Π½ΠΈΡΠ΅Π³ΠΎ ΡΠ΅Π΄Π°ΠΊΡΠΈΡΠΎΠ²Π°ΡΡ Π²ΡΡΡΠ½ΡΡ. + +### `integration-test` + +ΠΠ½ΡΠ΅Π³ΡΠ°ΡΠΈΠΎΠ½Π½ΡΠ΅ ΡΠ΅ΡΡΡ. +ΠΠ½ΠΈ Π·Π°ΠΏΡΡΠΊΠ°ΡΡΡΡ Π² ΠΎΡΠ΄Π΅Π»ΡΠ½ΠΎΠΌ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠ΅, ΡΡΠ΄ΠΎΠΌ Ρ ΠΊΠΎΠ½ΡΠ΅ΠΉΠ½Π΅ΡΠΎΠΌ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ. +Rest API ΡΠ΄ΠΎΠ±Π½ΠΎ ΡΠ΅ΡΡΠΈΡΠΎΠ²Π°ΡΡ Ρ ΠΏΠΎΠΌΠΎΡΡΡ [go-hit](https://github.com/Eun/go-hit). + +### `internal/app` + +ΠΠ΄Π΅ΡΡ Π½Π°Ρ ΠΎΠ΄ΠΈΡΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΎΠ΄Π½Π° _Run_ ΡΡΠ½ΠΊΡΠΈΡ. ΠΠ½Π° ΡΠ°Π·ΠΌΠ΅ΡΠ΅Π½Π° Π² ΡΠ°ΠΉΠ»Π΅ `app.go` ΠΈ ΡΠ²Π»ΡΠ΅ΡΡΡ Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠΈΠΌ ΠΏΡΠΎΠ΄ΠΎΠ»ΠΆΠ΅Π½ΠΈΠ΅ΠΌ ΡΡΠ½ΠΊΡΠΈΠΈ _main_. + +ΠΠ΄Π΅ΡΡ ΡΠΎΠ·Π΄Π°ΡΡΡΡ Π²ΡΠ΅ ΠΎΡΠ½ΠΎΠ²Π½ΡΠ΅ ΠΎΠ±ΡΠ΅ΠΊΡΡ. +[ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ](#Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅-Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ) ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΡΠ΅ΡΠ΅Π· ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ "New ...". +ΠΡΠ° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΡΠ»ΠΎΠΈΡΠΎΠ²Π°ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅, Π΄Π΅Π»Π°Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΡ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎΠΉ ΠΎΡ Π΄ΡΡΠ³ΠΈΡ ΡΠ»ΠΎΠ΅Π². + +ΠΠ°Π»Π΅Π΅, Π·Π°ΠΏΡΡΠΊΠ°Π΅ΡΡΡ ΡΠ΅ΡΠ²Π΅Ρ ΠΈ ΠΎΠΆΠΈΠ΄Π°Π΅ΡΡΡ ΡΠΈΠ³Π½Π°Π» Π² _select_ Π΄Π»Ρ ΠΊΠΎΡΡΠ΅ΠΊΡΠ½ΠΎΠ³ΠΎ Π·Π°Π²Π΅ΡΡΠ΅Π½ΠΈΡ ΡΠ°Π±ΠΎΡΡ. +ΠΡΠ»ΠΈ `app.go` ΡΡΠ°Π» ΡΠ»ΠΈΡΠΊΠΎΠΌ Π±ΠΎΠ»ΡΡΠΈΠΌ, Π²Ρ ΠΌΠΎΠΆΠ΅ΡΠ΅ ΡΠ°Π·Π΄Π΅Π»ΠΈΡΡ Π΅Π³ΠΎ Π½Π° Π½Π΅ΡΠΊΠΎΠ»ΡΠΊΠΎ ΡΠ°ΠΉΠ»ΠΎΠ². + +ΠΡΠ»ΠΈ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ ΠΌΠ½ΠΎΠ³ΠΎ, ΡΠΎ Π΄Π»Ρ ΡΠ΄ΠΎΠ±ΡΡΠ²Π° ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ [wire](https://github.com/google/wire). + +Π€Π°ΠΉΠ» `migrate.go` ΠΈΡΠΏΠΎΠ»ΡΡΠ·Π΅ΡΡΡ Π΄Π»Ρ Π°Π²ΡΠΎΠΌΠ°ΡΠΈΡΠ΅ΡΠΊΠΎΠΉ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ . +ΠΠ½ Π²ΠΊΠ»ΡΡΠ°Π΅ΡΡΡ Π² ΠΊΠΎΠΌΠΏΠΈΠ»ΡΡΠΈΡ ΡΠΎΠ»ΡΠΊΠΎ ΠΏΡΠΈ ΡΠΊΠ°Π·Π°Π½ΠΈΠΈ ΡΠ΅Π³Π° _migrate_. +ΠΡΠΈΠΌΠ΅Ρ: + +```sh +$ go run -tags migrate ./cmd/app +``` + +### `internal/controller` + +Π‘Π»ΠΎΠΉ Ρ ΡΠ½Π΄Π»Π΅ΡΠΎΠ² ΡΠ΅ΡΠ²Π΅ΡΠ° (MVC ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅ΡΡ). Π ΡΠ°Π±Π»ΠΎΠ½Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½Π° ΡΠ°Π±ΠΎΡΠ° 2Ρ ΡΠ΅ΡΠ²Π΅ΡΠΎΠ²: + +- RPC (RabbitMQ as transport) +- REST http (Gin framework) + +ΠΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΎΡΡ http ΡΠ΅ΡΠ²Π΅ΡΠ° ΠΏΠΈΡΡΡΡΡ Π² Π΅Π΄ΠΈΠ½ΠΎΠΌ ΡΡΠΈΠ»Π΅: + +- Π₯ΡΠ½Π΄Π»Π΅ΡΡ ΡΠ³ΡΡΠΏΠΏΠΈΡΡΡΡΡΡ ΠΏΠΎ ΠΎΠ±Π»Π°ΡΡΠΈ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ (ΠΏΠΎ ΠΎΠ±ΡΠ΅ΠΌΡ ΠΊΡΠΈΡΠ΅ΡΠΈΡ) +- ΠΠ»Ρ ΠΊΠ°ΠΆΠ΄ΡΠΉ Π³ΡΡΠΏΠΏΡ ΡΠΎΠ·Π΄Π°Π΅ΡΡΡ ΡΠ²ΠΎΠΉ ΠΌΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΎΡ +- ΠΠ±ΡΠ΅ΠΊΡ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ ΠΏΠ΅ΡΠ΅Π΄Π°Π΅ΡΡΡ Π² ΠΌΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΎΡ, ΡΡΠΎ Π±Ρ Π±ΡΡΡ Π΄ΠΎΡΡΡΠΏΠ½ΡΠΌ Π²Π½ΡΡΡΠΈ Ρ ΡΠ½Π΄Π»Π΅ΡΠΎΠ² + +#### `internal/controller/http/v1` + +ΠΠ°ΠΏΠΊΠ°, ΠΊΠ°ΠΊ ΠΏΡΠΎΡΡΠΎΠΉ ΡΠΏΠΎΡΠΎΠ± Π²Π΅ΡΡΠΈΠΎΠ½ΠΈΡΠΎΠ²Π°ΡΡ REST API. +ΠΠ»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π²Π΅ΡΡΠΈΠΈ v2, Π½ΡΠΆΠ½ΠΎ ΡΠΎΠ·Π΄Π°ΡΡ ΠΏΠ°ΠΏΠΊΡ `http/v2` Ρ ΡΠ°ΠΊΠΈΠΌ ΠΆΠ΅ ΡΠΎΠ΄Π΅ΡΠΆΠΈΠΌΡΠΌ. +ΠΠΎΠ±Π°Π²ΠΈΡΡ Π² ΡΠ°ΠΉΠ» `internal/app/app.go` ΡΡΡΠΎΠΊΠΈ: + +```go +handler := gin.New() +v1.NewRouter(handler, t) +v2.NewRouter(handler, t) +``` + +ΠΠΌΠ΅ΡΡΠΎ Gin ΠΌΠΎΠΆΠ½ΠΎ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ Π»ΡΠ±ΠΎΠΉ Π΄ΡΡΠ³ΠΎΠΉ http ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊ ΠΈΠ»ΠΈ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΡ `net/http` Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ. + +Π ΡΠ°ΠΉΠ»Π΅ `v1/router.go` Π½Π°Π΄ Ρ ΡΠ½Π΄Π»Π΅ΡΠΎΠΌ Π½Π°ΠΏΠΈΡΠ°Π½Ρ ΠΊΠΎΠΌΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ Π΄Π»Ρ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ Π΄ΠΎΠΊΡΠΌΠ΅Π½ΡΠ°ΡΠΈΠΈ ΡΠ΅ΡΠ΅Π· swagger [swag](https://github.com/swaggo/swag). + +### `internal/entity` + +Π‘ΡΡΠ½ΠΎΡΡΠΈ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ (ΠΌΠΎΠ΄Π΅Π»ΠΈ). ΠΠΎΠ³ΡΡ Π±ΡΡΡ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½Ρ Π² Π»ΡΠ±ΠΎΠΌ ΡΠ»ΠΎΠ΅. +Π’Π°ΠΊΠΆΠ΅ ΠΎΠ½ΠΈ ΠΌΠΎΠ³ΡΡΡ ΠΈΠΌΠ΅ΡΡ ΠΌΠ΅ΡΠΎΠ΄Ρ, Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, Π΄Π»Ρ Π²Π°Π»ΠΈΠ΄Π°ΡΠΈΠΈ. + +### `internal/usecase` + +ΠΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ°. + +- ΠΠ΅ΡΠΎΠ΄Ρ ΡΠ³ΡΡΠΏΠΏΠΈΡΠΎΠ²Π°Π½Ρ ΠΏΠΎ ΠΎΠ±Π»Π°ΡΡΠΈ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΠΈΡ (ΠΏΠΎ ΠΎΠ±ΡΠ΅ΠΌΡ ΠΊΡΠΈΡΠ΅ΡΠΈΡ) +- Π£ ΠΊΠ°ΠΆΠ΄ΠΎΠΉ Π³ΡΡΠΏΠΏΡ ΡΠ²ΠΎΡ ΠΎΡΠ΄Π΅Π»ΡΠ½Π°Ρ ΡΡΡΡΠΊΡΡΡΠ° +- ΠΠ΄ΠΈΠ½ ΡΠ°ΠΉΠ» - ΠΎΠ΄Π½Π° ΡΡΡΡΠΊΡΡΡΠ° + +Π Π΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΈ, webapi, rpc ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΡΡΡΡΠΊΡΡΡΡ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π² ΡΠ»ΠΎΠΉ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ Π² ΡΠ²ΡΠ·ΡΡΡΠ΅ΠΌ ΡΠ°ΠΉΠ»Π΅ `internal/app/app.go` +(ΡΠΌΠΎΡΡΠΈΡΠ΅ [ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ](#Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅-Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ)). + +#### `internal/usecase/repo` + +Π Π΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ β ΡΡΠΎ Π°Π±ΡΡΡΠ°ΠΊΡΠ½ΠΎΠ΅ Ρ ΡΠ°Π½ΠΈΠ»ΠΈΡΠ΅ (Π±Π°Π·Π° Π΄Π°Π½Π½ΡΡ ), Ρ ΠΊΠΎΡΠΎΡΡΠΌ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ°. + +#### `internal/usecase/webapi` + +ΠΡΠΎ Π°Π±ΡΡΡΠ°ΠΊΡΠ½ΠΎΠ΅ web API, Ρ ΠΊΠΎΡΠΎΡΡΠΌ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ°. +ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ Π²Π½Π΅ΡΠ½ΠΈΠΉ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡ, ΠΊ ΠΊΠΎΡΠΎΡΠΎΠΌΡ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ° ΠΎΠ±ΡΠ°ΡΠ°Π΅ΡΡΡ ΡΠ΅ΡΠ΅Π· REST API. +ΠΠ°Π·Π²Π°Π½ΠΈΠ΅ ΠΏΠ°ΠΊΠ΅ΡΠ° Π²ΡΠ±ΠΈΡΠ°Π΅ΡΡΡ ΡΠ°ΠΊΠΈΠΌ, ΡΡΠΎ Π±Ρ ΡΠΎΠΎΡΠ²Π΅ΡΡΡΠ²ΠΎΠ²Π°ΡΡ Π΅Π³ΠΎ Π½Π°Π·Π½Π°ΡΠ΅Π½ΠΈΡ. + +### `pkg/rabbitmq` + +RabbitMQ RPC ΠΏΠ°ΡΡΠ΅ΡΠ½: + +- ΠΠ½ΡΡΡΠΈ RabbitMQ Π½Π΅ ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΌΠ°ΡΡΡΡΡΠΈΠ·Π°ΡΠΈΡ +- ΠΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ fanout-ΠΎΠ±ΠΌΠ΅Π½, ΠΊ ΠΊΠΎΡΠΎΡΠΎΠΌΡ ΠΏΡΠΈΠ²ΡΠ·Π°Π½Π° ΠΎΠ΄Π½Π° ΡΠΊΡΠΊΠ»ΡΠ·ΠΈΠ²Π½Π°Ρ ΠΎΡΠ΅ΡΠ΅Π΄Ρ - ΡΡΠΎ Π½Π°ΠΈΠ±ΠΎΠ»Π΅Π΅ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ΄ΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΊΠΎΠ½ΡΠΈΠ³ΡΡΠ°ΡΠΈΡ +- ΠΠ΅ΡΠ΅ΠΏΠΎΠ΄ΠΊΠ»ΡΡΠ΅Π½ΠΈΠ΅ ΠΏΡΠΈ ΠΏΠΎΡΠ΅ΡΠ΅ ΡΠΎΠ΅Π΄ΠΈΠ½Π΅Π½ΠΈΡ + +## ΠΠ½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ + +ΠΠ»Ρ ΡΡΡΡΠ°Π½Π΅Π½ΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ ΠΎΡ Π²Π½Π΅ΡΠ½ΠΈΡ ΠΏΠ°ΠΊΠ΅ΡΠΎΠ² ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΠ΅ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ. + +ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΠ΅ΡΠ΅Π· ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡ "New" Π²Π½Π΅Π΄ΡΡΠ΅ΡΡΡ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ Π² ΡΠ»ΠΎΠΉ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ. +ΠΡΠΎ Π΄Π΅Π»Π°Π΅Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΡ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΠΎΠΉ ΠΈ ΠΏΠ΅ΡΠ΅Π½ΠΎΡΠΈΠΌΠΎΠΉ. +ΠΡ ΠΌΠΎΠΆΠ΅ΠΌ ΠΏΠ΅ΡΠ΅ΠΏΠΈΡΠ°ΡΡ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ° ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΡ Π½Π΅ Π²Π½ΠΎΡΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΡ Π² ΠΏΠ°ΠΊΠ΅Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ `usecase`. + +```go +package usecase + +import ( + // Nothing! +) + +type Repository interface { + Get() +} + +type UseCase struct { + repo Repository +} + +func New(r Repository) *UseCase{ + return &UseCase{ + repo: r, + } +} + +func (uc *UseCase) Do() { + uc.repo.Get() +} +``` + +ΠΠ»Π°Π³ΠΎΠ΄Π°ΡΡ ΡΠ°Π·Π΄Π΅Π»Π΅Π½ΠΈΡ ΡΠ΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ ΠΌΠΎΠΆΠ½ΠΎ Π³Π΅Π½Π΅ΡΠΈΡΠΎΠ²Π°ΡΡ ΠΌΠΎΠΊΠΈ (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΡ [mockery](https://github.com/vektra/mockery)) ΠΈ Π»Π΅Π³ΠΊΠΎ ΠΏΠΈΡΠ°ΡΡ ΡΠ½ΠΈΡ-ΡΠ΅ΡΡΡ. + +> ΠΡ Π½Π΅ ΠΏΡΠΈΠ²ΡΠ·Π°Π½Ρ ΠΊ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½ΡΠΌ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΡΠΌ ΠΈ Π²ΡΠ΅Π³Π΄Π° ΠΌΠΎΠΆΠ΅ΠΌ Π·Π°ΠΌΠ΅Π½ΠΈΡΡ ΠΎΠ΄ΠΈΠ½ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ Π½Π° Π΄ΡΡΠ³ΠΎΠΉ. +> ΠΡΠ»ΠΈ Π½ΠΎΠ²ΡΠΉ ΠΊΠΎΠΌΠΏΠΎΠ½Π΅Π½Ρ ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ, ΡΠΎ Π² Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ΅ Π½ΠΈΡΠ΅Π³ΠΎ Π½Π΅ Π½ΡΠΆΠ½ΠΎ ΠΌΠ΅Π½ΡΡΡ. + +## Π§ΠΈΡΡΠ°Ρ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° + +### ΠΠ»ΡΡΠ΅Π²Π°Ρ ΠΈΠ΄Π΅Ρ + +ΠΡΠΎΠ³ΡΠ°ΠΌΠΌΠΈΡΡΡ ΡΠΎΠ·Π΄Π°ΡΡ ΠΎΠΏΡΠΈΠΌΠ°Π»ΡΠ½ΡΡ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΡ ΠΏΠΎΡΠ»Π΅ Π½Π°ΠΏΠΈΡΠ°Π½ΠΈΡ ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΡΠ°ΡΡΠΈ ΠΊΠΎΠ΄Π°. + +> Π₯ΠΎΡΠΎΡΠ°Ρ Π°ΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ΅Ρ ΠΎΡΠΊΠ»ΡΠ΄ΡΠ²Π°ΡΡ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅ ΠΊΠ°ΠΊ ΠΌΠΎΠΆΠ½ΠΎ Π΄ΠΎΠ»ΡΡΠ΅. + +### ΠΡΠ½ΠΎΠ²Π½ΠΎΠΉ ΠΏΡΠΈΠ½ΡΠΈΠΏ + +ΠΠ½Π²Π΅ΡΡΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ (ΡΠ° ΠΆΠ΅, ΡΡΠΎ ΠΈ Π² SOLID) ΠΈΡΠΏΠΎΠ»ΡΠ·ΡΠ΅ΡΡΡ ΠΊΠ°ΠΊ ΠΏΡΠΈΠ½ΡΠΈΠΏ Π΄Π»Ρ Π²Π½Π΅Π΄ΡΠ΅Π½ΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ. +ΠΠ°Π²ΠΈΡΠΈΠΌΠΎΡΡΠΈ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½Ρ ΠΎΡ Π²Π½Π΅ΡΠ½Π΅Π³ΠΎ ΡΠ»ΠΎΡ ΠΊ Π²Π½ΡΡΡΠ΅Π½Π½Π΅ΠΌΡ. +ΠΠ»Π°Π³ΠΎΠ΄Π°ΡΡ ΡΡΠΎΠΌΡ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ° ΠΈ ΡΡΡΠ½ΠΎΡΡΠΈ ΠΎΡΡΠ°ΡΡΡΡ Π½Π΅Π·Π°Π²ΠΈΡΠΈΠΌΡΠΌΠΈ ΠΎΡ Π΄ΡΡΠ³ΠΈΡ ΡΠ°ΡΡΠ΅ΠΉ ΡΠΈΡΡΠ΅ΠΌΡ. + +ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΌΠΎΠΆΠ½ΠΎ ΡΠ°Π·Π΄Π΅Π»ΠΈΡΡ Π½Π° Π΄Π²Π° ΡΠ»ΠΎΡ - Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠΉ ΠΈ Π²Π½Π΅ΡΠ½ΠΈΠΉ: + +1. **ΠΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ°** (Π½Π°ΠΏΡΠΈΠΌΠ΅Ρ, ΡΡΠ°Π½Π΄Π°ΡΡΠ½Π°Ρ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠ° Go). +2. **ΠΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ** (Π±Π°Π·Ρ Π΄Π°Π½Π½ΡΡ , ΡΠ΅ΡΠ²Π΅ΡΠ°, Π±ΡΠΎΠΊΠ΅ΡΡ ΡΠΎΠΎΠ±ΡΠ΅Π½ΠΈΠΉ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΠΈ ΠΈ ΡΡΠ΅ΠΉΠΌΠ²ΠΎΡΠΊΠΈ). + + + +**ΠΠ½ΡΡΡΠ΅Π½Π½ΠΈΠΉ ΡΠ»ΠΎΠΉ** Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΎΠΉ Π΄ΠΎΠ»ΠΆΠ΅Π½ Π±ΡΡΡ ΡΠΈΡΡΡΠΌ. ΠΠ½ ΠΎΠ±ΡΠ·Π°Π½: + +- ΠΠ΅ ΠΈΠΌΠΏΠΎΡΡΠΈΡΠΎΠ²Π°ΡΡ ΠΏΠ°ΠΊΠ΅ΡΡ Ρ Π²Π½Π΅ΡΠ½ΠΈΡ ΡΠ»ΠΎΠ΅Π². +- ΠΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°ΡΡ ΡΠΎΠ»ΡΠΊΠΎ ΡΡΠ°Π½Π΄Π°ΡΡΠ½ΡΡ Π±ΠΈΠ±Π»ΠΈΠΎΡΠ΅ΠΊΡ. +- ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°ΡΡ Ρ Π²Π½Π΅ΡΠ½ΠΈΠΌΠΈ ΡΠ»ΠΎΡΠΌΠΈ ΡΠ΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ (!). + +ΠΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π΅ Π΄ΠΎΠ»ΠΆΠ½Π° Π½ΠΈΡΠ΅Π³ΠΎ Π·Π½Π°ΡΡ ΠΎ Postgres ΠΈΠ»ΠΈ ΠΎ ΡΠ΅Π°Π»ΠΈΠ·Π°ΡΠΈΠΈ web API. +ΠΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ° ΠΈΠΌΠ΅Π΅Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π΄Π»Ρ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΠ²ΡΠΈΡ Ρ _Π°Π±ΡΡΡΠ°ΠΊΡΠ½ΠΎΠΉ_ Π±Π°Π·ΠΎΠΉ Π΄Π°Π½Π½ΡΡ ΠΈΠ»ΠΈ _Π°Π±ΡΡΡΠ°ΠΊΡΠ½ΡΠΌ_ web API. + +**ΠΠ½Π΅ΡΠ½ΠΈΠΉ ΡΠ»ΠΎΠΉ** ΠΈΠΌΠ΅Π΅Ρ ΠΎΠ³ΡΠ°Π½ΠΈΡΠ΅Π½ΠΈΡ: + +- ΠΠΎΠΌΠΏΠΎΠ½Π΅Π½ΡΡ ΡΡΠΎΠ³ΠΎ ΡΠ»ΠΎΡ Π½Π΅ ΠΌΠΎΠ³ΡΡ Π·Π½Π°ΡΡ Π΄ΡΡΠ³ ΠΎ Π΄ΡΡΠ³Π΅ ΠΈ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²Π°ΡΡ Π½Π°ΠΏΡΡΠΌΡΡ. ΠΠ±ΡΠ°ΡΠ΅Π½ΠΈΠ΅ Π΄ΡΡΠ³ ΠΊ Π΄ΡΡΠ³Ρ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡ ΡΠ΅ΡΠ΅Π· Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠΉ ΡΠ»ΠΎΠΉ - ΡΠ»ΠΎΠΉ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ. +- ΠΡΠ·ΠΎΠ²Ρ Π²ΠΎ Π²Π½ΡΡΡΠ΅Π½Π½ΠΈΠΉ ΡΠ»ΠΎΠΉ Π²ΡΠΏΠΎΠ»Π½ΡΡΡΡΡ ΡΠ΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ (!). +- ΠΠ°Π½Π½ΡΠ΅ ΠΏΠ΅ΡΠ΅Π΄Π°ΡΡΡΡ Π² ΡΠΎΡΠΌΠ°ΡΠ΅, ΡΠ΄ΠΎΠ±Π½ΠΎΠΌ Π΄Π»Ρ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ (ΡΡΡΡΠΊΡΡΡΡ Ρ ΡΠ°Π½ΡΡΡΡ Π² `internal/entity`). + +ΠΠ°ΠΏΡΠΈΠΌΠ΅Ρ, Π½ΡΠΆΠ½ΠΎ ΠΎΠ±ΡΠ°ΡΠΈΡΡΡΡ ΠΊ Π±Π°Π·Π΅ Π΄Π°Π½Π½ΡΡ ΠΈΠ· HTTP Ρ ΡΠ½Π΄Π΅ΡΠ° (Π² ΡΠ»ΠΎΠ΅ ΠΊΠΎΠ½ΡΡΠΎΠ»Π»Π΅Ρ). +ΠΠ°Π·Π° Π΄Π°Π½Π½ΡΡ ΠΈ HTTP Π½Π°Ρ ΠΎΠ΄ΡΡΡΡ Π²ΠΎ Π²Π½Π΅ΡΠ½Π΅ΠΌ ΡΠ»ΠΎΠ΅. ΠΠ½ΠΈ Π½Π΅ Π·Π½Π°Ρ Π΄ΡΡΠ³ ΠΎ Π΄ΡΡΠ³Π΅ Π½ΠΈΡΠ΅Π³ΠΎ ΠΈ Π½Π΅ ΠΌΠΎΠ³ΡΡ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΎΠ²Π°ΡΡ Π½Π°ΠΏΡΡΠΌΡΡ. +ΠΠ·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Π±ΡΠ΄Π΅Ρ ΠΏΡΠΎΠΈΡΡ ΠΎΠ΄ΠΈΡΡ ΡΠ΅ΡΠ΅Π· ΡΠ»ΠΎΠΉ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠΈ `usecase`: + +``` + HTTP > usecase + usecase > repository (Postgres) + usecase < repository (Postgres) + HTTP < usecase +``` + +Π‘ΠΈΠΌΠ²ΠΎΠ»Ρ > ΠΈ < ΠΏΠΎΠΊΠ°Π·ΡΠ²Π°ΡΡ ΠΏΠ΅ΡΠ΅ΡΠ΅ΡΠ΅Π½ΠΈΡ ΡΠ»ΠΎΠ΅Π² ΡΠ΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΡ ΠΈ Π½Π°ΠΏΡΠ°Π²Π»Π΅Π½ΠΈΡ. +ΠΡΠΎ ΠΆΠ΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ΠΎ Π½Π° ΡΡ Π΅ΠΌΠ΅: + + + +ΠΡΠΈΠΌΠ΅Ρ Π±ΠΎΠ»Π΅Π΅ ΡΠ»ΠΎΠΆΠ½ΠΎΠ³ΠΎ ΠΏΡΡΠΈ Π΄Π°Π½Π½ΡΡ : + +``` + HTTP > usecase + usecase > repository + usecase < repository + usecase > webapi + usecase < webapi + usecase > RPC + usecase < RPC + usecase > repository + usecase < repository + HTTP < usecase +``` + +### Π‘Π»ΠΎΠΈ + + + +### Π’Π΅ΡΠΌΠΈΠ½ΠΎΠ»ΠΎΠ³ΠΈΡ Π² Π§ΠΈΡΡΠΎΠΉ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ΅ + +- **Entities** (ΡΡΡΠ½ΠΎΡΡΠΈ) - ΡΡΠΎ ΡΡΡΡΠΊΡΡΡΡ, Ρ ΠΊΠΎΡΠΎΡΡΠΌΠΈ ΡΠ°Π±ΠΎΡΠ°Π΅Ρ Π±ΠΈΠ·Π½Π΅Ρ Π»ΠΎΠ³ΠΈΠΊΠ°. + ΠΠ½ΠΈ ΡΠ°ΡΠΏΠΎΠ»Π°Π³Π°ΡΡΡΡ Π² ΠΏΠ°ΠΏΠΊΠ΅ `internal/entity`. + Π ΡΠ΅ΡΠΌΠΈΠ½ΠΎΠ»ΠΎΠ³ΠΈΠΈ MVC ΡΡΡΠ½ΠΎΡΡΠΈ - ΡΡΠΎ ΠΌΠΎΠ΄Π΅Π»ΠΈ. +- **Use Cases** ΡΡΠΎ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ°. Π Π°ΡΠΏΠΎΠ»Π°Π³Π°Π΅ΡΡΡ Π² ΠΏΠ°ΠΏΠΊΠ΅ `internal/usecase`. + +Π‘Π»ΠΎΠΉ, Ρ ΠΊΠΎΡΠΎΡΡΠΌ Π±ΠΈΠ·Π½Π΅Ρ-Π»ΠΎΠ³ΠΈΠΊΠ° Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΡΠ΅Ρ Π½Π°ΠΏΡΡΠΌΡΡ, ΠΎΠ±ΡΡΠ½ΠΎ, Π½Π°Π·ΡΠ²Π°Π΅ΡΡΡ _ΠΈΠ½ΡΡΠ°ΡΡΡΡΠΊΡΡΡΠ½ΡΠΌ_ ΡΠ»ΠΎΠ΅ΠΌ. +ΠΡΠΎ ΠΌΠΎΠΆΠ΅Ρ Π±ΡΡΡ ΡΠ΅ΠΏΠΎΠ·ΠΈΡΠΎΡΠΈΠΉ `internal/usecase/repo`, Π²Π½Π΅ΡΠ½Π΅Π΅ webapi `internal/usecase/webapi`, Π»ΡΠ±ΠΎΠΉ ΠΏΠ°ΠΊΠ΅Ρ ΠΈΠ»ΠΈ ΠΌΠΈΠΊΡΠΎΡΠ΅ΡΠ²ΠΈΡ. +Π ΡΠ°Π±Π»ΠΎΠ½Π΅ ΠΏΠ°ΠΊΠ΅ΡΡ _infrastructure_ ΡΠ°Π·ΠΌΠ΅ΡΠ΅Π½Ρ Π²Π½ΡΡΡΠΈ `internal/usecase`. + +ΠΡ ΠΌΠΎΠΆΠ΅ΡΠ΅ Π²ΡΠ±ΠΈΡΠ°ΡΡ, ΠΊΠ°ΠΊ Π½Π°Π·ΡΠ²Π°ΡΡ ΡΠΎΡΠΊΠΈ Π²Ρ ΠΎΠ΄Π°, ΠΏΠΎ ΡΠ²ΠΎΠ΅ΠΌΡ ΡΡΠΌΠΎΡΡΠ΅Π½ΠΈΡ. ΠΠ°ΡΠΈΠ°Π½ΡΡ ΡΠ°ΠΊΠΈΠ΅: + +- controller (Π² Π½Π°ΡΠ΅ΠΌ ΡΠ»ΡΡΠ°Π΅) +- delivery +- transport +- gateways +- entrypoints +- primary +- input + +### ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ»ΠΎΠΈ + +Π ΠΊΠ»Π°ΡΡΠΈΡΠ΅ΡΠΊΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ [Π§ΠΈΡΡΠΎΠΉ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) Π΄Π»Ρ ΡΠΎΠ·Π΄Π°Π½ΠΈΡ Π±ΠΎΠ»ΡΡΠΈΡ ΠΌΠΎΠ½ΠΎΠ»ΠΈΡΠ½ΡΡ ΠΏΡΠΈΠ»ΠΎΠΆΠ΅Π½ΠΈΠΉ ΠΏΡΠ΅Π΄Π»ΠΎΠΆΠ΅Π½ΠΎ 4 ΡΠ»ΠΎΡ. + +Π ΠΈΡΡ ΠΎΠ΄Π½ΠΎΠΉ Π²Π΅ΡΡΠΈΠΈ Π²Π½Π΅ΡΠ½ΠΈΠΉ ΡΠ»ΠΎΠΉ Π΄Π΅Π»ΠΈΡΡΡ Π½Π° Π΄Π²Π°, ΠΊΠΎΡΠΎΡΡΠ΅ ΡΠ°ΠΊΠΆΠ΅ ΠΈΠΌΠ΅ΡΡ ΠΈΠ½Π²Π΅ΡΡΠΈΡ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ Π² Π΄ΡΡΠ³ΠΈΠ΅ ΡΠ»ΠΎΠΈ ΠΈ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΡΡΡ ΡΠ΅ΡΠ΅Π· ΠΈΠ½ΡΠ΅ΡΡΠ΅ΡΡ. + +ΠΠ½ΡΡΡΠ΅Π½Π½ΠΈΠΉ ΡΠ»ΠΎΠΉ ΡΠ°ΠΊΠΆΠ΅ Π΄Π΅Π»ΠΈΡΡΡ Π½Π° Π΄Π²Π° (Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠΎΠ²) Π² ΡΠ»ΡΡΠ°Π΅ ΡΠ»ΠΎΠΆΠ½ΠΎΠΉ Π»ΠΎΠ³ΠΈΠΊΠΈ. + +--- + +Π‘Π»ΠΎΠΆΠ½ΡΠ΅ ΠΈΠ½ΡΡΡΡΠΌΠ΅Π½ΡΡ ΠΌΠΎΠ³ΡΡ Π±ΡΡΡ ΡΠ°Π·Π΄Π΅Π»Π΅Π½Ρ Π½Π° Π΄ΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½ΡΠ΅ ΡΠ»ΠΎΠΈ. +ΠΠ΄Π½Π°ΠΊΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΡΡ ΡΠ»ΠΎΠΈ ΡΠ»Π΅Π΄ΡΠ΅Ρ ΡΠΎΠ»ΡΠΊΠΎ Π² ΡΠΎΠΌ ΡΠ»ΡΡΠ°Π΅, Π΅ΡΠ»ΠΈ ΡΡΠΎ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΠ΅Π»ΡΠ½ΠΎ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ. + +### ΠΡΡΠ³ΠΈΠ΅ ΠΏΠΎΠ΄Ρ ΠΎΠ΄Ρ + +ΠΡΠΎΠΌΠ΅ Π§ΠΈΡΡΠΎΠΉ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ Π΅ΡΡΡ ΠΈ Π΄ΡΡΠ³ΠΈΠ΅ ΠΏΠΎΠ΄ΠΎΡ ΠΎΠ΄Ρ: + +- ΠΡΠΊΠΎΠ²Π°Ρ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΠ° +- ΠΠ΅ΠΊΡΠΎΠ³ΠΎΠ½Π°Π»ΡΠ½Π°Ρ (_ΠΠΎΡΡΡ ΠΈ Π°Π΄Π°ΠΏΡΠ΅ΡΡ_ ΡΠ°ΠΊΠΆΠ΅ Π½Π° Π½Π΅Ρ ΠΏΠΎΡ ΠΎΠΆΠ°) + ΠΠ½ΠΈ ΠΎΠ±Π΅ ΠΎΡΠ½ΠΎΠ²Π°Π½Ρ Π½Π° Π½Π° ΠΏΡΠΈΠ½ΡΠΈΠΏΠ΅ ΠΈΠ½Π²Π΅ΡΡΠΈΠΈ Π·Π°Π²ΠΈΡΠΈΠΌΠΎΡΡΠ΅ΠΉ. + _ΠΠΎΡΡΡ ΠΈ Π°Π΄Π°ΠΏΡΠ΅ΡΡ_ ΠΎΡΠ΅Π½Ρ ΠΏΠΎΡ ΠΎΠΆΠΈ Π½Π° _Π§ΠΈΡΡΡΡ ΠΡΡ ΠΈΡΠ΅ΠΊΡΡΡΡ_. Π Π°Π·Π»ΠΈΡΠΈΡ Π² ΠΎΡΠ½ΠΎΠ²Π½ΠΎΠΌ Π·Π°ΠΊΠ»ΡΡΠ°ΡΡΡΡ Π² ΡΠ΅ΡΠΌΠΈΠ½ΠΎΠ»ΠΎΠ³ΠΈΠΈ. + +## ΠΠΎΡ ΠΎΠΆΠΈΠ΅ ΠΏΡΠΎΠ΅ΠΊΡΡ + +- [https://github.com/bxcodec/go-clean-arch](https://github.com/bxcodec/go-clean-arch) +- [https://github.com/zhashkevych/courses-backend](https://github.com/zhashkevych/courses-backend) + +## ΠΠΎΠΏΠΎΠ»Π½ΠΈΡΠ΅Π»ΡΠ½Π°Ρ ΠΈΠ½ΡΠΎΡΠΌΠ°ΡΠΈΡ + +- [The Clean Architecture article](https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html) +- [Twelve factors](https://12factor.net/ru/)