Talk:Dependency injection

From Wikipedia, the free encyclopedia
Jump to: navigation, search
WikiProject Computing / Software (Rated Start-class, Mid-importance)
WikiProject icon This article is within the scope of WikiProject Computing, a collaborative effort to improve the coverage of computers, computing, and information technology on Wikipedia. If you would like to participate, please visit the project page, where you can join the discussion and see a list of open tasks.
Start-Class article Start  This article has been rated as Start-Class on the project's quality scale.
 Mid  This article has been rated as Mid-importance on the project's importance scale.
Taskforce icon
This article is supported by WikiProject Software (marked as Mid-importance).
 

Links[edit]

Sans-serif font confused me[edit]

Since loC (L) and IoC (i) were confusing readers, I changed all "IoC" to "IOC" as people suggested here. Ramiro Pereira de Magalhães (talk) 22:50, 8 January 2009 (UTC)


Introduction too short[edit]

"the lead section should briefly summarize the most important points covered in an article in such a way that it can stand on its own as a concise version of the article" (WP:LEAD) --the Wild Falcon (talk | log) 13:13, 3 October 2007 (UTC)

==========================[edit]

Maybe explain through concrete example such as: "Imagine you wanted to get a driver license. You go to the appropriate office and a sign is on the door that says you must have a social security card and $20 fee to get your driver license. The sign does not prevent you from getting the drivers license, but only lists dependencies or requirements. Similar to the sign, dependency injection is external code that wraps the code doing the action. This external wrapper code requires that one pass the dependencies as parameters to it." - Oct 2012 - Eric Bonner Wood. — Preceding unsigned comment added by 74.203.253.36 (talk) 14:31, 7 August 2012 (UTC)

Delete this article[edit]

This article needs to be deleted along with Inversion of Control. Both are red herrings. Dependency injection = usage of callbacks and IoC = abstraction layer. For some unknown reason Martin Fowler and others in the software obfuscation industry have decided to rename concepts which already have perfectly good names. Wikipedia doesn't have to stand for this nonsense. Just because Martin Fowler and a few others sucking at the teat of Enterprise prefer Java to C doesn't mean Wikipedia has to follow his lead. Mistercupcake (talk) 07:31, 29 December 2007 (UTC)

The Martin Fowler article on this subject is highly dubious. He is trying to draw similarities between different frameworks, but the fact is that the frameworks really are essentially different. In fact the only thing you can say is that the frameworks use observer patterns and perhaps some data-directed configuration. Fowler and a few of his flunkies seem intent on slathering this admittedly powerful combination with vast amounts of pomo-esque hype... This is why software developers have a bad reputation amongst some clear-thinking individuals! DON'T BELIEVE THE HYPE!!! Remember: patterns are only good if they help you communicate with other developers. This is why they exist. Don't describe your work using patterns that are too fuzzy for their own good. Mistercupcake (talk) 07:23, 19 April 2008 (UTC)

I disagree with that observation. Dependency injection is about having an object being supplied with whatever dependencies it needs by an assembler. The responsability of invoking the injected behavior is still on the first object.
Inversion of Control may be seen as usage of callbacks. I mean, you use IOC when you define some behavior and tell a certain framework to invoke it when the time is right.
Fowler says that DI is an specific form of IOC. IMO, you can say that if you're talking about the container that does the injection for you. It seems to me that, from a framework user's point of view, Dependency Injection is a pattern used when you want to set up your objects graph, while Inversion of Control is used when you want some behavior invoked in response to a certain event.Ramiro Pereira de Magalhães (talk) 04:25, 30 December 2008 (UTC)
Yet the example given in the article simply exhibits one bad implementation of abstraction (using an interface, but the class using it needs to know about the details of that interface)--and then as the "good" example, displays what people have been (correctly) doing with interfaces for the last decade (or two). I'm having a very hard time seeing how IOC/DI isn't abstraction, but renamed and re-attributed. And the presented example is absurd, in my opinion, because it is misusing the concept of an interface (why bother using an interface if the class is simply going to create a specific implementation? It's silly) and then presenting the "fix" (i.e. the way most of the world prefers to use interfaces) as some new concept.
If DI is about "having an object being supplied with whatever dependencies it needs by an assembler" then let's get an example that shows whatever that is. But the current example is re-purposed "Interfaces for Dummies," except now attributed to Fowler, and I agree with Mistercupcake that something is rotten about this article. Jnoring (talk) 01:51, 14 February 2009 (UTC)
Yes, I've been thinking about the example for some time and never wrote something. At last, I wrote something that represents better what DI really is. It still needs some explanation about it, but I'll write it latter. See it below. Ramiro Pereira de Magalhães (talk) 14:04, 16 February 2009 (UTC)
Mistercupcake, do you think DI is just usage of callbacks? If so you don't understand. Daniel.Cardenas (talk) 02:30, 12 December 2010 (UTC)

Mistercupcake's opinions, and the opinions in response, are irrelevant; Wikipedia doesn't work that way. -- 98.108.225.155 (talk) 07:35, 10 December 2010 (UTC)

Criticism[edit]

DI has been generaly accepted as something great, but there are some criticism that are quite valid to this practice. I believe that a good article about the subject must take in consideration "the dark side" of DI. Refer to this blog post and this other blog post for more detais on this subject.Ramiro Pereira de Magalhães (talk) 17:24, 4 April 2008 (UTC)

Could you enumerate the criticisms you see presented in these articles? The first article seems more a discussion of DI as it relates to Architecture Description Languages, but I didn't see any clear criticisms set forth. The second article is actually a pro-DI article which addresses someone's assertion that DI increases coupling. While this could result if the responsibility of resolving dependencies were assigned to each component's consumer, this is not a typical use of dependency injection and therefore isn't really a legitimate criticism. The only real criticism I see with the use of DI is increased complexity, but this is true of many patterns.--Derekgreer (talk) 21:13, 4 January 2009 (UTC)
Sorry, I misquoted the first blog post. It is correct now. I'll work on enumerating those criticisms when I get time since many interesting parts are in the comments made by those blogs readers and in the links inside the blog post. Ramiro Pereira de Magalhães (talk) 14:46, 11 January 2009 (UTC)

Problems with the term "Dependency Injection" and "Inversion of Control"[edit]

"Dependency Injection" is a vague description the practice it refers to. That practice is to externalize connections between components either in a specific third component or by using a configuration file to direct a general configuration component to do it. Injecting the dependency is only a part of the process.

"Inversion of control" as described in that article and elsewhere is clearly a misnomer. If class X depends on class Y then inserting the interface I such that X depends on I and Y implements I, is no inversion. To qualify as inversion Y would have to depend on X, not I. Precision-nazi 09:24, 6 August 2006 (UTC)

You have to consider what is being inverted. The practice of inverting the dependency relationship between X and Y is a technique described by the Dependency Inversion Principle. With Dependency Injection, what is being inverted is the responsibility (i.e. the control) of instantiating dependencies.--Derekgreer (talk) 20:21, 4 January 2009 (UTC)

It seems that Setter, Constructor and Interface under the list of styles should be more precise about where they point. Setter currently points to the dog, whereas Constructor and Interface point to disambiguation pages; they should all point specifically to pages about the styles of dependency injection. --134.173.86.14 06:37, 24 January 2007 (UTC)

The obvious question about the term "dependency injection" is "what is being injected?" When I first heard the term I thought it meant that there were some kind of software objects called "dependencies" and that they were being injected into something. Now I suspect that it is OOP objects that are being injected and that the meaning is really "dependency-driven injection." I have no problem with the article being titled "dependency injection" but would like an explicit statement as to what is being injected. It also wouldn't hurt to give an example of a dependency. The article mentions loading a driver and probably this is an example - the method depends on a driver to work - but this should be made explicit. Gene.Naden (talk) 01:35, 14 December 2010 (UTC)

Needs more pictures[edit]

To be easier to understand especially for users who may have hit this page just exploring software-articles, it would be good to have a couple diagrams that conceptually represent what is going on. There are various diagrams which could help to illustrate including UML. Also a dependency diagram may not be able to show the differences in design and coupling, but might stand as useful to clarify the problem-statement. The wording in this article I think is clunky by nature of the fact that software patterns (muchless largescale software development, muchless computing, muchless personal computing) are a relatively new thing, therefore I think before folks are willing to slog through an article like this one to gain some comprehension of the subject, they might want a visual aid to get the gears turning. Koyae (talk) 03:50, 27 November 2012 (UTC)

Merging with Dependency inversion principle[edit]

The Dependency inversion principle barely manage to define its concept, and if fails to differentiate itself from Inversion of Control and Dependency injection, mudding these already unclear pages. Since the goal of dependency injection is to follow the dependency inversion principle, I suggest to merge both and achieve a stronger article, instead of two weak ones. Diego (talk) 08:54, 10 June 2008 (UTC)

Thinking about it, Dependency injection and the Dependency inversion principle are different enough concepts to have different articles for them (the first is a technique, the second is an guideline to apply it). What is really needed is a rationale explaining how these concepts relate to each other and to Inversion of control. Diego (talk) 15:02, 12 June 2008 (UTC)
Just based on the fact that the contents of Dependency inversion principle article contains so little content, it shouldn't be on it's own. If at some point it becomes a distraction to the point of the Dependency injection article (not that I think it would), it could be split. —Preceding unsigned comment added by 12.21.236.10 (talk) 12:47, 19 June 2008 (UTC)
Yes, that was my idea in proposing the merger. But how do you address the problem of having to related (but different) concepts and emphasize that difference, when both are in the same article? Diego (talk) 13:53, 19 June 2008 (UTC)
While the Dependency inversion principle page may very well be anemic at this point, this principle does indeed describe something very different from Dependency injection. The Dependency Inversion Principle is primarily about having lower-level components depend upon higher level components rather than the conventional dependency relationship. The prescribed methodology by Robert Martin is to package a higher-level component together with an interface which defines the external behavior/services it needs. An external dependency in a separate package then implements the interface of the higher-level component, thus taking on the higher-level package as a dependency of itself. Once this decoupling has been achieved, some facility has to be used to enable the higher-level component to obtain an implementation of its interface. Dependency injection is one technique for facilitating this, but it isn't the only one. Another method would be use of the Plugin pattern (PoEAA), or Service Locator. Dependency injection is about externalizing the provisioning of dependencies and need not necessarily even involve the use of abstractions. It certainly isn't concerned with the dependency relationships between higher-level and lower-level components. I believe that combining these too topics together is detrimental to the clear understanding of each. My suggestion would be to supply a more robust description of the Dependency Inversion Principle and keep this article purely about Dependency injection. - Derek

I agree with Derek and, since Diego changed his mind about merging and no one has posted any new comments since June 2008, I'm removing the merge proposal announcement from the article.Ramiro Pereira de Magalhães (talk) 22:43, 10 January 2009 (UTC)

Example code is verbose and does not explain anything[edit]

The section "A code illustration using Java" is waaay too long and only gets to the point in the very last sentence. However, a concrete example of DI is lacking. ThomasTenCate (talk) 04:23, 25 September 2008 (UTC)

I agree with that, but it's the most readable and understandable example and at least it's a little funny. I think we should leave it and modify the rest of the examples to be more "real-life-ish." —Preceding unsigned comment added by 74.238.168.219 (talk) 16:53, 14 January 2009 (UTC)

I'm proposing the code below to replace the present example code. I believe that, with adequate explanation it will work better to show what dependency injection is about. For more explanation, read it above. Ramiro Pereira de Magalhães (talk) 14:20, 16 February 2009 (UTC)

Notice: a new example has already been added. The one shown below is still there just to work as a context to the discussion. —Preceding unsigned comment added by Ramiromagalhaes (talkcontribs) 15:55, 11 July 2009 (UTC)
public interface ComponentInterface {
 
	public void doComponentStuff();
 
}
 
public class ComponentImplementation implements ComponentInterface {
 
	public void doComponentStuff() {
		Dependency dependency = new Dependency();
		dependency.doDependencyStuff();
	}
 
}
 
public class ComponentImplementationWithDependencyInjected implements ComponentInterface {
 
	private Dependency dependency;
 
	public void doComponentStuff() {
		getDependency().doDependencyStuff();
	}
 
	public void setDependency(Dependency d) {
		this.dependency = d;
	}
 
	private Dependency getDependency() {
		return dependency;
	}
 
}
 
public class ComponentFactory {
 
	public ComponentInterface createComponent() {
		ComponentImplementationWithDependencyInjected component =
			new ComponentImplementationWithDependencyInjected();
		component.setDependency( new Dependency() );
		return component;
	}
 
}
I still don't think this illustrates any sort of principle that hasn't already been clearly established (e.g. Abstraction/Polymorphism) In your example, the Dependency class could either be an interface or some base-class, but in either scenario this is simply "abstraction" and not some new principle all together. Why does passing in an interface or base class (which people have been doing for a long, long, long time) suddenly being renamed and re attributed? How is this any different from what Stroustrup covers in his FAQ here: http://www.research.att.com/~bs/bs_faq.html#oop ??? (and in particular, "The key point here is that f() doesn't need to know which kind of driver it uses; all it needs to know is that it is passed a Driver; that is, an interface to many different kinds of drivers.")
Maybe I'm missing something or I've misunderstood the example, but I am still really struggling to see how this is A) a genuinely new idea and not the same OO principles that have been espoused for decades, and B) something that should be attributed to Fowler. Jnoring (talk) 22:13, 16 February 2009 (UTC)
Those principles you mentioned are in fact important OO concepts. They are the building blocks to more sofisticated techniques or object arrangements like design patterns. Dependency Injection is nothing more than a name that we can use to refer to a specific arrangement that has a defined purpose, like any other design pattern. If I am not wrong, the GoF book says that a design pattern is not a "new idea", but is a solution commonly used to solve a certain problem. So, Fowler should only get the credits for creating the name "Dependency Injection" not to the pattern itself.
Now, about the technique, I think you're focusing too much on the strategy side of it, I mean, the capability this pattern gives you to change the implementation without changing the interface. In fact, this is vital to the pattern, but - in my opinion - what matters most is the removal of the instantiation of the dependency from the dependent class. Such actions become part of a third component that does its job as on the example above, or as in the Stroustrup article you mentioned, or by reading some configuration file. By doing this, the component can provide its services once it has its dependencies resolved by whatever means are available. Notice this component's client does not need to have access to the component's methods that are used to solve the dependencies (such as constructors or setters as in the example above) Ramiro Pereira de Magalhães (talk) 02:41, 21 February 2009 (UTC).
I don't agree. If the "capability" this pattern gives is it allows changing the implementation without changing the interface, then _it is nothing new_. Clearly this is the case, given Stroustrup's example: this is how you are _supposed_ to use an interface. And if fowler should only get the credits for creating the name "DI," but not the pattern itself....doesn't that imply he doesn't deserve any credit? I'm sorry but this whole article is ridiculous, and Fowler's paper consists of a strawman, followed up by pointing out the obvious. Jnoring (talk) 02:34, 26 February 2009 (UTC)
I think you did not read my post with attention, so I ask you to please read it, including the references I posted. I also recomend reading the book I mentioned so that a design pattern identification does not sound that weird to you.
But I agree that the article is not explaining DI very well. The problem is not just the example. I could explain to you what I think about it, but it would be easier to just fix the article. I'll try to do that when I have time.Ramiro Pereira de Magalhães (talk) 15:33, 1 March 2009 (UTC)
Well, at last I got time a little to change the article. It still needs a lot of improvements, though. An important step I must take is to find where did I get those informations from, so we can give it some good citations.Ramiro Pereira de Magalhães (talk) 05:28, 21 June 2009 (UTC)
As I see it, the main capability allowed by Dependency Injection is allowing to change (extend) the definition of an object without having to recompile everything using that object. This is a proper subset of all cases where an interface of the object is passed as a parameter (i.e. there are cases in which you pass an interface as a parameter, and you still have to recompile classes using the interface - those wouldn't use DI). Diego (talk) 14:56, 27 February 2009 (UTC)
Yeah, this sure is one important capability which is enabled by the fact that the class which is responsible to inject the dependencies is not the component itself, but a third party. This third party, this "injector" is the one who is responsible for that capability and it is where, I think, we should focus our attention in this article.Ramiro Pereira de Magalhães (talk) 15:33, 1 March 2009 (UTC)

Another problem I see with the example is the 'straw man' set up in explanation of the non-DI code - "As shown, the Car class needs to create an instance of an Engine ... such an approach still forces the Car class to know how to instantiate its own Engine." But this is not 'forced', and the implication that this is the only way to remove the simple-minded dependency is false. We should be comparing DI to other ways of avoiding this dependency, and the fact that the example implies there aren't any makes it weak. For instance, just what makes this better than a call to a factory that provides the engine? —Preceding unsigned comment added by 204.152.2.82 (talk) 13:52, 14 October 2009 (UTC)

Biggest problem I have with the current example is use of double for money. Use this code and Richard Pryor (or that stapler guy from office space) is going to show up in your parking space with a hot-rod he bought after embezzling all the half penny's you lost the company. If outdated movie references aren't enough proof for you, read this Galhalee (talk) 10:27, 13 March 2014 (UTC)

Yet another example[edit]

I think the example mentioned above is as bad as the one currently in the article. An example explains an abstract idea in a concrete form. Then why on earth make the example abstract? Both examples also use horrible naming schemes. Either the names are nonsense, or the names are waaay to long. Long verbose names are a good thing in general, but it can be pushed over the edge (e.g. ComponentImplementationWithDependencyInjected - I just read blahblahblah).

So here is a better way to put forward an example (in my opinion, I welcome discussion):

Suppose, for example, you are asked to write the software for the next killer application: a blinking LED. Your algorithm will need some external assumptions: you must be able to switch the LED on and off, and you must be able to wait an amount of time.

Following the principle of dependancy injection (using interface injection in this simple example), you define these dependancies as an interface:

void led_on();
void led_off();
void wait_ms(unsigned ms);

This is all it takes to start implementing the main algorithm:

void blinking_led(unsigned period_ms)
{
	unsigned half_period = period_ms / 2;
	while(true)
	{
		led_on();
		wait_ms(half_period);
		led_off();
		wait_ms(half_period);
	}
}

The only thing that remains to be done is to find out how you accomplish the goals defined in the interface. You could access the hardware directly, use a driver and operating system calls, send it over a network using a field bus, or make it interface a GUI, but basically the meme here is "I don't care". Here is an example implementation having nothing to do with LED's:

void led_on()
{
	puts("ON");
}
 
void led_off()
{
	puts("OFF");
}
 
void wait_ms(unsigned ms)
{
 
	while(ms)
	{
		puts(".");
		ms = ms - 1;
	}
}

I hope everyone agrees that if you compare this example to the ones mentioned up till now, this is much more understandable. It is written on purpose to make it as readable as possible (e.g., I could have written while(ms--) but there's no need to), and the concept can be explained in seconds without making your head explode.

Right now, I think both examples are bad by the same reason: they do not really explain DI. They only explain polymorphism. Ramiro Pereira de Magalhães (talk) 05:14, 21 June 2009 (UTC)

Also, the discussion over wether this really is a principle or just another form of higher order functions, lambdas, abstraction etc. is sound in my opinion, but seeing how few people grasp this basic idea, I always welcome emphasis on this way of thinking. So, yes, they are manifestations of the same idea, but worth mentioning nevertheless. Hansvi (talk) 21:45, 20 May 2009 (UTC)

Similarities to lambdas, etc[edit]

First of all, the example is hilarious, but probably obstructive (the factory class is great). Second, if I grok the concept correctly, doesn't this warrant a link to Higher-order_function? In essence, standard folds and maps could be considered the simplest instances of dependency injection?

eg, a standard map, map f (x:xs) = (f x):(map f xs) (In Haskell syntax, omitting the base case), takes as input a function that provides some sort of service, and runs it, as long as its types matches up (eg it matches the correct interface). Am I wrong?

As far as I can tell, dependency injection is used to prepare an executable object with some external parameter, and leave it ready for later execution. If map and fold were examples of DI, then every higher order function would be; in my opinion they aren't, because the provided function is consumed at once and doesn't give an object prepared for execution.
Currying and closures, OTOH, do consume an external parameter and return a function that can be executed later. So maybe they are better examples of dependency injection in a functional paradigm. Diego (talk) 22:27, 5 November 2008 (UTC)
IMHO, those concepts are quite different because DI was created to solve problems in Object Oriented systems. It is not an abstract concept that is able to embrace something like Higher-order function.Ramiro Pereira de Magalhães (talk) 15:13, 11 July 2009 (UTC)

DI Frameworks Features Comparison[edit]

I think we should improve the DI Frameworks list so that it compares on DI framework with each other. Of course, we should first find a set of features that DI frameworks may have, and probably define them in the article too. I propose that anyone who has something to add, put it in the list below (or just write about it in the article). Ramiro Pereira de Magalhães (talk) 15:51, 20 July 2009 (UTC)

  • Transitive dependency resolution
  • Circular dependency detection and handling
  • Callback hooks for handling the objects lifecycle events
  • Dinamic Proxy creation
  • Configuration file based dependency configuration
  • Programatic dependency configuration —Preceding unsigned comment added by Ramiromagalhaes (talkcontribs) 03:42, 10 August 2009 (UTC)
  • Type of injection method (interface, setter, constructor) --coldacid (talk|contrib) 20:37, 17 September 2009 (UTC)

Jargon in lede[edit]

I find the lede of this article to be vague and esoteric to the point of being meaningless. It is composed almost entirely of words that can have a dozen different meanings in different contexts, such as "dependency", "external interface", and "software component".

Fowler's own article has a much clearer single-sentence description of the topic:

The basic idea of the Dependency Injection is to have a separate object, an assembler, that populates a field in the lister class with an appropriate implementation for the finder interface, resulting in a dependency diagram along the lines of Figure 2.

To me, this description (aside from the overly specific example classes "lister" and "finder") is a much clearer one-sentence introduction for those uninitiated in the latest and greatest in software engineering pontification. Can we base our lede on this instead? --Doradus (talk) 02:20, 18 January 2010 (UTC)

So you don't think that "object", "assembler", "field" and "lister class" are jargon? The purpose of the first sentence is not to provide a precise definition (which can be done later) but introducing a feeling of the subject ("an accessible overview") to the general reader - that including people without knowledge of OOP.
I have no problem with the words being vague (disclaimer: I wrote the current version of the lead paragraph), among other reasons because it allows for *different * implementations of DI other than the one described by Fowler (which is not necessarily the only one) - but mainly because "dependency" and "software component" are quite self-explaining even for non programmers.
If you find Fowler's definition clearer, you can add it later in the lead section for the benefit of readers who already know OOP. Diego (talk) 09:52, 18 January 2010 (UTC)
Good points indeed. Now I'm not sure what to do. I still find our lede puzzling but I'm not sure how to improve it. --Doradus (talk) 17:38, 22 January 2010 (UTC)

Framework based DI Code Example[edit]

I highly discourage anybody from using hard coded strings in-line. The example in the last section of the page would be better if we added an static class to it that contains the strings:

//static class provided by the framework or written by the user to indicate which dependencies are available
public static class MyAvailableServices{
    public static final string CarBuilderService = "CarBuilderService";
    public static final string VanBuilderService = "VanBuilderService";
}

public class MyApplication {
    public static void main(String[] args) {
        Service service = (Service)DependencyManager.get(MyAvailableServices.CarBuilderService);
        Car car = (Car)service.getService(Car.class);
        car.setPedalPressure(5);
        float speed = car.getSpeedInMPH();
    }
}

Making things explicit[edit]

(1) The obvious question about the term "dependency injection" is "what is being injected?" When I first heard the term I thought it meant that there were some kind of software objects called "dependencies" and that they were being injected into something. Now I suspect that it is OOP objects that are being injected and that the meaning is really "dependency-driven injection." I have no problem with the article being titled "dependency injection" but would like an explicit statement as to what is being injected. It also wouldn't hurt to give a software example of a dependency. The article mentions loading a driver and probably this is an example - the method depends on a driver to work - but this should be made explicit. (The example of the engine in a car is pretty helpful but an example in the realm of software - not too exotic - would also be helpful.) (2) THe article states "Dependency injection is a specific form of inversion of control where the concern being inverted is the process of obtaining the needed dependency. The term was first coined by Martin Fowler to describe the mechanism more clearly.[1]"

The word "dependency" in common usage refers to a relationship rather than an object. For example, "my code depends on driver x" means that there is a dependency of my code on the driver. "Dependency" in this case does not refer to my code, nor does it refer to driver x. Rather it refers (as I have said) to the relationship between my code and the driver.

The statement quoted above ("Dependency injection is a specific form...") contains the phrase "obtaining the needed dependency". Presumably this means obtaining the dependent object (the driver). But, not being an expert, I do not know for sure that this is what is meant. Does "obtaining the needed dependency" mean "obtaining the object on which the code depends?" If so then this should be stated. Gene.Naden (talk) 02:05, 14 December 2010 (UTC) — Preceding unsigned comment added by Gene.Naden (talkcontribs) 01:54, 14 December 2010 (UTC)

Major rewrite (mea culpa)[edit]

The page seems to have been idle for a while, and I found the original article to be quite unhelpful. Surprising, since I am a professional working in an environment where dependency injection is used routinely.

The page was rewritten with the following objectives in mind: define the pattern right up front in the introduction; try to move toward more concrete definitions and terminology; feature the importance of dependency injection in unit testing more prominently.

The use of concrete objects (Cars and Engines) in code examples is also -- I think -- very poor practice. Sorry. There are no "Cars" or "Engines" in real software development. It's an abuse of the "object" in object-oriented programming. So I rewrote that too.

Remaining things to do that would make a useful addition to the page: discussion of popular dependency injection frameworks (e.g. Spring, or MEF) would be useful. Maybe even a attempt at compilation of major and minor dependency injection frameworks.

The discussion of advantages and disadvantages needs a complete rewrite as well. Previous postings in the talk page would make a good starting point. Edrowland (talk) 22:41, 16 November 2011 (UTC)

Error/Typo in Example Code: The Interface "IAutomatedStockTrader" should declare the method "executeTrades()" and not "makeTrades()". BTW, thanks for the much clearer rewrite. --77.188.70.229 (talk) 13:28, 19 November 2011 (UTC)
Are the following four lines correct? I know it is a conceptual example, but conceptually it seems you should be registering an object with the dependency manager rather than two types.
DependencyManager.register(
  typeof(IOnlineBrokerageService),
  typeof(MockBrokerageService));
DependencyManager.register(
  typeof(IStockAnalysisService),
  typeof(MockAnalysisService));

75.87.186.225 (talk) 21:35, 12 July 2012 (UTC)

In Java, there is no typeof keyword or operator or standard API method. I don't know the specific signature of DependencyManager.register, but probably typeof(IOnlineBrokerageService) should be replaced by IOnlineBrokerageService.class, as should be in the whole article as long as the code examples are supposed to be Java. --Leo141 (talk) 09:10, 16 July 2012 (UTC)


Sorry for not knowing the markup. I was looking at this today in the context of Ruby. Dynamic, duck-typed languages do benefit from dependency injection. The term most recently has been popularized in the Ruby community by Sandi Metz.
However, DI in a dynamic language is a very different beast than in a statically typed language. Most particularly, it's really dangerous to provide a Java example without an example in a language like Ruby. Jamis Buck, a well know figure in the Ruby community, chronicled his experience writing two DI frameworks in Ruby. His conclusion was that DI frameworks are not appropriate for Ruby specifically, nor other dynamic languages generally. His article can be found at http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming — Preceding unsigned comment added by Hamannp (talkcontribs) 02:08, 25 October 2012 (UTC)

Don't double your money[edit]

Biggest problem I have with the current example is the use of double for money. Use this code and Richard Pryor (or that stapler guy from Office Space) is going to show up in your parking space with a hot-rod he bought after embezzling all the half penny's you lost the company. If outdated movie references aren't enough proof for you, read this. Seriously, don't teach people to do that. IEEE floating point numbers are for scientists, not accountants. Galhalee (talk) 10:27, 13 March 2014 (UTC)

DI vs Strategy Pattern[edit]

Can someone explain how DI is different then strategy pattern? — Preceding unsigned comment added by 198.208.251.23 (talk) 15:57, 26 September 2013 (UTC)

Rather than as some help desk conversation, please think of the answer to this question as a proposed section to the article and comment appropriately. The main point is the need to correct the current Motivation section. Galhalee (talk) 20:03, 15 March 2014 (UTC)


Using DI or the Strategy Pattern could actually end up with exactly the same code. The difference is intent. They both get you to separate and remove knowledge of an implementation from the client.


However, if you only have one implementation then when your peer reviewer asks why you're doing this your answer better not be the strategy pattern or she'll rightly beat you with the YAGNI stick. The point of strategy is the polymorphic power to swap out implementations, even at run time (something inheritance can't do). For that to work you'd need at least two implementations that implement the same interface.


DI has you do the same thing (the separation) for a different reason. Despite what the current Motivation section says, it's about the dependency inversion principle (Why do we have to tell this Foo thing what to be?), also single responsibility principle (hey, we just use Foo, building Foo is not our thing), loose coupling (we don't really want to know what Foo is anyway), substitution (we don't care if it's not a Foo so long as the way we talk to it doesn't change), reuseability (OK, so Foo is outta style, but we still rock), and creating a separation layer such as needed between business logic and data access layer (SQL, noSQL, we don't care, just save this somewhere already). It means the client never ever mentions Foo. IFoo maybe but not IFoo f = new Foo(); either. In fact, the new key word starts to get scarce.


Actually, who said you could call the interface IFoo? We're the client, we own the interface. Stop filling it up with methods we don't use. Foo and Foo's friends can play with other methods but we don't want to know about them. Here Foo, implement HowWeTalkToAnyFooishThing and don't go screwing with it without letting us know first.


If your constructor looks like this:
ClientClass() {
    this.foo = new Foo();
}


DI asks you to make it look like this:
ClientClass(HowWeTalkToAnyFooishThing fooishThing) {
    this.fooishThing = fooishThing;
}


That's the constructor style of DI. Use a setter instead or mention that setter in an interface the client implements and you get the other two styles of DI.


This is more then just DI I'm preaching here. This is SOLID. What we've done is simple. It's why we did it that is tough to explain.


When defending DI all you have to tell you're peer reviewer is that you don't want to depend on concrete implementations or be responsible for constructing them. You want to talk to those things through interfaces and you want something to just hand you a reference to them. Getting handed a reference IS dependency injection. The something could be a framework like spring, a factory (that builds you too), or just main(). The point of clean DI is that even this decision doesn't impact the client. Unlike Strategy, that makes sense even if right now you only have one concrete implementation.


The reason it makes sense is the same reason we use plugs and outlets in our homes. Sure, you could solder the wires in your toasters power cord directly into your house's wiring. But when the toaster breaks it's going to be a pain to fix. And whoever heard of a house that comes with a toaster?


Plugs and outlets are nice but they're expensive. When crossing an important boundary like your dry wall you definitely want them. But you'd probably fire an electrician who used them in every junction box (supposed to use wire nuts for those). Similarly, you may find people critical of over use of DI. The more significant the boundary being crossed (class, package, tier, library) the easier it is to justify using truly clean DI.


What's clean DI? No one should be able to look at the client and tell what's doing the injecting. Anything that gives it away, even annotations, represents something the code is dependent on. Something that you may have to change if you decide to inject using something else. When you use an alternative to DI like a Service Locator you're not removing all dependency. You're sweeping it into a corner.


The point of DI is to make a class that only offers it's own behavior. That is willing to talk to any object that implements it's interfaces. All without needing to rewrite it even if whatever is used to wire it together with other objects goes out of style and needs to change.
Galhalee (talk) 09:17, 13 March 2014 (UTC)

Disadvantages Section[edit]

The Disadvantages section claims that unit testing can mitigate incorrect dependency resolution. By definition unit tests test a unit in isolation, independent of their dependencies. Such a test is by definition an integration test even if achieved using jUnit or nUnit test harnesses. Galhalee (talk) 17:40, 15 March 2014 (UTC)

Dependency injection is...[edit]

The current statement, "Dependency injection is a software design pattern that allows the removal of hard-coded dependencies and makes it possible to change them, whether at run-time or compile-time" is not the definition used in the cited work[1]. That links to the abstract for this paper (See PDF link in lower left corner of abstract). On page 2 is an excellent definition of DI, "Dependency injection is a design pattern that shifts the responsibility of resolving dependencies to a dedicated dependency injector that knows which dependent objects to inject into application code". This keeps it from being confused with the Strategy Pattern's motivation to swap out implementations at run time. DI provides this power but only as a side effect. It is hardly the point. Galhalee (talk) 17:07, 16 March 2014 (UTC)

Introduction revision[edit]

ThomasO1989, why did you remove the concept of a reference being passed? Also, I'm trying to move away from the emphasis on swapping objects at run time as that's a motivation of strategy. For DI that's merely a side effect. DI just wants clients free of dependencies so the rest of the world can fall apart and the client doesn't need to change a line of its own code. Galhalee (talk) 02:39, 17 March 2014 (UTC)

Understood. Removed emphasis on "run-time" and explicitly referred to "reference" in the lead. It may be good to cover the difference between DI and the strategy pattern in the lead and in the Definition section as well. Also, feel free to ping me with {{ping|ThomasO1989}} when you have a question, as I may not see it immediately. --ThomasO1989 (talk) 02:52, 17 March 2014 (UTC)
Thanks, also, I am totally ignorant of proper citation procedures. That first citation is a URL hack of another one I saw and copied. I noticed dates inside that I have no clue if I am supposed to update. Please advise. Galhalee (talk) 03:58, 17 March 2014 (UTC)
If you're referring to the Martin Fowler citation, the only date you may want to update is the "accessdate" field. The other "date" field does not change, as it refers to the date the article was published. On an unrelated note, I feel that the opening sentence in the lead is becoming run-on and somewhat overly technical. It should be divided into two or more sentences. --ThomasO1989 (talk) 04:04, 17 March 2014 (UTC)
Yes that is the citation. I've updated it. And yes the first sentence is getting wordy. I've moved it into a second paragraph. How about I let you have at the whole introduction for a bit? Please ping me when you're done. Thanks for the help. Galhalee (talk) 05:03, 17 March 2014 (UTC)
I trimmed out some details that I thought were a little too much for the lead. It feels like it's trying to cover the entire definition of what and what does not make dependency injection, which might be overwhelming. I think that these details would be best appropriate in the Definition section. --ThomasO1989 (talk) 15:42, 17 March 2014 (UTC)

Definition[edit]

@ThomasO1989: Moved the details to the definition with some rewording. Take a crack at it. Thanks. Galhalee (talk) 19:10, 17 March 2014 (UTC)

Motivation[edit]

@ThomasO1989: Trimmed motivation down after Uses updated. Trying to avoid making the same point over and over. Galhalee (talk) 05:09, 19 March 2014 (UTC)

Examples replaced[edit]

@ThomasO1989: Have at it. Galhalee (talk) 08:39, 22 March 2014 (UTC)

@Galhalee: From a glance I notice some style problems. First is the repeated use of the word "you" and that it's written like instructions in a Head First textbook. Please avoid this, as it makes the article un-encyclopedic. Wikipedia is not a manual. Don't assume that the reader is interested in actually using DI. Second is the use of statements like "This is bad." and "So far so good." This is extremely un-formal for an encyclopedia. Same goes for the use of contractions like "it's", "isn't" and "doesn't". I'm letting you know this now before I make changes, so that you yourself can avoid this style in future edits. --ThomasO1989 (talk) 15:53, 22 March 2014 (UTC)
I've rewritten the "Refactoring in five seconds" to show the style I'd like the rest of the section to follow. The sections are renamed to avoid the manual-like intention.
Understood. Is the problem only with the text or are there problems with the code? Galhalee (talk) 16:44, 22 March 2014 (UTC)

--ThomasO1989 (talk) 16:24, 22 March 2014 (UTC)

Now that I look overall, the "Simple example" is already covered later in the Constructor injection section. It's not needed. "Complex example" is just a series of instructions to make a class fit the pattern. Like I said, Wikipeda is not a manual. I'm going to remove these sections altogether. We should focus on improving the existing sections instead. --ThomasO1989 (talk) 16:35, 22 March 2014 (UTC)
@ThomasO1989: "Complex example" is intended to show a dependency injection refactoring. It's meant to illustrate how wide the impact of a change like the "simple example" is to the rest of the system. Are you saying the code itself violates a wikipedia policy? Galhalee (talk) 16:58, 22 March 2014 (UTC)
I feel like iteratively refactoring the code is not the way to convey the benefits of DI. Objectively speaking, "Complex example" isn't an example of DI per se, it's an example of how to achieve it, which is what violates Wikipedia policy. The code examples already in the article already show how it's supposed to look. Since the goal is show the benefits of DI, I feel that rewriting Motivation should show this. You also must keep in mind that, like any pattern, DI has disadvantages. You shouldn't play up DI as a really great solution to a problem, otherwise you violate neutral point of view. --ThomasO1989 (talk) 17:10, 22 March 2014 (UTC)
@ThomasO1989:I don't mean to sound like Dependency Injection is a perfect solution. I would like to portray the mind set behind it. I'm still trying to find the right voice to do it with.
I had already made fairly critical additions to the disadvantages section. I'm trying to show DI as a solution to some problems and a way to over complicate others. Without showing the impact of refactoring the client on the rest of the system we'd actually be hiding one of its greatest disadvantages. It forces the creation of other code outside the client. That other code is what does the injecting and is a vital part of dependency injection.
I will admit it got fairly long because of the iterative steps. Would you accept if it was switched to simple before and after code listing? Galhalee (talk) 22:00, 22 March 2014 (UTC)

@ThomasO1989: I've unified the class names used in the examples so they are no longer conflict with other examples and made them less conversational. Is the hard coded example acceptable now? Galhalee (talk) 05:41, 23 March 2014 (UTC)

Comments[edit]

@Galhalee: Hey there, sorry for the week's absence, I was busy mostly with other articles and real-life, but I have some comments. The article is greatly improved, but I feel that the article is broken up into too many sections. Many of them are just for describing the pattern, its characteristics, and uses. I think one section, Overview, would encompass this better.

  • The Assembly comparison has problems. First, the use of "It turns out ... it's not implemented that differently." Turns out to who? This is using really casual textbook and instruction-like prose. It feels like the purpose of this section is to compare DI to other patterns. Can't this just be merged with the prose dealing with Strategy?
  • Definitions: it's nothing but random quotes. Can't they be merged elsewhere?
  • Equivalent terms: do you really need a whole section for this?
  • Elements: This can be merged into Overview.

--ThomasO1989 (talk) 16:29, 29 March 2014 (UTC)

@ThomasO1989: Glad to have you back. You're hard to replace. I'm glad you think it's improved.
The idea of an overview section sounds good. I'm reluctant to try to merge the different points together. That's how they were before and the concepts were getting muddled together.
The definitions are not random. They are from reputable sources and cited as such. The point was how different the definitions were. I had intended to add more as I found them. Is this not acceptable?
Different sources use a wide variety of terminology that needs to be explicitly dealt with. I'm trying to reduce this by ruthlessly re-editing the article to make the terms it uses consistent at least with it self.
I guess Textbook prose is hard to keep from writing after reading a lot of textbooks. I've made some edits to correct it. The point of assembly comparison was to admit dependency injections dirty little secret. You can't use it everywhere. At some point you have to breakdown and decide what dependent implementations to use. When you do that you're often using a service locator. This causes confusion because these are seen as opposing patterns. The point was that it's fine if it's done in one place in an application. It has nothing to do with strategy and shouldn't be dealt with until after the assembly examples.
Thanks for the feedback,
Galhalee (talk) 17:33, 29 March 2014 (UTC)
The current Overview section doesn't flow well. It goes all over the place, from comparison to other patterns, then to uses, then to definitions, etc. This confuses the reader. Defining what the pattern is should always come first. What it's used for won't make any sense for the reader if he doesn't know what it is. I feel that the Overview should actually be one whole section without subsections; things like "equivalent terms" can be described in a sentence or two instead of lists. In regards to the quotes, while they are relevant, they aren't integrated well. What I meant by "random" is that they're just kinda dumped there, like it was copy pasted from any source found on Google. I feel like this approach unintentionally slips into plagiarism territory. If you can define the pattern with one or two of the most useful quotes, you don't need more. Copying more and more quotes into the section isn't going to be useful to the reader. You should also paraphrase quotes instead of using them verbatim. In regards to DI's "dirty little secret", it sounds like a disadvantage. Could you merge this in the Disadvantages section? --ThomasO1989 (talk) 17:59, 30 March 2014 (UTC)
@Galhalee: I have a new version of the Overview section rewritten. I felt ultimately that there's a lot of repetitiveness and a lot of information that is either not vital or that should go into over sections. I've tried to condense the information into only a few paragraphs. There's still more work to be done, though, and it's difficult because not many references have been supplied. I've added many "citation needed" tags also. --ThomasO1989 (talk) 19:27, 30 March 2014 (UTC)

Destructive edit[edit]

@ThomasO1989: Did you honestly only mean to reorganize when you made this edit? "reorganise; having an overview halfway down the article doesn't seem to make sense to me, and a comparison with other options probably belongs near the end"

This edit did not merely reorganize. It destroyed cited content that was not merged into anything else.

@Galhalee: You're referring to this edit? It's quite clear I didn't do it, user Ironholds did. But I do agree that having Overview halfway down the article didn't make sense. I was thinking it should have been the first section after the Lead. --ThomasO1989 (talk) 08:21, 30 March 2014 (UTC)
@ThomasO1989: Ha, you're right. My apologies. How embarrassing. I guess I was used to you being the only other user making large changes.
Well then please offer your onion. Does it flow better organized like this or with an overview after the lead? I liked having the comparison to other patterns before the code examples because the code examples never explain the point of the pattern, just how it's achieved.
The comparison could be part of the Overview. Was thinking of having Overview then Examples as the first two sections. Galhalee (talk) 12:22, 30 March 2014 (UTC)
    • ^ Niko Schwarz, Mircea Lungu, Oscar Nierstrasz, “Seuss: Decoupling responsibilities from static methods for fine-grained configurability”, Journal of Object Technology, Volume 11, no. 1 (April 2012), pp. 3:1-23, doi:10.5381/jot.2012.11.1.a3.