I have a thorough background in .NET but have been using Python and Ruby lately. I found myself pondering how to best provide dependencies to objects that need them in Ruby.
At first thought, I did not actually think DI and IoC frameworks would be required to interact with dependencies because of the leniency of dynamic languages (a la redefinition, mixins, stubs, etc). Then, however, I came across answers as to why DI/IoC frameworks are not needed in dynamic languages. The reasons provided don't sit too well with me. I'm hoping I can see an example that might clear things up.
In Why are IOC containers unnecessary with dynamic languages we see that a dependent class (non-injected), say X
, can be stubbed or mocked in a test. Sure, but that requires us to know our System Under Test
is depending on something called X
. If our System Under Test
suddenly depends on N
instead of X
, we must now remember to mock N
instead of X
. The benefit of using DI is we'd never accidentally run a test with production dependencies because we'd always be passing in mocked dependencies.
In everyone's favorite goto resource for all things DI + Ruby, LEGOs, Play-Doh, and Programming, we see an example of subclassing a System Under Test to mock dependencies. Alternatively, we can use constructor injection. Okay, so B
depends on A
. We call B.get_dependency
which provides B
with an instance of A
. But what if A
depends on N
which depends on X
? Must we call get_dependency
on each successive object in the chain?
Fabio mentions we can just use mixins/monkeypatch. So X
is mixedin to N
. But The issue is what if X
depends on A
which depends on B
? Do we just use mixins for every dependency down the chain? I see how that can work but it could get messy and confusing quickly.
Side note: Many users say DI frameworks are not needed in dynamic languages. However, Angular.JS has really benefited from implementing a pretty solid DI system. Angular is built on JavaScript, a dynamic language. Is this approach comparable to Ruby or Python?
Please keep in mind I'm not saying I want to force DI/IoC into Ruby, Python, etc.
While many think DI is not needed, I agree with you, that it's indeed needed a lot; but sometimes it gets mixed with other techniques Python provides. I suggest you to look at venusian, it may kind of verbose, but if you come from .NET you'll see the relation. In a word: venusian allows you to annotate your methods without changing their behavior. Thus, you may write venusian decorators so that your unit-testing does not get affected. Pyramid uses venusian to annotate views, for instance.