locked
When to implement Dependency Injection? RRS feed

  • Question

  • I am working on a large web app, and I've studied Dependency Injection.

    What are the tell-tale signs in my code that I should consider implementing this pattern? Is it a bad thing to be refactoring  what is a currently large and growing codebase to implement DI?


    Thanks
    Thursday, April 17, 2008 12:24 AM

Answers

  • Hi guys,

     

       I dare to say, as a conclusion of all posts on this thread that the story about DI starts on the root of basic design patterns (the ones enlisted on the best-seller GoF book)

     

       The Strategy pattern seems to be a good way to separate the major activities of an algorithm from the internals of its implementation. That way we don't need to get married with any specific implementation of the algorithm (let's call each "a strategy") but we can generate several and eventually change the strategy at our conveniency

     

       However, linking a given strategy with classes that will use it may need a 2-step process:

    1. Instancing the chosen strategy (for instance via the Factory method pattern)
    2. Assigning the created instance as a dependence (i.e. a property) of its "clients"

       This model, put in practice, may require other features like instance control. For instance, if a given strategy will be used by several consumers, should they instanciate a separated object each or they might share just a single one?

       Derived from that, what about the GoF implementation of the Singleton pattern? Its original intention is avoiding a proliferation of instances when one is enough for the whole application scope. However the original GoF implementation (based on assignments made directly to the singleton class via the static keyword, what turns inheritance useless as whatever is the descendant class, if we call the SingletonClass.GetInstance() class-level method, the returned instance will always belong to SingletonClass, so in order to get the single instance of a descendant, we need to call the overwritten version of InheritedSingleton.GetInstance()

       The resulting aftermath of all these is a strong coupling between strategies and their consumers

     

       A dependency injection framework helps get the best of GoF patterns (in terms of clarity, maintenance and low coupling) without staying tangled in their drawbacks

     

       As some of you guys gave as example, using mocking techniques for testing purposes, etc is a way to put the strategy pattern in practice once again, so applying a DI framework is a good alternative, as it will be any other alternative where we need to follow a single algorithm with the chance of varying its internals. You'll find plenty of examples: a billing system where each service has a particular way to be billed, a mortgage application where loans are being lent but with different amortization mechanism (let's say, french, german, etc). And many many others

     

     

     

       Hope that helps

    Tuesday, May 20, 2008 8:46 PM

All replies



  • My main drive when I initially looked at DI was to use it with mocking objects.  If you have dependencies and would like the ability to inject then into an object, then that would be your driver for dependency injection.

    Since my work has been driven by testing the code, the code my team writes is written with tests in mind, and thus uses DI.

    If the refactor, and changes are minor and still conform to the original interface, then DI is useful to you, but if a new interface is required, then another overload on a constructor for example would be required to accept that interface.

    And refactoring is good, if you have the processes in place to do so, so the risk is minimized.  Processes I am talking about are change control, and unit tests particularly.

    If you have any further questions, please ask,

    Martin Platt.
    Thursday, April 17, 2008 1:51 AM
  • Please don't use it only for mocking objects, IMO you should worry if you're having to change your code to accommodate a testing framework but it certainly can be used to help you use interfaces if that's the way you choose to implement your code. The if you choose to use DI for your code then you can certainly use it for mocking too.




    Thursday, April 17, 2008 5:59 AM
  • HI

     

    there's really no golden rule when to implement DI/service factory/service locator

    It's more of a structural choice to have all your service/controller

    - based on interfaces

    - created by calls to the same interface

     

    as a plus you get the possibility to

    - manage your dependencies

    - insert AOP

     

    and so on..

     

    Hope this helps you out

    Thursday, April 17, 2008 7:16 AM


  • Hmmm....

    I'd agree to an extent.  I wouldn't expect to change the code to switch testing code in and out, as the item being tested will change depending whether it is compiled for testing (debug) or production code, and thus the tests are not all that reliable, and not testing the same code, so I wouldn't have a great deal of confidence in the solution.

    On the other hand, designing to allow objects to be injected into another object, isn't a bad thing.  The fact that it is then used for testing is not overly relevant, so long as the same paths are used if the dependencies are injected, or if the code is created with default constructors, and the objects are encapsulated.  I think mocking and TDD create very loosely coupled, clean code, so the benefits outweigh any drawbacks from a little extra code to allow DI.

    My original aim was to allow the above, TDD, good solid unit test coverage, DI was the vehcile I used to achieve that.  The fact that is also opened up a whole new world of possibilities further adds to the strength of case that this is a good thing to use.  This was some time back that I started this, I have my team doing this now, and can confirm that this was a good choice when I made it.

    The extra benefits of enabling DI are wide ranging, the biggest being the ability to initially encapsulate things, but then being able to supply a new implementation at a later date.  That said, that could well be a poorly considered design, in that you break encapsulation, which is a workaround to a proper solution.  Ideally if something is likely to change often, that should be catered for by the design.

    My view is, even if all you use it for is 100% coverage unit testing, and nothing else, it is worth the effort.  It's the only way that I know to fully test the encapsulated functionality of a class.

    There are situations where using DI would clearly be useful as a pattern, and in that respect, DI needs to be considered as a possible design, on its merits.  Generally speaking in that case, I prefer the factory pattern, it's clearer generally than DI.

    Martin Platt.


    Friday, April 18, 2008 1:10 AM
  • I have to disagree here, you do not need any interfaces to implement mocking, you just need to choose the right mocking framework. I agree that DI is useful if you choose that route and if you do then the number of mocking frameworks available to you does increase, however it is NOT needed for mocking. I'm going on about this because it frustrates me that a number of people are saying to alter your code to use DI because you'll get mocking, it's just not true. You do not *need* DI for mocking. I'm not (currently) using DI and I'm happily using mocking in my unit tests without *any* changes to my domain code...(well actually I do declare them as internal and then make them available to my testing project). But to be clear, I'm not suggesting you shouldn't use DI, just don't use it because of unit testing alone.

     

     

     

    Friday, April 18, 2008 7:00 AM
  • FYI, and interesting post on the subject...
    http://scruffylookingcatherder.com/archive/2007/08/07/dependency-injection.aspx
    Saturday, April 19, 2008 9:20 AM


  • Okay, yes you can mock classes directly with the 'correct' choice of libraries.  That doesn't mean that you should though.

    The benefits of using an interface over a class are numerous, separation of concerns being one, cleaner SOA type implementations and so on.

    Declare what as internal and then make them available to the test classes?  That sounds like specific code in the classes to allow unit testing, and mocking, and is much worse than having a special constructor to allow DI.  I hope that that is not what you're saying?

    To me, the fact that you can use DI for mocking, as well as getting other benefits out of it, is a bonus.  The resultant code is worth it regardless, it is much cleaner and infinately more readable and well understood.

    I'm fully aware of the fact that you can mock a class, and that leads to coupled code, coupled on the concrete implementation, which is a reason why I wouldn't do it.  Adding a constructor, and designing the code to allow dependencies to be injected is a mind shift, but doesn't actually mean that you're writing code for testing.  Instead look on it that your allowing your code to be decoupled and in so doing, allowing it to be tested easily with interface based mocking.

    Personally I have seem major benefits of this approach.  Test coverage, decoupled code, clean and easy to refactor, and so on.  Dependency injection is a means by which this is achieved in my opinion, and a benefit is that it can also be used for other situations and scenarios if required.

    My point isn't that you can't do it without dependency injection, it's just that to do it properly and benefit from the approach of mocking the most, you would use DI.  My advice is to do this properly, and gain the most benefit, not that it is the only way.

    Martin Platt.
    Sunday, April 20, 2008 10:46 PM
  • 'My point isn't that you can't do it without dependency injection, it's just that to do it properly and benefit from the approach of mocking the most, you would use DI.  My advice is to do this properly, and gain the most benefit, not that it is the only way.'

    I think will just have to agree to disagree.

     

     

    Monday, April 21, 2008 8:49 AM


  • Now I'm confused, if you're saying that DI is the best way to go, but not the only way, then you're agreeing with me.  But doing it in a way that seems like you're disagreeing. 
    I don't believe I ever said that DI was the only way, I was merely giving my best advice.  I still stand by that advice, which it seems like you do to

    Okay, so we're agreed that to do mocking properly you use DI then?  Cool.  Agreed!

    Martin Platt.


    Monday, April 21, 2008 10:42 PM
  • LOL, you sly fox you. I'm not saying DI is the best way to go, nor am I saying you shouldn't use it. It's an option you evaluate to see if it meets your needs. For me I don't like it because, as I've said, I don't like changing my model to fit the framework, but that's my preference. But no I don't agree that to do mocking properly properly you use DI. I'll also expand on that, first off my comment about using 'internal' and then using the MakeInternalsVisibleTo attribute is that I prefer to have a single test project so I take it on the chin to basically have little or no 'private'. After all private/public/internal in .net is little more that an IDE\compiler nicety, it doesn't enforce anything. The benefit for me is that I can unit test the 'private' behaviour of classes (without using late binding) as well as the public interfaces, something I think is useful even if it raises some people's hackles. As for requiring the use of interfaces then again I don't see it. A unit test is effectively your contract about how something behaves. Now if you choose to implement those components via an interface or not doesn't affect that. If you choose not to use interfaces then some mocking frameworks require that you use interfaces and suddenly you're changing to fit the framework, that's what I don't like. Sure you can get into the whole, always use or only sometimes use interface debate but for me that's a different discussion. The link I posted goes into this mocking/interface debate, just don't expect to find an answer in there, just more posturing!



    Tuesday, April 22, 2008 4:54 AM
  • It's all starting to make sense.

    Right now I have some interface driven code using WCSF. To test my classes, I have used Typemock for isolation.

    I've read an msdn article on DI with the SPRING.NET framework and understand the concept a bit better.

    This brings me to one question: What signs in my code should I look for to consider DI? I mean, if there is a high coupling between two classes would that be an area I should consider DI?

    As I said above ("interface driven") all of my code is based on interfaces, but what happens when an interface is passed as a parameter into a function? See here: http://www.codeproject.com/KB/architecture/DependencyInjection.aspx

    So should I not be using DI by injection interfaces into my constructors?

    Thanks
    Wednesday, April 23, 2008 10:49 PM
  • I'm not sure I understand your question. Most, if not all (I could be wrong), DI frameworks will pass the interface (or rather the concrete implementation of the interface) into the constructor.

    The point of the DI is the, "make the decision of what to use at the last responsible time". I.e. the code that depends on the interface passed in, is "told" what concrete object to use at the last moment, or in DI's case when the object is constructed. So in theory all classes that depend upon another could be implemented using DI in order to reduce coupling.


    Thursday, April 24, 2008 6:12 AM
  •  

    Hi

     

    as for what signs, imho there are very little telltale signs, IOC is a design choice, DI is a side benefit Smile
    your application is already interface-based (which is GOOD ), so IOC is relatively easy to implement

     

    as for your question, interfaces as parameters (first without DI):

    consider the following

     

    Code Snippet

    class TestOne{

    void DoSomething(){

    IService svc = Container.Resolve();

    svc.SomeMethod();

    }

    }

    class Usage{

    void Test(){

    new TestOne().DoSomething();

    }

    }

     

    or

     

    Code Snippet

    class TestTwo{

    void DoSomething(IService svc){

         svc.SomeMethod();

    }

    }

    class Usage{

     void Test(){

        new TestTwo().DoSomething(Container.Resolve());

     }

    }

     

     

    In my opinion, the first example requires less coupling as you don't have to know anything about the DoSomething() method.

    If you know want add DI into the mix (i'm using Unity for this example), you could do something like the following

     

    Code Snippet

    class TestOne{

    private IService svc

    public TestOne(IService svc){

    this.svc = svc;

    } // constructor injection

    void DoSomething(){

    this.svc.SomeMethod();

    }

    }

     

    //Usage => resolve testone from container

     

     

    or

     

    Code Snippet

    class TestOne{

    [Dependency]

    property IService Service {get;set;} // property injection

    void DoSomething(){

    Service.SomeMethod();

    }

    }

     

    //Usage => resolve testone from container OR call container.BuilUp

     

     

     

    In the end i prefer to let my container do the creation and DI of my objects (i'm lazy Stick out tongue)

     

    for some more information about unity see here

     

    Hope this answers your question

     

    Thursday, April 24, 2008 7:59 AM
  • Hi guys,

     

       I dare to say, as a conclusion of all posts on this thread that the story about DI starts on the root of basic design patterns (the ones enlisted on the best-seller GoF book)

     

       The Strategy pattern seems to be a good way to separate the major activities of an algorithm from the internals of its implementation. That way we don't need to get married with any specific implementation of the algorithm (let's call each "a strategy") but we can generate several and eventually change the strategy at our conveniency

     

       However, linking a given strategy with classes that will use it may need a 2-step process:

    1. Instancing the chosen strategy (for instance via the Factory method pattern)
    2. Assigning the created instance as a dependence (i.e. a property) of its "clients"

       This model, put in practice, may require other features like instance control. For instance, if a given strategy will be used by several consumers, should they instanciate a separated object each or they might share just a single one?

       Derived from that, what about the GoF implementation of the Singleton pattern? Its original intention is avoiding a proliferation of instances when one is enough for the whole application scope. However the original GoF implementation (based on assignments made directly to the singleton class via the static keyword, what turns inheritance useless as whatever is the descendant class, if we call the SingletonClass.GetInstance() class-level method, the returned instance will always belong to SingletonClass, so in order to get the single instance of a descendant, we need to call the overwritten version of InheritedSingleton.GetInstance()

       The resulting aftermath of all these is a strong coupling between strategies and their consumers

     

       A dependency injection framework helps get the best of GoF patterns (in terms of clarity, maintenance and low coupling) without staying tangled in their drawbacks

     

       As some of you guys gave as example, using mocking techniques for testing purposes, etc is a way to put the strategy pattern in practice once again, so applying a DI framework is a good alternative, as it will be any other alternative where we need to follow a single algorithm with the chance of varying its internals. You'll find plenty of examples: a billing system where each service has a particular way to be billed, a mortgage application where loans are being lent but with different amortization mechanism (let's say, french, german, etc). And many many others

     

     

     

       Hope that helps

    Tuesday, May 20, 2008 8:46 PM