Hacker News new | past | comments | ask | show | jobs | submit login

It's funny to me from a mathematical POV. Dependency injection is clearly "just" function abstraction. It could not be simpler.

Yet here we are belabored by whole frameworks to achieve it.




There are ways to talk about it that help developers understand. Instead of focusing on the pattern overall, talk about the core dependency manager as often as possible. If a junior or mid-level developer gets it pounded into their heads that there's a magical piece of code doing some stuff they can't see, then they might just figure things out.

But that's only a band-aid. It's my experience that they still won't truly understand why they can't just call A from B and they certainly don't understand how to get B in A through an injection.


It always just feels like unnecessary terminology and technology. Here's the core pattern.

    function app(injected) {
      return injected.doSomething();
    }

    function main() {

      var injectable = new Injectable();
      var result     = app(injectable);
      console.log(result);

    }
Everything else is around obscuring that core pattern or making it "convenient" by providing some kind of naming abstraction. That at least makes a little bit of sense in Javascript, like above, since you need the stringy names to simulate types... but in any language with nominal typing you're just killing yourself with unnecessary complexity.


apparently LSP is just a contravariant functor https://apocalisp.wordpress.com/2010/10/06/liskov-substituti...

But I don't see how the relationship of contravariant functors to OO-style subclasses is as clear as the DI <-> function abstraction example (functions are just functions in OO or FP)


The trick of that article is noting that Rúnar translates "S is a subtype of T" to "S => T", e.g. subtyping implies coercion. This is the first part of subtyping. The second part is that we must have that definitions of Q[S] for any Q must follow naturally from definitions of Q[T].

So let's say that Apple is a subtype of Fruit. That means that there exists a natural coercion function f : Apple => Fruit. It also means that if we have a predicate Delicious that we define for both Fruit and Apple then the answer Delicious[Apple] must be exactly Delicious[Fruit].comap(f). If they don't align then your coercion function is somehow wrong and not implementing subtyping properly.




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: