dwyl / learn-node-js-by-example

:cloud: Practical node.js examples.
http://nelsonic.gitbooks.io/node-js-by-example/
Other
48 stars 11 forks source link

Dependency Injection in nodejs, yes or no? #31

Open jruts opened 7 years ago

jruts commented 7 years ago

Dependency Injection

I come from a Java background where DI is a very good approach to build a solid code base. I am interested to hear what the nodejs community thinks about this and if the same logic applies.

Why DI?

DI makes your code more modular since you pass along your dependencies rather then requiring them. It also makes unit testing a lot easier since you can just pass in fake representations of your dependencies without having to do some complex mocking.

Why not?

This is the question I would like to see answered.

Articles

https://blog.risingstack.com/dependency-injection-in-node-js/ https://www.devbridge.com/articles/dependency-injection-in-javascript/ https://medium.com/@Jeffijoe/dependency-injection-in-node-js-2016-edition-f2a88efdd427#.jxijeinhq

nelsonic commented 7 years ago

Hi @jruts, yeah, having spent time in Java-land I can see the temptation to follow the DI pattern. 🤔 In node-topia 🌈 while you can use DI, you don't have to and the pattern can add complexity to your app/service...

Thankfully, there'a much better set of answers on StackOverflow for this question: http://stackoverflow.com/questions/9250851/do-i-need-dependency-injection-in-nodejs-or-how-to-deal-with I differ to @jprichardson's experience/insight (wisdom) on this. 👍

jruts commented 7 years ago

@nelsonic I read it, but if you check the replies on his answer they seem pretty negative, and I have to agree with most of them.

nelsonic commented 7 years ago

@jruts the "negative" comments on the answer http://stackoverflow.com/a/9254959/1148249 all come from people who are clinging on to their OO knowledge (pre-conceived idea of the "right" way of writing code) and trying to apply it to JS (which is a bit of a hodge-podge multi-paradigm language...) instead of being open to a less complex way of writing code.

Perhaps a more constructive (pun intended) way of thinking about this question is:

What problem are we trying to solve? Are you writing single-use code or are building a library for others to use/invoke? Have you solved the problem before and realised DI would have made the code simpler? and What is the least amount of code I can write to solve it now which makes the test(s) pass so I can ship this for a user to test.

DI will be the "solution" if that's the "hammer" you've been taught to use during your "formative" years (e.g. learning Java as your first Programming Language at School/University or your first job...) the same as NO-DI would be the preferred approach if you were lucky enough to learn Lisp

Ultimately, this is JavaScript so the "I don't like it because that's not how I do it" rule applies: https://twitter.com/iamdevloper/status/803265259402305536

But I urge you (and everyone else) to think about every "challenge" with a mind of how can I write the least code for the current problem I'm solving without over-thinking it with "forward planning" (i.e. don't build "interfaces" until you need them and then re-factor older code when required...)

If you discover by shipping that DI results code that:

  • solves the problem/challenge and only does one thing
  • easier to read & "reason about"
  • easier to maintain (by people who did not write the code)

.then you should use DI to solve the problem. But I don't think anyone can make a blanket statement that DI is always the "best" way of solving the problem whereas in many cases DI will not improve things.

jprichardson commented 7 years ago

Hi. I want to point out that I wrote that answer almost 5 years ago. However, I still stand by this statement that I made:

In short, you don't need a dependency injection container or service locater like you would in C#/Java. Since Node.js, leverages the module pattern, it's not necessary to perform constructor or property injection. Although you still can.

However, from a unit-testing front, I'd strongly recommend https://github.com/thlorenz/proxyquire

Finally, there's a lot of wisdom in this statement by @nelsonic:

But I urge you (and everyone else) to think about every "challenge" with a mind of how can I write the least code for the current problem I'm solving without over-thinking it with "forward planning" (i.e. don't build "interfaces" until you need them and then re-factor older code when required...)

👍