go-clean-arch icon indicating copy to clipboard operation
go-clean-arch copied to clipboard

How to manage dependency will be more elegant?

Open bluntdel opened this issue 5 years ago • 7 comments
trafficstars

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 avatar Dec 02 '19 07:12 bluntdel

@bluntdel and @bxcodec what do you think about https://github.com/google/wire guys?

frederikhors avatar Feb 12 '20 01:02 frederikhors

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.

bxcodec avatar May 15 '20 08:05 bxcodec

@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.

PhantomX7 avatar Aug 11 '20 08:08 PhantomX7

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()
    ....
}

myugen avatar Nov 10 '20 21:11 myugen

@bxcodec I made a sample project with dependency injection framework uber-go/fx. Could you feedback to me?

https://github.com/mcauto/todolist-api

mcauto avatar Dec 13 '21 05:12 mcauto

I wonder that is this way testable? and where to place ArticleContext.

HubQin avatar Feb 23 '23 11:02 HubQin

이런 식으로 테스트 가능한지 궁금합니다. 그리고 ArticleContext를 배치할 위치.

How about this?

https://github.com/mcauto/todolist-api/blob/main/modules/domains/todo/service_test.go#L38

mcauto avatar Feb 24 '23 06:02 mcauto