7

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
  • 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. Commented May 29, 2017 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. Commented May 29, 2017 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 Commented May 30, 2017 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.) Commented May 30, 2017 at 10:23

2 Answers 2

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.

6
  • 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
    Commented May 29, 2017 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. Commented May 29, 2017 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
    Commented May 29, 2017 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. Commented May 29, 2017 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
    Commented May 29, 2017 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
  • 3
    This is a great answer but it doesn't really address using DI frameworks, specifically. Commented May 29, 2017 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
    Commented May 29, 2017 at 23:10
  • @wchargin got it :) Commented May 30, 2017 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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