bxcodec / go-clean-arch

Go (Golang) Clean Architecture based on Reading Uncle Bob's Clean Architecture
MIT License
9.06k stars 1.19k forks source link

[feature]:implement transaction #36

Open philchia opened 4 years ago

frederikhors commented 3 years ago

@bxcodec I love Golang and your project. Is there any news on this? No pressure. 😄

bxcodec commented 3 years ago

Hi @frederikhors ,

So yeah, I keep this PR open, so everyone can see all the opinions by the other.

I want to make this PR just like a reference and any new golang engineer can choose which evil side they prefer. Every opinion is valid from anyone's perspective. So since this a public PR, I don't wanna choose one and merge it, unless if it's for my private project I'll choose one and convince my team about it.

frederikhors commented 3 years ago

@bxcodec thanks for your answer.

Since I don't know how to decide (because I'm newbie and because they all seem not 100% correct to me) I can ask you which method do you prefer?

I need to use a transaction:

  1. in a one usecase method that uses multiple repositories methods
  2. in a single method of a single repository (but here I can also do it manually)
frederikhors commented 3 years ago

@bxcodec what do you think about this?

https://github.com/frederikhors/go-clean-arch/commit/2ec0f2d7d8d4a5f5ed076e4a1ce59eb862333ca7

I don't know how to do this:

//I can also create an helper like this:
//dbConn := db.GetTxFromCtxOrUseDBConn(ctx, m.Conn)
//instead of the below:
var dbConn interface{} // I think I need an interface for *sql.DB & *sql.Tx here
tx, ok := repository.GetTransactionFromCtx(ctx)
if ok {
    dbConn = tx
} else {
    dbConn, _ = m.Conn.BeginTx(ctx, nil)
}

Is that what you thought? To use context like this to handle transactions?

nii236 commented 3 years ago

If you have to use transactions across multiple repositories, it doesn't make sense to put it behind an interface anyway. Unless you'll only be dealing with different flavours of SQL databases.

frederikhors commented 3 years ago

@nii236 I don't understand. Can you please explain it better? Thanks.

masajip commented 1 year ago

@nii236 I don't understand. Can you please explain it better? Thanks.

I would try to explain what is meant by @nii236 , the idea of defining a repository as an interface is because we're trying to make it pluggable/changeable by following the principle of Dependency Inversion, but if we use a transaction moreover if it's across multiple repositories, it would be impossible for our system to change our dependency from a SQL database into another kind of repository (NoSQL, Rest API, GRPC, or any other kind) because the concept of atomic transaction is only exist on SQL Database, then if we define those repository as an interface it would be useless because we're preparing for something that would never happen

nii236 commented 1 year ago

This blog post explains my thinking: https://threedots.tech/post/common-anti-patterns-in-go-web-applications/

Scroll down to "Starting with the database schema".