Any need for dependency injection in Dynamic Languages?
Asked Answered
B

4

12

In order to write testable C# code, I use DI heavily.

However lately I've been messing around with IronPython and found that as you can mock any methods/classes/functions etc... you like, the need for DI is gone.

Is this the case for dynamic langagues such as Python?

Instead of:

class Person(Address) {
...

You can have:

class Person() {
...
    // Address initialised in here.

For dynamic languages and therefore following manaual DI for dynamic langagues is simply not needed.

Any advice on this?

Bisulcate answered 24/12, 2009 at 0:43 Comment(1)
This seems to be a duplicate of the question .. #2274183Stakhanovism
S
10

Dependency Injection is also about how you wire things together --- which has nothing to do about the mockability of depended-on objects. There's a difference between having a Foo-instance that needs a Bar-connection of some kind instantiate it directly and having it completely ignore how it gets that connection as long as it has it.

If you use dependency injection you also gain better testability. But the converse isn't true. Easier testability by being able to overwrite anything doesn't bring the other advantages of dependency injection. There are many component/DI-frameworks for Python available exactly for these reasons.

Showmanship answered 24/12, 2009 at 1:2 Comment(1)
What are "the other advantages" of dependency injection?Ensconce
D
10

I strongly disagree with your statement that Dependency Injection is not needed in dynamically typed languages. The reasons for why DI is useful and necessary are completely independent of the typing discipline of the language.

The main difference is that DI in dynamically typed languages is easy and painless: you don't need a heavyweight framework and a gazillion lines of XML configuration.

In Ruby, for example, there are only two DI frameworks. Both were written by a Java programmer. Neither of the two frameworks is used by a single project. Not even by the author of those frameworks.

However, DI is used all over the place in Ruby.

Jamis Buck, who is the author of both of those frameworks gave a talk called Recovering from Enterprise at RubyConf 2008 about how and why he wrote those frameworks and why that was a bad idea, which is well worth watching. There’s also an accompanying blog post if you’d like to read. (Just substitute “Python” everytime he says “Ruby” and everything will be just as valid.)

Dejesus answered 24/12, 2009 at 1:24 Comment(5)
Isn't "gazillion" an exaggeration? I use DI heavily in C# and I use very little, if any, XML configuration.Collazo
Yes, it most definitely is an exaggeration. It's also an outdated exaggeration, since post-.NET2 and post-Java5 DI frameworks tend to use attributes/annotations instead of XML. The basic idea is this: wiring things up dynamically in Java or C# is hard. That's why it makes sense to use a DI framework: I don't care about parsing XML or processing annotations/attributes, so I let someone else do the work, who enjoys that kind of stuff. But in Python or Ruby, everything is always wired up dynamically, anyway. The language itself is already a DI framework. No need to put another one on top.Edelsten
Another way to think about it: what does a DI framework do? It glues independent components together. And what do we usually call gluing independent components together? Scripting! And how does it determine what to do? It reads an XML file or a set of annotations. And what do we usually call a set of instructions that tell how to glue things together? A script! And the thing that executes those instructions is a script interpreter. So, a DI framework is just an interpreter for a (usually pretty crappy, especially when using XML) scripting language. But in Python we already have that: Python!Edelsten
No XML in my Ninject / StructureMap and other IOC Containers... Sorry but with modern development in .NET MVC3 / MVC4 it is super simple. XML yuck, the 90's called and want their XML code back ( I exaggerate, but I do zero XML configuration with Ninject and Structurmap ). But yes, you are right in the OP question on doing DI with Dynamic Languages is a good practice.Fiedler
"main difference is that DI in dynamically typed languages is easy and painless: you don't need a heavyweight framework" You don't need a framework in statically typed language either. DI is a more general concept than ioc containers (which it'd seem what you had in mind).Dinsmore
V
0

I'll try again. My last answer missed the question by a mile and zoomed way off topic.

Using pseudo-code, dependency Injection says out with:

class Person
  def Chat() { 
    someOperation("X","Y","Z")
  end
end
...
Person.new().Chat()

and in with:

class Person
  initialize(a,b,c)
    @a=a
    @b=b
    @c=c
  end
  def Chat()
    someOperation(@a,@b,@c)
  end
end
...
Person.new("X","Y","Z").Chat()

,., and generally in with putting the object and the call into different files for SCM purposes.

Whether "X", "Y" or "Z" are mockable (...if they were instead objects...(!)...(!)...) have nothing at all to do with whether DI is good. Really. :-)

DI is just easier in Python or Ruby, like a lot of other tasks, because there's more of a scripting approach, like Jörg says; and also of course less of a culture and a tendency saying that constants and adapters are to get populated into models and global constants.

In practical terms for me DI is the first step towards separating out those application parameters, API constants and factories into separate files to help make your revision tracking report look less spaghetti-like ("Were those extra checkins on the AppController to change the configuration..? Or to update the code...?") and more informing, and more easy to read.

My recommendation: Keep using DI... :-)

Viable answered 27/12, 2009 at 20:39 Comment(0)
V
-2

I think you're presenting a question that seems to be about best practice but is actually about run-time performance.

Get rid of dependency injection? How can a software release manager sleep at night?

The tests for function to perform must surely slow the program down one or two tads.

// my generic function entry point - IronPython
if func="a":
  ...
if func="b":
  ...
if func="c":
  ...

You can use standard Python with classes... or you can assign function pointers to function pointer members. Just what kind of a beast is it...?? I know, I know. Python I think is difficult to define but I like it. And I like and think highly of dependency injection, not that I've had long where I'd think to assign such a lengthy name to the practice.

Viable answered 24/12, 2009 at 1:12 Comment(1)
Reading this left me confused.Paradiddle

© 2022 - 2024 — McMap. All rights reserved.