

Dependency Injection with Go - saj1th
http://blog.parse.com/2014/05/13/dependency-injection-with-go/

======
argon81
Went down this path already.

It was OK for a while with a small codebase, but the problem is that you need
to give up your simple direct Go code for magic reflection.

I discovered there are better and more idiomatic ways to do this type if thing
without resorting to dependency injection.

~~~
sagichmal
Strongly agree. A verbose `main` carries the benefit of being explicit and
unambiguous. Components whose constructors take all of their dependencies are
simple to reason about and straightforward to test.

The code described in the article seems like it's burdened with patterns from
other languages and ecosystems, and which are pretty nonidiomatic Go:
"AppLoader"? The complexity of their final solution seems to be a result of
not challenging those patterns and assumptions.

~~~
blt
Yeah. I think the fear of a verbose `main` is wrong. It's OK for complicated
code to look complicated. If your app needs to initialize a lot of complex
network dependencies at startup, then maybe your startup routine is going to
have a lot of code. No big deal.

Software is complex. We all repeat, and try to follow, the mantra of writing
simple code that does one thing. We succeed a lot of the time. But sometimes,
we just need to do something f'n complicated. Better to express the complexity
in type safe, debuggable code that everyone understands, than to hide it
behind some framework.

I think developers should be more accepting of a code base that's 95% clean
and 5% messy. "The perfect is the enemy of the good."

------
chewxy
Does anyone think this is a little stoppy (there isn't a Go equivalent to
"unpythonic")?

~~~
Mithaldu
> there isn't a Go equivalent to "unpythonic"

Of course there is. :) Python does good marketing and rephrased an existing
word, but the pair you're looking for is:

idiomatic / unidiomatic

------
mutatio
"Typically the main() function would call the various init functions like
InitMongoService"

Why muddy your main() when init() exists?

See:
[http://golang.org/ref/spec#Package_initialization](http://golang.org/ref/spec#Package_initialization)

~~~
sagichmal
And why use InitXxx at all, when you can create an initialized, locally-scoped
MongoService with a constructor, and pass it to the things that need it?

~~~
mutatio
I was referring to Go's magic func init()

Putting that in your files, let's say:

    
    
      db.go func init() => handle global DB's...
    
      templates.go func init() => handle HTML templates...
    
      settings.go func init() => load some settings...
    

All fired _automatically_ prior to your applications main() entry point
WITHOUT needing to pollute main() with initDB(); initTemplates();
initSettings() etc. etc.

~~~
nostrademons
They're trying to pass the objects created at startup into other objects, so
that dependencies are explicit and can be mocked out in unit tests. You can't
do this with init(), which always takes no arguments and returns no values.

------
fishnchips
I honestly don't think there even was a problem to be solved. Constructors
could just accept their dependencies (interfaces) as parameters.

~~~
shellac
On larger code bases it can help a lot. You get to a point where you need that
config object over in some random function and you start weaving it through
constructors. At which point a simple DI system really appeals.

DI code also tends to be more pleasant to test in my experience since it
promotes loose coupling.

~~~
fishnchips
I believe there are other ways:

[http://commandcenter.blogspot.com/2014/01/self-
referential-f...](http://commandcenter.blogspot.com/2014/01/self-referential-
functions-and-design.html)

And you should probably avoid situations where you suddenly need config
objects in 'random places'. This could be a symptom of chaotic API design. But
then again, whatever works for you.

------
pjmlp
And thus the path to Go2EE slowly starts....

~~~
lmm
Just as with Java, if you keep the language simple then the complexity still
has to go somewhere.

------
iand
I'm interested in real examples of dependency injection being useful outside
of hooking up testing objects. Anyone got any links to interesting examples?

~~~
eknkc
Martini ([https://github.com/go-martini/martini](https://github.com/go-
martini/martini)) uses DI for everything. I's supposed to be freaking slow
though. But it might not be a real world problem.

~~~
iand
I guess I should have been clearer - I mean examples where you actually want
different dependencies for the same application.

All uses of DI that I have seen have a single configuration that basically
never changes. The DI is used for hooking up test objects, but not for
reconfiguring the production app.

