Git Product home page Git Product logo

Comments (4)

camstuart avatar camstuart commented on May 18, 2024 2

Ok, I'll bite :)

IMHO the use of global variables should indeed be discouraged. But in this case, I think a global database connection is a perfectly valid decision.

Before I explain why perhaps some background on how I came to be here.

I just discovered this awesome concept of "real world apps". I am on the lookout for a new frontend framework that doesn't make me crazy. Looks like elm fits the bill. And being a Go developer, I was pleased to see this repo. As it turns out, I use Gin as well.

And all my Gin projects have a global DB connection. As with all software, there are tradeoffs. I think there are plenty of reasons documented that recommend against the use of global variables, articles that you have pointed out. And I have tried the middleware approach.

I use a global database connection for these reasons;

init()

During the init phase of my apps is when I connect to the database. The global has been declared already, and during init, I connect. Incidentally, this is also where I define all of my routes.

And therefore, I defer the close of the database as the first line in main()

I also favour deployment to serverless cloud platforms, in Docker containers if I can.
And one common situation here is the outer architecture keeping my app "warm" for me.

Some serverless implementations recommend connecting to a database within your http handler. Which can result in poor scaling (too many database connections at once)

So connecting in init() is simple, and works well.

func myFunc(db *gorm.DB, .....)

So you might be able to avoid having to pass your database connection into your handlers by using middleware or some other approach, but what about functions that those handlers may call? Again, a single, global variable is easier.

The most common argument I hear about the use of global variables is that in a large codebase they make things messy, complicated, and potentially dangerous. I agree with this view.

But let's remember, you don't go "modifying" the content of this variable. So it could also be considered a constant. So I don't see any risk of it being blatted. And in my 20 years of software, that has never occurred.

And in the microservice world, apps are just not that big anymore.

package somethingOtherThanMain

Globals go out of scope in other packages. But I keep my API/Service code in package main because my philosophy of package is "re-usable" code. Yes, I split my app into multiple files, so I can organise. But not packages. That's an entirely different concept. Never have I written a User package and been able to re-use it in another app. Life is never that simple.

I like a global database connection/handle. It's simple to set up and use, works, and very readable. In my view, this is what I strive for in all the code I write.

While we are on the topic of global variables in a web API / microservice, I also have a global logger.

At the end of the day, I can talk to the database, and log messages anywhere in my code, and so far, nothing bad has ever happened.

from golang-gin-realworld-example-app.

kravemir avatar kravemir commented on May 18, 2024

Hello @camstuart,

thank you for the exhaustive answer. Thinking about this awesome concept of "real world apps"...

You've got a point with that life is not that simple to make reusable feature "packages". IMHO, it might be easier to implement it as configurable reusable microservice with API contract (and maybe client library / package to implement connectors).

In the end, in modern development, things tend to get away from monoliths connecting to multiple databases. With YAGNI principle, it is valid point to think about database as a constant for whole application / microservice.

What about testing? Do you do automated tests? If so, how do you deal with having DB connection as global variable?

I'm coming from Java world, and DI helps to create temporary and isolated unit/integration test environment, which is completely isolated from others test. I'm not quite sure, how to accomplish isolation of individual tests, when there's a global variable holding database connection.

from golang-gin-realworld-example-app.

wangzitian avatar wangzitian commented on May 18, 2024

The function invokes a package global database/sql.Conn, to make a query against some unspecified database; a package global ... . All of these operations have side effects that are completely invisible from an inspection of the function signature. There is no way for a caller to predict any of these things will happen, except by reading the function and diving to the definition of all of the globals.

Global variables are bad behavior, but global utils/middlewares are not bad which could help us reduce code repeating. A better practice might write some utils in global, then managing the database connections in a very small & obvious scope. For example, initializing a database connection might slow, we just initialize once in one place. Or we don't want too much clients connect to the database at the sametime, we write a manager to do the job. Those codes could be share to all apps in your project.
BTW, accessing unspecified database(more general, accessing a resource/interface) was hard to prevent in real world even manage database in non global place. My idea of this point is that never trust 3rd resource, we should always check it & log error as early as possible.

By lifting each of the dependencies into the signature as parameters, we allow readers to accurately model the scope and potential behaviors of the function. The caller knows exactly what the function needs to do its work, and can provide them accordingly.

This idea sounds like 'Functional programming', it was good practice in most scenes(easy to write ut, not need to worry break down other function behavior, no state inside function, one input will always have one certainly output), but some time it will lose some flexibility(consensus logic/info might repeated everywhere). Depends on your tradeoffs..

For this small project, I just want to offer a comfortable way to write curd logic for newcomers. A important requirement is that a newcomer should easliy find a place to insert own code, putting similar codes together & making main workflow simple will make it more easier to read. :)

from golang-gin-realworld-example-app.

wangzitian avatar wangzitian commented on May 18, 2024

@camstuart

But let's remember, you don't go "modifying" the content of this variable. So it could also be considered a constant.

Hit the nail! Offering a bigger context in main workflow will bring convenient for most time in real world.

@kravemir
The main side effect of bigger contexts is we might need write more regression testings and it was painful to write unit tests.
We could wrapping some small function just do simple things with good unit testings, then regression testings only test main work flow indeed works.

from golang-gin-realworld-example-app.

Related Issues (18)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.