gothinkster / golang-gin-realworld-example-app

Exemplary real world application built with Golang + Gin
https://realworld.io
MIT License
2.5k stars 495 forks source link

[Question] Coupling Persistent Model and Business Model #2

Closed vanhtuan0409 closed 6 years ago

vanhtuan0409 commented 6 years ago

Just my concern, it is considered bad practice when you use the same Persistent Model for Business Model. Also, I saw some pieces of logic was implemented by database query (Article Feed)

wangzitian0 commented 6 years ago

Thanks for the reaching out, I'm very open to discuss the better practice. I think you describe 2 issue: Q1, r u means the the Persistent model was unnecessary?In my view, business model should not coupling with SQL sentences or the object level cache issue, so how would you write the codes without gorm? BTW, many codes here are reusable. Q2, The purpose of this project was that showing a conciseness practice of using framework, such as data binding and param dealing, not how to improve the throughput. Of course, api like Article Feed could use Elastic Search, auth model could save in Redis, the performance will be totally different, but that's another topic. Feel free to discuss:)

vanhtuan0409 commented 6 years ago

Sorry, my English is very bad. I will try to explain my concern again. I think we should aim for absolute separation of Business model and Persistent model.

func (u UserModel) following(v UserModel) error {
    db := common.GetDB()
    var follow FollowModel
    err := db.FirstOrCreate(&follow, &FollowModel{
        FollowingID:  v.ID,
        FollowedByID: u.ID,
    }).Error
    return err
}

With this function, UserModel was coupled with a specific database implementation and it will be hard to test this function without running a real SQL database. With ORM, your users/router.go become very clean and I love it. But I afraid with ORM, you cannot separate Business Model and database implementation completely. How do you think about using repository pattern with an interface?

wangzitian0 commented 6 years ago

Alright, those kind of code only appears in the dealing of relationships(one2one,one2many,many2many). Normal objects might need modify some fields without committing a transaction while most relationships could be modified right now, so I didn't separate them. How to save the relationships are truely related to database such as MongoDB using List type. BTW, Golang was not object-oriented language, do we need to separate a very pure object without persistent? As for testing, I just used a test DB for integration tests like the Django framework, mocking the datas in the real test database. It's not friendly to writing unit tests with relationships.

vanhtuan0409 commented 6 years ago

@wangzitian0 tks for your reply 👍 I learnt a lot from your project