Ryan Griffith
Ryan Griffith

Reputation: 1640

Why use IoC / DI if concrete classes are known?

I have been reading for several days now on Dependency Injection / Inversion of Control and am struggling to understand a concept.

Lets assume I have the following trivial scenario:

public interface ILocation
{
    string LocationName { get; set; }
}

// The implementation / concrete class for ILocation
public class Location : ILocation
{
    public string LocationName {
        get { /* logic */ }
        set { /* logic */ }
    }
}


// My class that depends on ILocation as a dependency
public class SomeClass{
    public SomeClass(ILocation location)
    {
        this.theLocation = location;
    }

    // 
    // more code...
    // 
}

Great, so I get my ILocation injected into my SomeClass... but I had to wire up ILocation to be handled by Location within my Dependency Injection framework IN CODE and compile that. (Aside: I realize that there are frameworks that do this configuration in files, i.e. XML config files)

What is the point of creating this "separation" of knowledge when all the components listed above are necessary to exist at compile time?

This is really racking me. Perhaps I've missed the point entirely. Now, that being said, I do see a lot of people talk about "testability" and I can see the advantage there, but let's assume we're throwing testing out the window; what else are the advantages? What is this really giving me?

I originally sought out this concept to learn more in hopes that I could find a good way to design a "plugin" pattern for an application I'm building. So far, this appears as though it would not work for the concept of runtime plugins.

Looking forward to insight on the subject - Thank you!

Upvotes: 3

Views: 740

Answers (4)

Jace Rhea
Jace Rhea

Reputation: 5018

Let's take your class and get rid of DI.

public class SomeClass
{
    private Location _location = new Location();
    public SomeClass()
    {
    }
}

Great, you are able to create the Location object and it takes in no parameters in its constructor. Code is looking pretty, and it was easy right? But wait, there is now a change to the Location class that requires it's own dependency, LocationFinder. So we add that to the object construction, and maybe we move it to the constructor.

public class SomeClass
{
    private Location _location;
    public SomeClass()
    {
         _location = new Location(new LocationFinder());
    }
}

Ok, less pretty but still not too bad. But sure enough 6 months later LocationFinder has to change and now it needs to be created from a factory, LocationFinderFactory, which has its own dependencies.

public class SomeClass
{
    private Location _location;
    public SomeClass()
    {
        var locationFinderFactory = new LocationFinderFactory(new LocationFinderStrategy());
        _location = new Location(locationFinderFactory.Create());
    }
}

Not quite as clean not right? The more noteworthy point is that everytime the Location implementation changed you had to change the SomeClass as well. You've coupled the implementation of SomeClass to Location and 3 other classes as well! Now you will be changing SomeClass everytime any of the these 4 classes has to change.

Moral of the story, code your classes in a loosely coupled way (such as using DI) and these type of code changes will be localized to only the classes that it should affect.

Upvotes: 3

Vizu
Vizu

Reputation: 1921

The way you manage dependencies inside your system have a huge impact on the quality of your software (flexibility, robustness, reusability, maintability) especially in the long run when your system goes through a lot of changes as time goes by. And dependency injection is one powerful tool (among others) to manage dependencies.

This article discusses this topic beautifully, so I don't try to replicate it :) http://www.objectmentor.com/resources/articles/Principles_and_Patterns.pdf

Upvotes: 0

jmoerdyk
jmoerdyk

Reputation: 5521

What you're gaining is separation of concerns. With DI, you can freely change the implementation or swap out implementations of the ILogger without having to modify (or even recompile) SomeClass. With DI, SomeClass doesn't care what class is implementing the ILogger interface, as long as it implements all the methods in the interface. If you used concrete classes, if you wanted to change which class was implementing the methods, you would have to modify SomeClass as well. With DI, all you have to change is what class is getting sent to the constructor, or the configuration of the IoC container, without having to modify SomeClass itself.

Upvotes: 1

JB Nizet
JB Nizet

Reputation: 691765

Dependency injection's first goal is to make the code easily unit-testable.

Then come additional advantages, like the possibility to inject proxies (AOP, used for transactions, security checks, etc.), to configure the injected components, to choose implementations depending on a profile or configuration, etc. All this depends on the capabilities of your framework.

Upvotes: 2

Related Questions