go-clean-arch
go-clean-arch copied to clipboard
How to manage dependency will be more elegant?
I see these codes in the main.go.
authorRepo := _authorRepo.NewMysqlAuthorRepository(dbConn) ar := _articleRepo.NewMysqlArticleRepository(dbConn) timeoutContext := time.Duration(viper.GetInt("context.timeout")) * time.Second au := _articleUcase.NewArticleUsecase(ar, authorRepo, timeoutContext) _articleHttpDeliver.NewArticleHttpHandler(e, au)
I think if articleUcase need articleRepo,articleAuthorRepo and more other repository... Dependency management will be terrible, it will produce many codes like "newAriticleUseaCase(ARepo,BRepo,CRepo...)".So if it can be more elegant? I don't think write in the main.go is a good idea.
@bluntdel and @bxcodec what do you think about https://github.com/google/wire guys?
Wow, good question, personally I haven't do any elegant way.
Because for me personally, I'd rather see an explicit one rather than implicit, like in Java world with a lot of decorator things, that really consumes a lot of my mind budget to understand how is it worked.
Also in this explicit way, I can do knowledge transfer to junior engineers easily without the need to know how dependency injection tools work.
@frederikhors , I'll look into it, and try to understand it. If it's not making things more complicated, then it's a good to try.
@bluntdel surely it is a problem if we create a monolith using this this design pattern. It will create a long dependency injection call
func New(aRepo a.repository, bRepo b.repository ...) AUsecase { ... }
i have found a great library called fx to reduce the code boilerplate of the dependency injection.
@frederikhors the difference between wire and fx is that wire is a code generator and fx is runtime auto inject dependency.
Maybe, it could be possible manage those dependencies through a context, for example, creating an ArticleContext interface such that
type ArticleContext interface {
GetARepo() ARepo
GetBRepo() BRepo
GetCRepo() CRepo
....
GetZRepo() ZRepo
}
Then, you just need to call inside usecase the respective repository:
func (a *articleUsecase) Fetch(c MyArticleContext, cursor string, num int64) (res []domain.Article, nextCursor string, err error) {
....
aRepo := c.GetARepo()
....
}
@bxcodec I made a sample project with dependency injection framework uber-go/fx. Could you feedback to me?
https://github.com/mcauto/todolist-api
I wonder that is this way testable? and where to place ArticleContext.
이런 식으로 테스트 가능한지 궁금합니다. 그리고 ArticleContext를 배치할 위치.
How about this?
https://github.com/mcauto/todolist-api/blob/main/modules/domains/todo/service_test.go#L38