Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

DI is generally used to solve one of three problems that are pretty much unique to Java:

Passing a function

Decoupling initialization from memory allocation (eg. making constructors work) (This problem is also shared by C# before 3.0 but you can kind of get around it by passing a function that does the initialization, or using an anonymous constructor in 3.0 and up)

Avoiding the FactoryFactoryFactory pattern where it's all factories all the way down which is a pattern designed to get around the constructor anti-pattern. Because constructors are somehow special and not just a function that returns a specific data-type. So in C# you'll wrap a constructor in a function so it can be passed, and in Java you'll use DI. (eg. Func<String> s = () => new string())

DI is primarily a euphemism for programming in XML or another language that sucks less than Java. Primarily it's a euphemism designed to assage the egos of Java programmers who don't want to admit you can't solve problems elegantly in Java so they move their code to other languages that interact with Java to pretend Java solves more problems than it creates.



I am not sure you understand what DI is: if you're programming to interfaces and are passing instances of an interface to a constructor, you're doing DI. You don't need a framework to do so. It's a great pattern to use in other object oriented languages, including ones that let you pass functions. The reason it's a "big deal" in C# and Java is due to these languages lack of support for mixins or multiple inheritance.

I've used DI in C++, Perl and Scala - the only difference being in these languages I didn't need a framework: I used mixins (or if mixins were not available, multiple inheritance in mixin-style) to "wire" the interfaces to implementations.

In Java I ended up either having a big class where I do all the wiring (in my current project: < https://github.com/voldemort/voldemort/blob/master/src/java/... >) or using Guice (Spring is a little too "enterprisey" to be my cup of tea). Yes it's more awkward, but it's certainly possible to write clean and readable (if more verbose) code in Java.

DI comes about as a reaction to use of static methods and more-harmful-than-useful design patterns such as singleton, which have the issue of making it more difficult to isolate specific layers of your code for unit testing.


This is not at all the definition of Dependency Injection. The wikipedia article [1] does a pretty good job of describing what it really is. DI is a pattern that is intended to reduce coupling between components in a large system. It applies to any OOP language, although it is true to say that the term first gained popularity in the "enterprise" Java world.

I also think it's wrong to conflate DI with XML. One of the first major DI frameworks, Spring, did use XML for configuring and wiring-up components, but it's also quite popular to do this part purely in the code, without any external configuration files.

[1] http://en.wikipedia.org/wiki/Dependency_injection


> This is not at all the definition of Dependency Injection.

Re-read fleitz message. He never stated what he believed DI to be but what he believes DI to be used for.

> I also think it's wrong to conflate DI with XML.

Which, again, is not what he said at all.


To be honest, I didn't really understand what he was trying to say, but I am certain that the first two problems he mentions are not what DI is intended to solve.


DI is generally used to solve one of two problems that are pretty much unique to Java:

Passing a function

If you will pardon my English: What a load of bullshit.

I'm sure it can be used for that as well (i.e. in implementing the delegation pattern, due to lack of delegates and first class functions), but saying that is what it all that is good for simply makes you look inexperienced.

For any system with a reasonable complexity you will find yourself wanting to separate your code into modules. It might be that you want to thoroughly implement SOC (seperation of concerns), it might be that you want your code to be more flexible (i.e. be able to replace a file-store with a db-store later) or simply that you realize that your system is so big, that you need to be able to work with components separately to be able to properly test your modules.

Decoupling initialization from memory allocation

First you criticise Java, then you bring up a point which (usually) is not a very big concern in garbage-collected languages.

Maybe you mean "controlling initialization" which is crucial for testable code, but given how your first point is completely off base I'm not really sure I would give you the benefit of the doubt.

DI is primarily a euphemism for programming in XML

You can implement DI without any XML. And no, for reference, I don't do Java.


I know you can implement it with out XML, I do DI all day long with functions. I just don't call it DI, I call it passing functions. When people talk about DI they're generally talking about using a DI framework. My point is that the concept is trivial enough to implement in the language itself and doesn't require a framework to help 'manage' it.

What problems can be solved with DI that can't be solved by passing a function? Or 'controlling initialization'

Allocation issues are present in GC languages because of the overhead of GC when you could just reinitialize an existing piece of memory. (You also get to keep your L1/L2 caches hot by not initializing new memory when old will do) Allocation has non-trivial costs. This is why using the methods that allow you to pass a byte[] buffer are often more efficient than those that allocate their own buffer. And we're not even getting into the fragmentation that can occur when you're rapidly allocating memory and some of that memory is locked by the OS so it can't be collected.

How is it that DI frameworks are necessary for large code bases yet most operating systems don't have DI frameworks?

When most people writing OO code have a problem, they think 'I know I'll use a DI Framework', now they have two problems.


Dependency Injection != using a DI container http://loosecouplings.blogspot.com/2011/01/dependency-inject...

DI is about passing all that is needed through parameters instead of creating it or using globals - this is completely independent from the type of arguments passed - you can pass functions or scalars or objects or whatever. Of course all that passed stuff is still needed to be created somewhere - so DI is also about having a factory of objects - it creates a lot of objects - but creation alone should be simple (and indeed frequently it can even be automated by using a DI framework).

You ask: "What problems can be solved with DI that can't be solved by passing a function?" - OK, I never thought about it from that side - but how about the problem of globals? How do you solve it by using function passing? Let's say you have a global database connection - if you modify it and pass that connection (or more frequently objects created from it) as a parameter to all code that needs it - that is DI. How function passing fits here?


I know you can implement it with out XML, I do DI all day long with functions.

Non-sequitur. Most .Net DI frameworks (as opposed to DI in Java, or DI without a framework) use configuration in code. This is generally much more readable and flexible than config in XML. Only some of them use functions for some things.


What problems can be solved with DI that can't be solved by passing a function?

Any non-trivial interface implementation will have more than one function.

Let's say I have a core library which defines lots of possible actions for my application. This application will need to work with other applications although only one at a time (in my case, trough COM), however the operations which needs to be done in these applications remain the same. Applications, not one. Operations, not one.

Obviously this calls for a common interface (in a statically typed language) so that the you can make Application-proxy classes which handles the application interaction in a similar way.

Once you have those implemented as classes you typically pass those around, for instance via the constructor when setting up your instance. Even without a DI-framework this is DI.

For this case "passing a function around" would be very impractical as you would have to pass several functions around. You would have to make sure all functions were created at the same time, with closures referencing the same application COM instances etc.

In fact, passing functions around here would make your solution more complex and error-prone with little benefit what so ever.

Don't get me wrong: I love what function-passing enables. I've written tons of code where function-passing is used to simplify the solution and make it more reusable, more elegant and generally better to work with. Being able to pass functions is awesome.

That said, function passing can be considered a primitive and it's not one which solves all problems. DI is for when your problem domain is bigger, more complex and function-passing would be you were only allowed to pass primitive objects (int,string,etc) around as opposed to sending class-instances around.

They are very, very different and if you can't see that difference, you really should step back and take another look.

Allocation issues are present in GC languages because of the overhead of GC when you could just reinitialize an existing piece of memory

Sure. But your argument that this was one of "two" reasons to use DI is most certainly false. I've never seen anyone advocate DI because of memory issues. This is simply not an argument.

How is it that DI frameworks are necessary for large code bases yet most operating systems don't have DI frameworks?

Because you don't need a DI-framework to implement DI in your code. If you think DI needs "frameworks", you are obviously missing the core point about it: It's a way to structure your code.


Totally agree with you re: DI as a way to structure your code.

I tend to start with function passing and yeah, when it gets to 5 functions you start putting them in a class or other structure that allows you to pass them as a unit. I like using tuples to pass gobs functions because it works better with type-inference in F#

I've just never heard it referred to as DI except in OO (Java) circles.


> First you criticise Java, then you bring up a point which (usually) is not a very big concern in garbage-collected languages.

Of course it is for a number of reasons (instance sharing or reusing, caches, registries, ...), and most GC'd languages (significantly, not Java or C#) give separate access to these two operations (allocating an instance and initializing it).

See Ruby (new/initialize), Python (__new__/__init__), Obj-C (alloc, init), etc...


Great point. This presentation showed how easy it can be to implement DI in ruby: http://onestepback.org/articles/depinj/index.html

Dynamic languages don't suffer many of the overheads with using DI. So do those with Mixins (see the Scala's Cake pattern for more on this http://jonasboner.com/2008/10/06/real-world-scala-dependency...)

This blog post says more about it: http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-pro....




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

Search: