Hacker News new | ask | show | jobs
by zarathustreal 1373 days ago
>I don't have a very good answer for "yeah, but what about dependency injection"? though. Any thoughts from anyone?

There is no "dependency injection" in a functional world, take this opportunity to show your colleague how FP makes their life easier. It's just a function.

Instead of a class, implementing an interface, created by a factory, requiring a constructor, all you need is a function.

Anything that was previously a "dependency" in OO terms is now an argument to your function. If you want to "inject" that dependency you simply partially apply your function, the result is then of course a function with that "dependency" "injected" which can then be used as usual. In JavaScript there's even a nifty built-in prototype method on every function called `Function.prototype.bind` which allows you to do the partial application to create the "dependency injected" function!

Example:

```

const iRequireDependencies = (dependencyA, dependencyB, actualArgumentC, actualArgumentD, ...etc) => console.log(dependencyA, dependencyB, actualArgumentC, actualArgumentD, ...etc);

const withRandomDependencies = iRequireDependencies.bind(undefined, 'randomA', 'randomB')

withRandomDependencies('actualA', 'actualB', 'actualC', 'actualD', 'actualE') // etc

// => 'randomA' 'randomB' 'actualA' 'actualB' 'actualC' 'actualD' 'actualE'

```

2 comments

I think the problem with DI is less about how they are passed in and more about how usually there is are only two implementations: the real one and a test one. The test one is a mock/stub based on assumed behaviours of the real thing. Obviously, such an approach is essential in some situations but in general it is mostly bad.
The problem with that is that eventually you want to have the dependencies automatically injected (like how an IoC container would be used in a typical OOP application).

Sure, there's solutions for this in the FP world, but in my experience they tend to have their own drawbacks. Admittedly, I've only ever used TS on the front-end (with no DI), so I've never really looked at what FP-style libraries exist for this.

You could model that with one function taking that dependency and returning a new one with it included. Then you just use the one that has it included instead of the one that doesn't.
You still have to construct and pass in that dependency though, along with all of its dependencies, recursively.
Are you seeing any decorator or OOP style in React? Yet plenty of dependencies are automatically injected without the OOP jargon, if you want to see a pure JS example of auto DI go check angular 1.5 dep system, and Vuejs.
> React

I totally agree there are other good/better options (as evidenced by react and many others), but I don't think this is an entirely fair comparison. The main "DI" alternatives in React are hooks, context, and imports, none of which could really replace traditional IoC containers on the backend without some modifications.

I think the main thing that makes automatic DI easy with OOP is the clear separation between dependencies (constructor parameters), and method parameters. Admittedly, this is totally possible with FP, but requires some good conventions and doesn't seem to be nearly as popular.

I also think most OOP langs have terrible syntax for constructors, which makes it look clunkier than it really is. Primary constructors (e.g. kotlin) make this not much more verbose than the FP alternative.

> Angular 1.5 dep system

Yes it's vanilla JS, but I doubt there's many FP people that would call that functional. The examples I saw are all just using JS functions as "discount classes", which definitely aren't pure or functional.

Why do you need automatic injection? What the parent said is idiomatic FP
Because in typical back-end software, the dependency tree can get very big very fast. Having an IoC container means devs only have to declare direct dependencies for each service, rather than constructing the entire tree (and figure out the necessary ordering, etc).