6

A while ago I was investigating dependency injection frameworks for a project I'm working on in Python (part of a full-time job, moderately large and complex). I found some projects such as dependency_injector that look interesting but many of them look somewhat abandoned. The examples from those projects make dependency injection frameworks appear to use the same amount of code (or more) than simply putting a dependency between two classes/objects in the first place.

I did some more reading and it looks like a similar situation has happened with DI frameworks in Ruby as well; it turned out to be easier to use dependencies directly than to code with some frameworks.

Is it useful to use DI frameworks in languages that dynamically typed? I know such frameworks are often used with statically typed languages such as Java or C#. What about dynamic languages like Python or Ruby?

  • 4
    Main problem is that DI frameworks usually use type information for automatic wiring. With dynamic languages, that's not available, so the user has to set up all the wiring anyway. – Sebastian Redl May 29 '17 at 17:53
  • 1
    Dependency Injection is used all the time in dynamic languages. If you take a look at Newspeak, for example, every dependency must be injected precisely because of NS's "dynamicness", since Newspeak has no static, ambient, or global state! However, DI Frameworks are much more seldom used. I know of exactly two DI Frameworks for Ruby. Both were written by the same person (a former Java developer), both were only used in a grad total of two projects (both written by that same former Java developer), and both of those projects were very quickly refactored to get rid of the DI Framework. – Jörg W Mittag May 29 '17 at 23:31
  • @JörgWMittag I was also thinking about bringing up NewSpeak. This is a bit of an aside, but object-capability languages (like NewSpeak, E, and, more and more, JavaScript) absolutely require a certain amount dependency injection. This is what forces the DI, not the "dynamicness". More relevant to the question, there are those who argue for not bothering with DI frameworks even in statically typed languages e.g. softwaremill.com/the-no-framework-scala-di-framework or youtube.com/watch?v=xPlsVVaMoB0 – Derek Elkins May 30 '17 at 6:22
  • @DerekElkins: You are right. I was referring to Newspeak specifically, where Object-Capability-Safety is implemented through its extreme dynamicness. (Really everything is a dynamic message send, so everything that you could conceivably send a message to, needs to either returned by another message send or injected.) – Jörg W Mittag May 30 '17 at 10:23
7

The main benefit of a DI framework is that it moves construction into a different language (xml, json, whatever). This enforces not mixing construction code with behavior code. It's a poor programming team that needs that, but it works.

DI doesn't require a framework. Simply not mixing these responsibilities is enough. Construction also doesn't have to be done procedurally in main. You're entitled to use every feature of the language. Creational patterns have come a long way. It's when you mix use and construction that you find yourself hard coding dependencies with no way to override.

Good defaults are extremely easy to override as needed in a language with named parameters. This makes a much bigger impact to DI then dynamic typing. DI works well in dynamic languages. Even prototypical languages can benefit. That's because DI's is more then just mechanical. It actually makes code easier to read, if you're doing it right.

I recommend everyone learn how to do DI without a framework before trying to evaluate what any one framework provides. Some are useful even when you have the skill to live without them. Some are just something else trying to convince you to become dependent on it. Use with caution.

  • 2
    "The main benefit of a DI framework is that it moves construction into a different language (xml, json, whatever)." -- This isn't really true. For a static language, one key benefit is that construction can be automated based on type, so in many cases it isn't written in any language at all. For example, using Spring I can declare a dependency simply by including it in my constructor, and the container will automatically search for an object it knows how to construct that implements the necessary interface and supply it. I'm not writing construction in any language at all; it's automatic. – Jules May 29 '17 at 21:56
  • That's not a benefit. It's a bad habit. That style litters your pojos with knowledge of dependency injection. No thank you. I can setup good overridable defaults on my own. – candied_orange May 29 '17 at 22:02
  • Why does it do that? I can still use those objects without any other framework, or even without a framework at all. It's more work to do so, because I lose the automatic configuration, but I don't see any downside to having used it in the first place. – Jules May 29 '17 at 22:08
  • You're essentially creating a new language. You can do that but now you can't advertise the job as a java job. It's a java/spring job. – candied_orange May 29 '17 at 22:11
  • While in many cases with Spring, I'd accept your point (a lot of its features require a lot of understanding to configure), for the simple case of automatically finding an appropriate object to supply to a constructor, I don't get it. It saves a single line of typing in some composition root somewhere, which could easily be produced later if necessary. It doesn't require any deep understanding of how Spring works, or any tricks on how to configure it, it just works based on the standard type system of the language itself. – Jules May 29 '17 at 22:19
4

For me DI is a best practice I use in both dynamically typed languages and statically typed languages, for the following reasons:

  1. I like my modules/functions/classes/whatever to explicitly say what they depend on, so someone can look at my module and say hmm yes this module is dependent on a validator or a db or whatever.
  2. Not using DI makes you use language-specific tricks to fake objects, variables, members in tests; sometimes these tricks work well, sometimes they give you a headache.
  3. Clean code techniques are true for any programming language
  4. If you refactor your code and extract something out if you don't do DI you will find out it's more difficult, its more difficult to use it, you have to then look inside the code to know what to override as opposed to just taking some module out and providing it the dependencies externally.
  • 3
    This is a great answer but it doesn't really address using DI frameworks, specifically. – joshin4colours May 29 '17 at 18:47
  • 2
    Please do not use code formatting to format things that are not code. In all of the places where you have used code formatting, you should use no formatting at all. – wchargin May 29 '17 at 23:10
  • @wchargin got it :) – Tomer Ben David May 30 '17 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.