evrone / go-clean-template

Clean Architecture template for Golang services
MIT License
6.35k stars 536 forks source link

Repo has to be outside usecases #204

Open lexizz opened 6 months ago

lexizz commented 6 months ago

I've not understood why you put the Repo inside usecases layer. As I as know Repo relates of infrastructure layer, and there may be storage like postgresql, kafka, file and some external service. And some business logic has to be inside usecases layer. I mean this:

Storage

internal/storage
├── postgres
│   ├── translation
│   │   ├── entity.go      // struct entity's db, for scan (getting data into this struct entity)
│   │   └── translation.go // there are some requests to db
│   ├── system
│   │   ├── entity.go      // struct entity's db, for scan (getting data into this struct entity)
│   │   └── system.go      // some requests to db
│   └── user
│       ├── entity.go      // struct entity's db, for scan (getting data into this struct entity)
│       └── user.go        // some requests to db
├── kafka
│   ├── translation
│   │   ├── entity.go      // struct entity's kafka consumer
│   │   └── translation.go // there are some requests to db
│   ├── system
│   │   ├── entity.go      // struct entity's kafka consumer
│   │   └── system.go      // some requests to db
│   └── user
│       ├── entity.go      // struct entity's kafka consumer
│       └── user.go        // some requests to db
├── google
│   ├── translation
│   │   ├── entity.go      // struct entity's google
│   │   └── translation.go // there are some requests to db
│   ├── system
│   │   ├── entity.go      // struct entity's google
│   │   └── system.go      // some requests to db
│   └── user
│       ├── entity.go      // struct entity's google
│       └── user.go        // some requests to db
└── storage.go             // description of interfaces entity's methods (translation, system, user) for implementation by other storage

UseCases (Services)

internal/usecases
├── translation
│   └── create.go
│   └── translate.go
│   └── convert.go
├── system
│   └── create.go
│   └── check.go
│   └── off.go
└── user
    └── create.go
    └── check_role.go
    └── notificate.go

Models

As you did mentioned, domain models are need to work between layers

Conclusion

All the layers are isolated and reused easy


What do you think about it?

dangquyitt commented 2 months ago

I've not understood why you put the Repo inside usecases layer. As I as know Repo relates of infrastructure layer, and there may be storage like postgresql, kafka, file and some external service. And some business logic has to be inside usecases layer. I mean this:

Storage

internal/storage
├── postgres
│   ├── translation
│   │   ├── entity.go      // struct entity's db, for scan (getting data into this struct entity)
│   │   └── translation.go // there are some requests to db
│   ├── system
│   │   ├── entity.go      // struct entity's db, for scan (getting data into this struct entity)
│   │   └── system.go      // some requests to db
│   └── user
│       ├── entity.go      // struct entity's db, for scan (getting data into this struct entity)
│       └── user.go        // some requests to db
├── kafka
│   ├── translation
│   │   ├── entity.go      // struct entity's kafka consumer
│   │   └── translation.go // there are some requests to db
│   ├── system
│   │   ├── entity.go      // struct entity's kafka consumer
│   │   └── system.go      // some requests to db
│   └── user
│       ├── entity.go      // struct entity's kafka consumer
│       └── user.go        // some requests to db
├── google
│   ├── translation
│   │   ├── entity.go      // struct entity's google
│   │   └── translation.go // there are some requests to db
│   ├── system
│   │   ├── entity.go      // struct entity's google
│   │   └── system.go      // some requests to db
│   └── user
│       ├── entity.go      // struct entity's google
│       └── user.go        // some requests to db
└── storage.go             // description of interfaces entity's methods (translation, system, user) for implementation by other storage

UseCases (Services)

internal/usecases
├── translation
│   └── create.go
│   └── translate.go
│   └── convert.go
├── system
│   └── create.go
│   └── check.go
│   └── off.go
└── user
    └── create.go
    └── check_role.go
    └── notificate.go

Models

As you did mentioned, domain models are need to work between layers

Conclusion

All the layers are isolated and reused easy

What do you think about it?

I agree with your structure, but I don't think it's necessary to declare the interface in/storage/storage.gobecause this is Go, not Java or C#. Interfaces should be declared where they are used, according to the Go code review comments document. This keeps the use case independent of the storage, making it easier to refactor and unit test.