612

I'm trying to understand dependency injections (DI), and once again I failed. It just seems silly. My code is never a mess; I hardly write virtual functions and interfaces (although I do once in a blue moon) and all my configuration is magically serialized into a class using json.net (sometimes using an XML serializer).

I don't quite understand what problem it solves. It looks like a way to say: "hi. When you run into this function, return an object that is of this type and uses these parameters/data."
But... why would I ever use that? Note I have never needed to use object as well, but I understand what that is for.

What are some real situations in either building a website or desktop application where one would use DI? I can come up with cases easily for why someone may want to use interfaces/virtual functions in a game, but it's extremely rare (rare enough that I can't remember a single instance) to use that in non-game code.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • 3
    This may also be useful information: http://martinfowler.com/articles/injection.html – ta.speot.is Jan 13 '13 at 07:17
  • 1
    http://stackoverflow.com/questions/1638919/how-to-explain-dependency-injection-to-a-5-year-old – Sinan AKYAZICI Jan 13 '13 at 07:40
  • @Steven Yes. Actually not in my C# code but I am game for an explanation. And no I never had any pains or issues with it. My code (and my teams code) is always very well put together –  Jan 13 '13 at 08:03
  • 1
    [See also](http://gamedev.stackexchange.com/questions/14217/several-classes-need-to-access-the-same-data-where-should-the-data-be-declared/14232#14232). – BlueRaja - Danny Pflughoeft Jan 13 '13 at 10:38
  • I found this video on how to build a simple DI Container quite amazing: (By the developer of Funq) http://blogs.clariusconsulting.net/kzu/funq-screencast-series-on-how-to-building-a-di-container-using-tdd/ – Tyst Jan 13 '13 at 15:19
  • 54
    I'm with this guy: http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html. – Eric Lippert Jan 13 '13 at 17:29
  • I've also written a piece about it: http://www.codeproject.com/Articles/386164/Get-injected-into-the-world-of-inverted-dependenci – jgauffin Jan 14 '13 at 06:51
  • I really enjoyed reading this - http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/ – Lloyd Powell Jan 14 '15 at 09:43
  • 5
    Another very simple explanation of DI: http://www.codearsenal.net/2015/03/c-sharp-dependency-injection-simple.html – ybonda Mar 24 '15 at 08:05
  • On my case I understood the premise, the problem it had, I had the problem and it hit me hard I wish I learn this before I can even get started in my project. I am on Android/Java side so I use Dagger2. Now digging deeper into it, it just even more absolute mess I have to deal with, I find it complicated (even though it advertises to save me from writing boiler plate code, which I definitely believe) but the learning curve to get around it is extremely high. The concept is good but the extra heiroglyph to write on top of my own mess is not worthwhile the trouble. But I'm still trying. – Neon Warge Jun 25 '17 at 11:54
  • Here's a good tutorial/examples in C# about this topic: https://www.tutorialsteacher.com/ioc – carloswm85 Oct 12 '21 at 17:04

6 Answers6

920

First, I want to explain an assumption that I make for this answer. It is not always true, but quite often:

Interfaces are adjectives; classes are nouns.

(Actually, there are interfaces that are nouns as well, but I want to generalize here.)

So, e.g. an interface may be something such as IDisposable, IEnumerable or IPrintable. A class is an actual implementation of one or more of these interfaces: List or Map may both be implementations of IEnumerable.

To get the point: Often your classes depend on each other. E.g. you could have a Database class which accesses your database (hah, surprise! ;-)), but you also want this class to do logging about accessing the database. Suppose you have another class Logger, then Database has a dependency to Logger.

So far, so good.

You can model this dependency inside your Database class with the following line:

var logger = new Logger();

and everything is fine. It is fine up to the day when you realize that you need a bunch of loggers: Sometimes you want to log to the console, sometimes to the file system, sometimes using TCP/IP and a remote logging server, and so on ...

And of course you do NOT want to change all your code (meanwhile you have gazillions of it) and replace all lines

var logger = new Logger();

by:

var logger = new TcpLogger();

First, this is no fun. Second, this is error-prone. Third, this is stupid, repetitive work for a trained monkey. So what do you do?

Obviously it's a quite good idea to introduce an interface ICanLog (or similar) that is implemented by all the various loggers. So step 1 in your code is that you do:

ICanLog logger = new Logger();

Now the type inference doesn't change type any more, you always have one single interface to develop against. The next step is that you do not want to have new Logger() over and over again. So you put the reliability to create new instances to a single, central factory class, and you get code such as:

ICanLog logger = LoggerFactory.Create();

The factory itself decides what kind of logger to create. Your code doesn't care any longer, and if you want to change the type of logger being used, you change it once: Inside the factory.

Now, of course, you can generalize this factory, and make it work for any type:

ICanLog logger = TypeFactory.Create<ICanLog>();

Somewhere this TypeFactory needs configuration data which actual class to instantiate when a specific interface type is requested, so you need a mapping. Of course you can do this mapping inside your code, but then a type change means recompiling. But you could also put this mapping inside an XML file, e.g.. This allows you to change the actually used class even after compile time (!), that means dynamically, without recompiling!

To give you a useful example for this: Think of a software that does not log normally, but when your customer calls and asks for help because he has a problem, all you send to him is an updated XML config file, and now he has logging enabled, and your support can use the log files to help your customer.

And now, when you replace names a little bit, you end up with a simple implementation of a Service Locator, which is one of two patterns for Inversion of Control (since you invert control over who decides what exact class to instantiate).

All in all this reduces dependencies in your code, but now all your code has a dependency to the central, single service locator.

Dependency injection is now the next step in this line: Just get rid of this single dependency to the service locator: Instead of various classes asking the service locator for an implementation for a specific interface, you - once again - revert control over who instantiates what.

With dependency injection, your Database class now has a constructor that requires a parameter of type ICanLog:

public Database(ICanLog logger) { ... }

Now your database always has a logger to use, but it does not know any more where this logger comes from.

And this is where a DI framework comes into play: You configure your mappings once again, and then ask your DI framework to instantiate your application for you. As the Application class requires an ICanPersistData implementation, an instance of Database is injected - but for that it must first create an instance of the kind of logger which is configured for ICanLog. And so on ...

So, to cut a long story short: Dependency injection is one of two ways of how to remove dependencies in your code. It is very useful for configuration changes after compile-time, and it is a great thing for unit testing (as it makes it very easy to inject stubs and / or mocks).

In practice, there are things you can not do without a service locator (e.g., if you do not know in advance how many instances you do need of a specific interface: A DI framework always injects only one instance per parameter, but you can call a service locator inside a loop, of course), hence most often each DI framework also provides a service locator.

But basically, that's it.

P.S.: What I described here is a technique called constructor injection, there is also property injection where not constructor parameters, but properties are being used for defining and resolving dependencies. Think of property injection as an optional dependency, and of constructor injection as mandatory dependencies. But discussion on this is beyond the scope of this question.

NoDataDumpNoContribution
  • 10,591
  • 9
  • 64
  • 104
Golo Roden
  • 140,679
  • 96
  • 298
  • 425
  • Ok so you wrote "Dependency injection is one of two ways". What is the other way? Because... I already know what I would do rather then this and I don't know if we are thinking the same thing. -edit- fyi i nearly upvoted. idk why someone DV you –  Jan 13 '13 at 07:42
  • 2
    The way I would have done it is LEAVE EVERYTHING THE WAY IT WAS (as in not change `new Logger()` nor write `LoggerFactory.Create();` anywhere. I would change it so Logger has a ICanLog member which is set in the constructor by reading the XML file and forward all the commands to it. No code change required except renaming the original Logger class to SomeConcreteLogger then create a forwarding class as `Logger`. –  Jan 13 '13 at 07:59
  • 7
    Of course you can do it this way, too, but then you have to implement this logic in every single class which shall provide support for exchangability of implementation. This means lots of duplicated, redundant code, and this also means you need to touch an existing class and rewrite it partially, once you decide that you need it now. DI allows you to use this on any arbitrary class, you do not have to write them in a special way (except defining dependencies as parameters in the constructor). – Golo Roden Jan 13 '13 at 08:37
  • 1
    Dependency Injection is one of two ways - right: The other way is the service locator. – Golo Roden Jan 13 '13 at 08:38
  • 1
    @GoloRoden Nice explanation but I think you put too much stress on classes - they aren't directly related to DI. If `Foo` depends on `IBar` and there's only one implementation of `IBar` called `Bar` (heck, the type `IBar` might not be defined at all), then DI still makes sense: depending on the context you may want to inject differently configured instances of `Bar`. – Kos Jan 13 '13 at 11:33
  • 184
    Here is the thing I never get about DI: it makes the architecture **vastly** more complicated. And yet, as I see it, the use is pretty limited. The examples are certainly always the same: interchangeable loggers, interchangeable model / data access. Sometimes interchangeable view. But that’s it. Do these few cases really justify a vastly more complex software architecture? – Full disclosure: I’ve already used DI to great effect, but that was for a very special plug-in architecture that I wouldn’t generalise from. – Konrad Rudolph Jan 13 '13 at 13:15
  • 21
    @GoloRoden, why are you calling the interface ICanLog instead of ILogger? I worked with another programmer who often did this, and I could never understand the convention? To me it is like calling IEnumerable ICanEnumerate? – DermFrench Jan 13 '13 at 16:03
  • 38
    I called it ICanLog, because we work too often with words (nouns) that mean nothing. E.g., what is a Broker? A Manager? Even a Repository is not defined in a unique way. And having all these things as nouns is a typical disease of OO languages (see http://steve-yegge.blogspot.de/2006/03/execution-in-kingdom-of-nouns.html). What I want to express is that I have a component that can do logging for me - so why not call it that way? Of course, this is also playing with the I as the first person, hence ICanLog(ForYou). – Golo Roden Jan 13 '13 at 17:57
  • 5
    @KonradRudolph I'm with you as far as using an IOC goes, it's overkill for many applications, but I'm interested how you suggest unit testing without designing classes to allow the injection of dependencies? Often injecting infrastructure, but also often pieces of domain code that you want to be able to replace for testing. Injecting these dependencies as ctor params has never struck me as much more complicated. And of course the case you mention of wanting pluggable behaviour makes DI a must. I've for a long time found the D in SOLID to be a key enabler for a lot of the power of OO patterns. – David Hall Jan 13 '13 at 18:00
  • 23
    @David Unit testing works just fine – after all, a *unit* is independent of other things (otherwise it’s not a unit). What *doesn’t* work without DI containers is mock testing. Fair enough, I am unconvinced that the benefit of mocking outweighs the added complexity of adding DI containers in all cases. I do rigorous unit testing. I rarely do mocking. – Konrad Rudolph Jan 13 '13 at 18:12
  • 1
    @KonradRudolph: Exactly my thoughts. It bothers me when I hear people use DI -a lot- (as in when they can they do). –  Jan 13 '13 at 18:46
  • @GoloRoden: You said "Of course you can do it this way, too, but then you have to implement this logic in every single class" <-- I personally think is better then replacing all the `new Logger()`. It would be nice if something existed to automate creating or generating a forwarding class. Also I'd have the advantage of offering more then one logger at a time. But... as you may understand I still don't have a use as I can do that question which IMO is clean. I just need an easy way to create a forward class so I guess DI is helpful there if I actually want that (complexity as Konrad mentioned) –  Jan 13 '13 at 18:49
  • 7
    @KonradRudolph I've always found that as soon as I want to unit test methods on classes which have dependencies on other systems that injecting the dependencies is necessary. Whether to mock or merely stub the dependencies out. Do you perhaps have a reference to a description of unit testing where dependencies don't need to be replaced? I'm very interested in other approaches. – David Hall Jan 13 '13 at 18:55
  • @DavidHall: I never felt a problem but I don't unit test that much. I just want to know A) How clean is the code and B) Do you use singletons? If singletons exist and or its not well design code then I can see why its a problem. –  Jan 13 '13 at 18:59
  • 3
    @acidzombie24 I never use singletons. That is a huge benefit of DI in the first place, it negates the need for patterns like service locator. Of course I think my code is well designed - that is why I design it that way :) For me personally the best way to understand a class is to run its methods and see what happens. I find code that has been designed to allow DI makes running pieces of a large code base in isolation MUCH easier - as for unit testing, it just happens to be a convenient way of doing that in a repeatable manner. – David Hall Jan 13 '13 at 19:08
  • 5
    @acidzombie24: To cut a long story short - dependency injection is a (not *THE*) way to resolve dependencies. It you are happy without, then there is no need to use it. But if you run into problems that are caused by unresolved dependencies (may it be within tests or whatever), I'd suggest you go with DI, because this is a wide-spread best practice. No need to figure out your own style of doing it ;-). – Golo Roden Jan 14 '13 at 04:56
  • 13
    @acidzombie24 "It bothers me when I hear people use DI -a lot-". What bothers me the most is often, you get all this complexity for **no** reason, because in actuality, nothing is ever injected and _there are no tests_. I hate this because it is gratuitous complexity. I say YAGNI/KISS – sehe Jan 14 '13 at 08:53
  • 3
    I don't agree DI complicates architecture **vastly**, but it's a bit more complex indeed (assuming you use DI container as a blackbox to achieve DI, rather than rolling your own). The benefits of DI is quite a lot though, it encourages unit testing, TDD, modularity. But if you roll your DI container, then probably its benefits are not worth the added complexity. – liang Nov 11 '14 at 07:44
  • 2
    How exactly do you write unit tests (which depend on other objects) without using DI to mock the dependencies? Or is this where you need a different architecture? – FBryant87 Sep 17 '15 at 09:18
  • 1
    A bit of necroing, but I've got the question. Whenver I know, or at least suspect that I might be using different thing in the same place (i.e. a different implementation of an interface) I am using some sort of config class for my application, so I am changing it instead of vast amounts of code. Is it a worse approach? – Barsik the Cat Feb 28 '18 at 10:41
  • Great answer! I would also like to add that, besides constructor injection and property injection as you mention yourself, there is also method injection where the method parameters are used for defining and resolving dependencies. – TheSteelDuck Apr 23 '18 at 13:38
  • RE: "Think of property injection as an optional dependency, and of constructor injection as mandatory dependencies." I like to contrast the difference between the two as dynamic v. static injection preferring the latter because it's easier to maintain. – Mario Jul 14 '18 at 15:22
  • 1
    ha! love your answer, I wish my coworkers can read and understand this. they are pushing back in using interface and DI. they said it is just too much work, not knowing that every damn time they update a function or class in the core library i breaks to many things and that is more work and more issues. – CyberNinja Mar 05 '19 at 17:46
  • I understand the motivation of “no compilation necessary” when using XML. This works well in multiple environment scenarios. What about the Java based config in Spring? Although it might be more simple to read than XML, isn’t that detrimental to the ability to change config without compiling? Of course you could reference external files from that config class, or replace config jars in the classpath, but those two seem really cumbersome. Am I missing something about Java Config? – Oren Aug 11 '19 at 12:05
582

I think a lot of times people get confused about the difference between dependency injection and a dependency injection framework (or a container as it is often called).

Dependency injection is a very simple concept. Instead of this code:

public class A {
  private B b;

  public A() {
    this.b = new B(); // A *depends on* B
  }

  public void DoSomeStuff() {
    // Do something with B here
  }
}

public static void Main(string[] args) {
  A a = new A();
  a.DoSomeStuff();
}

you write code like this:

public class A {
  private B b;

  public A(B b) { // A now takes its dependencies as arguments
    this.b = b; // look ma, no "new"!
  }

  public void DoSomeStuff() {
    // Do something with B here
  }
}

public static void Main(string[] args) {
  B b = new B(); // B is constructed here instead
  A a = new A(b);
  a.DoSomeStuff();
}

And that's it. Seriously. This gives you a ton of advantages. Two important ones are the ability to control functionality from a central place (the Main() function) instead of spreading it throughout your program, and the ability to more easily test each class in isolation (because you can pass mocks or other faked objects into its constructor instead of a real value).

The drawback, of course, is that you now have one mega-function that knows about all the classes used by your program. That's what DI frameworks can help with. But if you're having trouble understanding why this approach is valuable, I'd recommend starting with manual dependency injection first, so you can better appreciate what the various frameworks out there can do for you.

Lii
  • 11,553
  • 8
  • 64
  • 88
Daniel Pryden
  • 59,486
  • 16
  • 97
  • 135
  • 11
    Why would I prefer the second code rather than the first one? the first one only has the new keyword, how does this help? – user962206 Jan 13 '13 at 11:30
  • 22
    @user962206 think about how you would test A independently from B – jk. Jan 13 '13 at 14:12
  • 83
    @user962206, also, think about what would happen if B needed some parameters in its constructor: in order to instantiate it, A would have to know about those parameters, something that might be completely unrelated to A (it just wants to depend on B, not on what B depends on). Passing an already constructed B (or any subclass or mock of B for that matter) to A's constructor solves that and makes A depend only on B :) – epidemian Jan 13 '13 at 15:39
  • 21
    @acidzombie24: Like many design patterns, DI isn't really useful unless your codebase is large enough for the simple approach to become a problem. My gut feeling is that DI won't actually be an improvement until your application has more than about 20,000 lines of code, and/or more than 20 dependencies on other libraries or frameworks. If your application is smaller than that, you may still prefer to program in a DI style, but the difference won't be nearly as dramatic. – Daniel Pryden Jan 13 '13 at 21:21
  • 5
    @DanielPryden i don't think the code size matters as much as how dynamic your code is. if you're regularly adding new modules that fit the same interface, you won't have to change the dependent code as often. – FistOfFury Dec 10 '13 at 21:51
  • Note to @Lii: I'm not going to revert your edit, but specifically using C# syntax highlighting was not necessary for this answer. The code is intentionally written to be nearly as language-agnostic as possible (with a tiny tweak it would compile as Java as well). The answer isn't about C#, it's about dependency injection in general, and the concepts are not C#-specific. – Daniel Pryden Nov 01 '18 at 12:12
  • In FIRST example B class release memory when A class work is done But in SECOND example B will release memory at the end so why we hold that memory if its not required. I think its wrong It's just useful for developer not useful for user – Sanjayrajsinh Jan 17 '21 at 16:07
42

As the other answers stated, dependency injection is a way to create your dependencies outside of the class that uses it. You inject them from the outside, and take control about their creation away from the inside of your class. This is also why dependency injection is a realization of the Inversion of control (IoC) principle.

IoC is the principle, where DI is the pattern. The reason that you might "need more than one logger" is never actually met, as far as my experience goes, but the actually reason is, that you really need it, whenever you test something. An example:

My Feature:

When I look at an offer, I want to mark that I looked at it automatically, so that I don't forget to do so.

You might test this like this:

[Test]
public void ShouldUpdateTimeStamp
{
    // Arrange
    var formdata = { . . . }

    // System under Test
    var weasel = new OfferWeasel();

    // Act
    var offer = weasel.Create(formdata)

    // Assert
    offer.LastUpdated.Should().Be(new DateTime(2013,01,13,13,01,0,0));
}

So somewhere in the OfferWeasel, it builds you an offer Object like this:

public class OfferWeasel
{
    public Offer Create(Formdata formdata)
    {
        var offer = new Offer();
        offer.LastUpdated = DateTime.Now;
        return offer;
    }
}

The problem here is, that this test will most likely always fail, since the date that is being set will differ from the date being asserted, even if you just put DateTime.Now in the test code it might be off by a couple of milliseconds and will therefore always fail. A better solution now would be to create an interface for this, that allows you to control what time will be set:

public interface IGotTheTime
{
    DateTime Now {get;}
}

public class CannedTime : IGotTheTime
{
    public DateTime Now {get; set;}
}

public class ActualTime : IGotTheTime
{
    public DateTime Now {get { return DateTime.Now; }}
}

public class OfferWeasel
{
    private readonly IGotTheTime _time;

    public OfferWeasel(IGotTheTime time)
    {
        _time = time;
    }

    public Offer Create(Formdata formdata)
    {
        var offer = new Offer();
        offer.LastUpdated = _time.Now;
        return offer;
    }
}

The Interface is the abstraction. One is the REAL thing, and the other one allows you to fake some time where it is needed. The test can then be changed like this:

[Test]
public void ShouldUpdateTimeStamp
{
    // Arrange
    var date = new DateTime(2013, 01, 13, 13, 01, 0, 0);
    var formdata = { . . . }

    var time = new CannedTime { Now = date };

    // System under test
    var weasel= new OfferWeasel(time);

    // Act
    var offer = weasel.Create(formdata)

    // Assert
    offer.LastUpdated.Should().Be(date);
}

Like this, you applied the "inversion of control" principle, by injecting a dependency (getting the current time). The main reason to do this is for easier isolated unit testing, there are other ways of doing it. For example, an interface and a class here is unnecessary since in C# functions can be passed around as variables, so instead of an interface you could use a Func<DateTime> to achieve the same. Or, if you take a dynamic approach, you just pass any object that has the equivalent method (duck typing), and you don't need an interface at all.

You will hardly ever need more than one logger. Nonetheless, dependency injection is essential for statically typed code such as Java or C#.

And... It should also be noted that an object can only properly fulfill its purpose at runtime, if all its dependencies are available, so there is not much use in setting up property injection. In my opinion, all dependencies should be satisfied when the constructor is being called, so constructor-injection is the thing to go with.

bad_coder
  • 11,289
  • 20
  • 44
  • 72
cessor
  • 1,028
  • 11
  • 16
  • 6
    That actually looks like a terrible solution. I would definitely write code more like [Daniel Pryden answer](http://stackoverflow.com/a/14301816/34537) suggest but for that specific unit test i'd just do DateTime.Now before and after the function and check if the time is in between? Adding more interfaces/much more lines of code seems like a poor idea to me. –  Jan 13 '13 at 19:11
  • 4
    I don't like generic A(B) examples and I never felt a logger is required to have 100 implementations. This is an example that I recently encountered and it is one of 5 ways to solve it, where one actually included using PostSharp. It illustrates a classic class based ctor injection approach. Could you provide a better real world example of where you encountered good use for DI? – cessor Jan 13 '13 at 22:31
  • Have you been working in an environment with a lot of tests? I found that even without test DI is the first thing to start with. Breaking up and then injecting dependencies helps one to reduce the sice of each component which helps to commit to Single Responsibility & Interface Seggregation principles. Another example could be a plugin container. You have classes laying around and wish to instantiate them without calling them explicitly the di container can do all that. I found DI to be very usefull wherever you do it. – cessor Jan 14 '13 at 11:58
  • 1
    Be aware that even in small functional programs, whenever you have f(x), g(f) you are already using dependency injection, so each continuation in JS would count as a dependency injection. My guess is that you are already using it ;) – cessor Jan 15 '13 at 10:56
  • 2
    I agree with this answer in that in my professional career I have never seen anyone actually utilize a benefit of Dependency Injection i.e., there is always just one child class implementing the interface. The ONLY useful benefit I have seen with DI is in your Unit Tests because like others have said you can use Mockitto and other tools to inject a "Testing" version of the class so that you can more easily write tests with expected results. But like others also said I'm sure you could do similar testing without DI. My impression of DI is that it overfly complicates code and gives little reward – Kyle Bridenstine May 06 '19 at 13:37
  • You are right, TDD and DI are conceptually connected. Tests become easier to write, especially up front, because you can substitute a dependency with a test double (see, for example: http://xunitpatterns.com/Test%20Double%20Patterns.html). But I see this as a benefit: TDD (using tests to DRIVE development) encourages using DI. The result is an improved design where you focus on compositions (A(b, c) composition, rather than A <- B inheritance). See, for example Gamma et al. (Gang of Four) on the discussion Composition vs. Inheritance. – cessor May 07 '19 at 12:34
17

I think the classic answer is to create a more decoupled application, which has no knowledge of which implementation will be used during runtime.

For example, we're a central payment provider, working with many payment providers around the world. However, when a request is made, I have no idea which payment processor I'm going to call. I could program one class with a ton of switch cases, such as:

class PaymentProcessor{

    private String type;

    public PaymentProcessor(String type){
        this.type = type;
    }

    public void authorize(){
        if (type.equals(Consts.PAYPAL)){
            // Do this;
        }
        else if(type.equals(Consts.OTHER_PROCESSOR)){
            // Do that;
        }
    }
}

Now imagine that now you'll need to maintain all this code in a single class because it's not decoupled properly, you can imagine that for every new processor you'll support, you'll need to create a new if // switch case for every method, this only gets more complicated, however, by using Dependency Injection (or Inversion of Control - as it's sometimes called, meaning that whoever controls the running of the program is known only at runtime, and not complication), you could achieve something very neat and maintainable.

class PaypalProcessor implements PaymentProcessor{

    public void authorize(){
        // Do PayPal authorization
    }
}

class OtherProcessor implements PaymentProcessor{

    public void authorize(){
        // Do other processor authorization
    }
}

class PaymentFactory{

    public static PaymentProcessor create(String type){

        switch(type){
            case Consts.PAYPAL;
                return new PaypalProcessor();

            case Consts.OTHER_PROCESSOR;
                return new OtherProcessor();
        }
    }
}

interface PaymentProcessor{
    void authorize();
}

** The code won't compile, I know :)

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Itai Sagi
  • 5,537
  • 12
  • 49
  • 73
  • @ItaiS You can avoid the countless switches with the class factory design pattern. Use reflection System.Reflection.Assembly.GetExecutingAssembly().CreateInstance() – domenicr Nov 05 '15 at 19:39
  • @domenicr ofcourse! but I wanted to explain it in a simplified example – Itai Sagi Nov 15 '15 at 18:59
  • I agree with the above explanation, except the need of factory class. The moment we implement factory class its simply a crude selection. The best explanation of above which I found in the Chapter of Poymorphism and virtual function by Bruce Erkel. The true DI should be free from the selection and the object type should be decided at the run-time through the interface automatically. That is also what the true polymorphic behavior is. – Arvind Krmar May 14 '16 at 11:56
  • For example(as per c++) we have a common interface which takes just the reference to base class and implements the behavior of its derive class without selection. void tune(Instrument& i) { i.play(middleC); } int main() { Wind flute; tune(flute); } Instrument is the base class, wind is derived from it. As per c++, virtual function make this possible to implement behavior of derived class through common interface . – Arvind Krmar May 14 '16 at 12:02
7

The main reason to use DI is that you want to put the responsibility of the knowledge of the implementation where the knowledge is there. The idea of DI is very much inline with encapsulation and design by interface. If the front end asks from the back end for some data, then is it unimportant for the front end how the back end resolves that question. That is up to the requesthandler.

That is already common in OOP for a long time. Many times creating code pieces like:

I_Dosomething x = new Impl_Dosomething();

The drawback is that the implementation class is still hardcoded, hence has the front end the knowledge which implementation is used. DI takes the design by interface one step further, that the only thing the front end needs to know is the knowledge of the interface. In between the DYI and DI is the pattern of a service locator, because the front end has to provide a key (present in the registry of the service locator) to lets its request become resolved. Service locator example:

I_Dosomething x = ServiceLocator.returnDoing(String pKey);

DI example:

I_Dosomething x = DIContainer.returnThat();

One of the requirements of DI is that the container must be able to find out which class is the implementation of which interface. Hence does a DI container require strongly typed design and only one implementation for each interface at the same time. If you need more implementations of an interface at the same time (like a calculator), you need the service locator or factory design pattern.

D(b)I: Dependency Injection and Design by Interface. This restriction is not a very big practical problem though. The benefit of using D(b)I is that it serves communication between the client and the provider. An interface is a perspective on an object or a set of behaviours. The latter is crucial here.

I prefer the administration of service contracts together with D(b)I in coding. They should go together. The use of D(b)I as a technical solution without organizational administration of service contracts is not very beneficial in my point of view, because DI is then just an extra layer of encapsulation. But when you can use it together with organizational administration you can really make use of the organizing principle D(b)I offers. It can help you in the long run to structure communication with the client and other technical departments in topics as testing, versioning and the development of alternatives. When you have an implicit interface as in a hardcoded class, then is it much less communicable over time then when you make it explicit using D(b)I. It all boils down to maintenance, which is over time and not at a time. :-)

Loek Bergman
  • 2,192
  • 20
  • 18
  • 1
    "The drawback is that the implementation class is still hardcoded" <-- most of the time there is only one implementation and like I said I can't think of nongame code that requires an interface that isn't already built in (.NET). –  Jan 13 '13 at 19:04
  • @acidzombie24 May be ... but compare the effort to implement a solution using DI from the beginning to the effort to change a non-DI solution later if you need interfaces. I'd nearly always go with the first option. It's better to pay now 100$ instead of having to pay 100.000$ tomorrow. – Golo Roden Jan 17 '13 at 08:07
  • 1
    @GoloRoden Indeed, maintenance is the key issue using techniques like D(b)I. That is 80% of the costs of an application. A design in which the required behaviour is made explicit using interfaces from the start saves the organization later on a lot of time and money. – Loek Bergman Jan 17 '13 at 10:02
  • I'm not going to understand truly until I have to pay it because so far I paid $0 and so far I still only need to pay $0. But I do pay $0.05 to keep every line or function clean. –  Jan 17 '13 at 11:08
3

Quite frankly, I believe people use these Dependency Injection libraries/frameworks because they just know how to do things in runtime, as opposed to load time. All this crazy machinery can be substituted by setting your CLASSPATH environment variable (or other language equivalent, like PYTHONPATH, LD_LIBRARY_PATH) to point to your alternative implementations (all with the same name) of a particular class. So in the accepted answer you'd just leave your code like

var logger = new Logger() //sane, simple code

And the appropriate logger will be instantiated because the JVM (or whatever other runtime or .so loader you have) would fetch it from the class configured via the environment variable mentioned above.

No need to make everything an interface, no need to have the insanity of spawning broken objects to have stuff injected into them, no need to have insane constructors with every piece of internal machinery exposed to the world. Just use the native functionality of whatever language you're using instead of coming up with dialects that won't work in any other project.

P.S.: This is also true for testing/mocking. You can very well just set your environment to load the appropriate mock class, in load time, and skip the mocking framework madness.

user986730
  • 1,226
  • 1
  • 13
  • 12
  • Can you explain how that would work? By writing `new Logger()` in your code, nothing is exchangable – Nico Haase Oct 08 '20 at 13:18
  • 1
    @NicoHaase indeed, nothing is exchangeable in runtime, but it is in load time (i.e.: just before your application gets executed). With this approach you would *write multiple classes with the same name*, and then configure your runtime to load the correct one by setting the correct environment variable, (like PYTHONPATH or CLASSPATH) thus loading the implementation you want for that particular execution of your application. – user986730 Oct 09 '20 at 14:24
  • @NicoHaase, but the point is having a mechanism or pattern that allows to change the implementation in runtime. – Jose4Linux Jan 13 '23 at 12:43
  • @Jose4Linux what do you mean by that? by using `new Logger()` within the code itself, nothing is changable in runtime – Nico Haase Jan 13 '23 at 12:47
  • @NicoHaase, it's my fault, I was answering to @ user9867330. I share your thoughts on this topic :) – Jose4Linux Jan 13 '23 at 12:55