Getting rid of IoC

What is the point of IoC?

It’s not cleaner code. It’s not convenient unit testing.

It’s seamlessly interchanging implementations of interfaces.

I think you will agree with me on this: How often do you really need to do that? Almost never.

So go ahead and replace the following code:

class Rock {
	private Instrument guitar;

	public void setInstrument(Instrument instrument) {
		this.guitar = instrument;
	}
}

with:

class Rock {
	private Instrument guitar = new Guitar();
}

This is actually cleaner (one less method). And we probably got rid of some XML somewhere in our app…

So how do we unit test the Rock class by providing it a stubbed or mocked instrument? Easy: Reflection. Reflection has three really useful features: Get and set private field and invoke private method. So the test could be:

class RockTest extends TestCase {
	public void testShouldPlayGuitar() {
		Rock rock = new Rock();
		Instrument stubbedGuitar = RockObjectMother.gibsonSg();
		TestUtils.setPrivateField(rock, "guitar", stubbedGuitar)
		assertEquals("guitar bite", rock.play());
	}
}

Now, I’m not saying IoC is bad and I’m not saying don’t use IoC. What I’m saying is: Use IoC when you need it and use it for what it’s for.

Thanks to Stuart Caborn and David Reed for reminding me that Reflection is not all that bad.

21 Responses to “Getting rid of IoC”

  1. Ricky Clarkson Says:

    1. IoC

    I can do the IoC way without any extra methods. My preferred idiom is the anonymous class. Compare:

    Rock rockOn()
    {
    return new Rock()
    {
    private final Instrument instrument=new Guitar();
    };
    }

    Rock rockOn(final Instrument instrument)
    {
    return new Rock()
    {
    };
    }

    Now which is cleaner? In this case, the IoC way.

    2. Reflection

    Reflection doesn’t really fit in a statically typed language. When you refactor, you want as much help from the compiler as you can muster in Java. Reflection bypasses the compiler, so you see the errors when you run the code instead. Also, support from your IDE might not be that useful either, depending on how you write your reflection.

    I prefer writing two interfaces; one used for testing, and one used for normal code.

    Further, I prefer writing one interface, and having my automated tests run against that. That way my code coverage results will reflect the actual usage of the code, and not just what I’m exposing to automated tests via reflection or via a second interface. Also, it will quickly expose any inflexibilities in my APIs.

    Cheers.

  2. James Mead Says:

    In Ruby you can do something similar using Mocha as follows…

    class Rock
    def initialize
    guitar = Guitar.new
    end
    end

    class RockTest ‘result’)
    Guitar.stubs(:new).returns(stubbed_guitar)
    rock = Rock.new
    assert_equal “guitar bite”, rock.play()
    }
    }

    You might also be interested in this article.

  3. afsina Says:

    actually you should prefer constructor based injection. that would make your code cleaner. IOC’s spirit is all about plggability, in many applications telling private Instrument guitar = new Guitar(); is not a good solution when there is not only a ClassicGuitar but also an AccusticGuitar.. you will immediately feel the fire after the dependancies are piled up. sure, what i usually suggest, resist until the last point before using the IOC, and do not use a heavy weight one (like spring) for your small applications. you can roll your own or use picoContainer or something if you think it is necessary.

  4. Alan Green Says:

    While your approach certainly gets rid of an icky XML file, it clutters up the unit tests considerably. Depending how much configuration you end up doing in unit tests, that may be a problem. It certainly would be in my application.

    The main advantage we get from IoC is that it causes me to think about my application’s internal components in a different way. I think our application’s has more cleanly defined components as a result, making them easier to test and easier to maintain.

    You would be right to say though, that that’s something we could have achieved without Spring, if only we’d been careful with our design.

  5. kofno Says:

    IoC as an approach to software development is a good thing. Maybe using an IoC container is overkill, but IoC does make your code cleaner. It also will make your tests cleaner. After all, unit tests are also part of your code documentation.

  6. Jeff Says:

    Hi George,

    Alot of good points were made in the comments above, but one I think was implied by or with the given arguments was communication. IoC patterns communicate more to a reader of the code, or a reader of the tests.

    In addition I try not to know how many implementations of a given interface exist or should exist. Leaving the interface door open to others who need to solve new problems can be a big help. I have spent many a maintenance day introducing Interfaces to solve problems in testing or strategy introductions because “there is only one implementation” was used as an argument to remove an interface some time in the past.

  7. Jacob Briscoe Says:

    IOC is simply an enabling technology, it enables your code to evolve. Without IOC and IDD (Interface Driven Development) code becomes much more difficult to change because, instead of a container managing your instances YOU are managing your instances throughout your system. This will lead to more difficulty in debugging and flexibility in the long-run. BTW, try to change a class name or way you would like to enforce instance creation of a class used throughout your system without IOC and a decent IDE! Good luck! You’ll need it.

  8. Tom Says:

    > I think you will agree with me on this: How often do you really need to do that? Almost never.

    Great post. Java doesn’t have to be hard. We just seem to get obsessive-compulsive about making it hard on purpose.

    In fact, just make it a public field and dodge the reflection and the getters/setters. (Oh no, I’ve spoken heresy!)

  9. Matt Savage Says:

    I’m with George, with a strong note of caution.

    I think there were several places in our codebase where it was very VERY clear that there would never be more than one implementation of a particular piece of behaviour (so much so that we didn’t even have an interface). In these places it felt very comfortable to mock dependencies by using reflection to set private fields rather than using constructor or setter injection.

    From memory, these tended to be cases where we were effectively moving behaviour from supporting private methods of one class in to a class with a narrower set of responsibilities because the parent class was getting too big and becoming incoherent.

    Not exposing dependecies which are really REALLY not expected to be substituted keeps the interface of the class cleaner and avoids the confusion of having Foo and DefaultFoo classes hanging around. Things like builders and adapters when there’s only ever one way to turn a Foo into a Bar in the application. Why bother using an IoC container to configure this kind of thing? It’s just messy and doesn’t express intent.

    However, this does risk devs without a clear understanding of the reasons for eschewing constructor injection in this specific case repeating the pattern in places where it’s inappropriate. If you’re worried about this on your project, I reckon it’s probably best to standardise on commonplace IoC patterns.

    As far as IDEs and refactoring goes, if you name your fields after the class they contain, any decent java IDE will pick up the refactoring. And even if it doesn’t, the break will turn up immediately when our comprehensive suite of unit tests fails, right? ;o)

    Matt

  10. Peter Hendriks Says:

    Well, having to resort to reflection “to get rid of IoC” seems to me like missing the point entirely. Injecting through reflection is still, well, injection, so you are still using IoC, just not in the Spring/Pico/JEE 5 way.

    If you _need_ to change stuff from outside your component, why not just make the constructor/setter injection? Reflection won’t get picked up by IDE tools when refactoring, is not typesafe, etc etc. Matt: try refactoring 2 variables (types), then run the tests and see what breaks. This stuff gets very hard, very fast. And how about possible lifecycle issues, like when the “guitar” variable in above example is used in the constructor?

    IoC also is not for the simple HelloGuitar objects. Real dependencies need configuration, other dependencies etc of their own. You either need to program objects als self-configuring objects (which add a lot of complexity), or program a factory. Suddenly, an XML file that does this all for free does not seem that bad at all…

    With IoC you recognize that your app may and probably will change over time. It is _very_ easy to stub components when testing (not just unit testing). If you use business interfaces (a best practice anyway), then setters in the implementation are not noticed. Any decent java IDE will collapse these setters anyway… ;)
    Of course IoC is not always appropriate and not a final solution. But when you have to use reflection to work around a setter, maybe it’s time to reconsider.

  11. k-man Says:

    Just thought I’d throw this out there - clean code is a subjective term that gets used and abused….less code is not necessarily cleaner code…using the aspects of the language in an intelligent understandable way makes code easier to follow, even if it takes more keystrokes…. someone mentioned reflection — sure you could bypass every mechanism that java has in place through reflection…you could use one static method to accomplish everything you want to do…..not bothering with coding all those nasty objects and method names…. :) cleaner - I don’t think so…..

  12. Marcus Ahnve Says:

    While I agree with with the “use IoC for what its for”, in my opinion IoC is not about changing implementations. It is all about getting rid of dependencies, which in turn enables modularized code.

    I normally encourage the use of IoC between layers, so that the view layer does not access the logic layer directly etc. IoC within layers is normally overkill.

  13. Matt Savage Says:

    To be clear,

    (and George, please correct me if I’m misrepresenting you)

    1. Nobody’s advocating using this technique anywhere other than in unit tests.
    2. Nobody’s suggesting there isn’t a place for IoC containers, just that wiring up everything and its dog in Spring IoC is often overkill.

    What George is talking about is things a bit like this:

    class Jimi {
    private Instrument instrument;

    public Jimi(Instrument instrument) {
    this.instrument = instrument;
    }
    }

    We all know Jimi’s always going to play guitar. If Jimi’s not playing guitar, that’s not really what we wanted. So why bother exposing it? Why not just say:

    class Jimi {
    private Instrument instrument = new Geetar();

    public Jimi() {
    }
    }

    We’ve expressed the intent that Jimi should ALWAYS play guitar. We’ve avoided some more unnecessary configuration in our IoC container.

    This is all to the good, shurely?

    A better, real-world example would be a service that uses a builder to create one object from another (a Foo from a Bar). It’s a reasonable expectation that there will only ever be one way you can make a Foo from a Bar in your system. So why bother injecting the builder into your service? Why bother even suggesting there will ever be another type of builder in your container configuration?

    What I like about George’s post is that he’s challenging all those well-ingrained architectural decisions we make (thou shalt use an IoC container EVERYWHERE) and pointing out that actually, a lot of the time, we make more work for ourselves like this.

    Sometimes this is a bad idea on the basis that it’s better to have a consistent architecture that leads to over-engineering in some places. On the project we’ve just come off, I don’t think that was the case and this technique worked well for us.

  14. Pat Says:

    Though I think I understand what George is trying to say, I think the post is a little bit extreme.

    I dislike the example above because the dependency injected looks more like state based DI instead of role based DI.

    One tangible benefit I have seen using DI properly is that I can move aspects from one implementing class to another, and I don’t break any consumers. In the above example, if I moved the role that the Guitar actually played to another class, I would be forced to change the Rock class (blech!).

  15. Solomon Says:

    FYI… I have a trackback (When to user IoC) at http://jroller.com/page/Solomon?entry=when_to_use_ioc

    Javalobby: (Is IoC / Dependency Injection Overated?) http://www.javalobby.org/java/forums/t78371.html

    I have a question about your entry:

    1) Do you really think that people advocate “thou shalt use an IoC container EVERYWHERE?” Even if some do, I would suspect that the majority of pro-IoC container developers don’t think that it’s useful EVERYWHERE.

    2) What kind of container do you recommend for large projects? J2EE containers came about because of a need for containers in LARGE project. Heck, even Tiles has a container… You need some method of managing dependencies.

    3) Your example is a Domain object. IoC’s generally help manage configuration of the view, service and persistence layers, where interfaces and configuration are much more important. IoC/AOP in the Domain layer is most definitely a controversial. What exactly was your intention by using a domain-type argument? Was it to prove that IoC is overrated or that IoC is not applicable for THAT particular case?

    I personally like what IoC and IoC Containers can do for me. They do pay the bills right now. However, I’m always on the lookout for other advancements in technology theory and practical use. I’m also looking for clearly stated “best practices” types of advice and discussions as to when to use something and when not to use something. IMHO, IoC Container (and specifically Spring Framework) “best practices” are still emerging even after almost three years of IoC being in the lime-light.

    With that said, thanks for the post. It definitely brought about some interesting discussions.

  16. Jeff Says:

    I am suspicious of someone saying Jimi will always play a guitar.

    If he were alive today we may have seen him do some interesting things with other instruments. I certainly bet he would not like to discover he had been constrained such that he could only ever play one instrument.

    It is kind of like the hammer thing. If you get told that every problem in the world must be solved with a hammer then you are less likely to think about that screwdriver in the corner.

  17. Matt Savage Says:

    [Testing whether I can use   characters to format code]

  18. Matt Savage Says:

    > IoC’s generally help manage configuration of the view, service and persistence layers, where interfaces and configuration are much more important.

    …for which I think they’re great.

    > Your example is a Domain object…

    You’re right. This is an inappropriate use of IoC, and that’s the point.

    A more real-world example would be this:

    class PaymentService {
        private PaymentRepository paymentRepository;
        private PaymentBuilder paymentBuilder;
        private MainframePaymentMessageBuilder mainframeMessageBuilder;
        private MainframePaymentsService mainframePaymentsService;

        public PaymentService(
                PaymentBuilder paymentBuilder,
                MainframePaymentMessageBuilder mainframeMessageBuilder,
                PaymentRepository paymentRepository,
                MainframePaymentsService mainframePaymentsService) {

            this.paymentBuilder = paymentBuilder;
            this.mainframeMessageBuilder = mainframeMessageBuilder;

            this.paymentRepository = paymentRepository;
            this.mainframePaymentsService = mainframePaymentsService;

        }

        public void makePayment(PaymentDocument document) {

            Payment payment = paymentBuilder.buildPaymentFrom(document);
            PaymentMessage paymentMessage = mainframeMessageBuilder.buildPaymentMessage(payment);

            mainframePaymentsService.makePayment(paymentMessage);
            paymentRepository.save(payment);

        }
    }

    In this instance (which is a _simplified_ real-world example- and please ignore all the irrelevant bad things in the design of this class) there’s absolutely no need to inject the builders. The repository and the other service, yes, but not the builders.

    It’s so, SO easy to forget that what you’re injecting is a domain object (see: FooBuilder example in my comment above). I for one have had to stop myself a couple of times automatically adding another constructor argument for something that should only ever have one implementation anywhere in the system. The smell here is seeing what should be domain objects with a single implementation popping up in your IoC container config.

    > I think the post is a little bit extreme.

    The title of the post is extreme, this: “What I’m saying is: Use IoC when you need it and use it for what it’s for.” is probably more like it.

  19. Matt Savage Says:

    …and the thing is it’s doubly hard to do what I think is the right thing and remove the builders from the constructor (or delete the setter or whatever) if you find yourself wanting to mock them out in tests.

    Which is why I originally decided that setting the things through reflection in tests was better than messing up my classes by introducing a PaymentBuilder interface with a DefaultPaymentBuilder, PaymentBuilderImpl or something equally nasty. Which also suggests that we might acutally want to replace the builder classes with a different implementation later (which we never will, because there should only ever be one way to make a Payment from a PaymentDocument).

    *takes deep breath, steps away from the keyboard*

    Please excuse the huge volume of posting- I’m sure this can be explained in less words.

  20. Matt McGill Says:

    What you’re saying about polluting constructors with extra parameters is definately resonating with me, but I’m still not convinced that using reflection to get at private members is such a hot idea, even in this case. Just today I’ve encountered a few situations along these lines, and I fell back on using template methods to ‘inject’ the desired class. Something like this:

    public abstract class AbstractJimi {
    protected abstract Guitar createGuitar();
    private Guitar guitar = createGuitar();

    }

    pubilc class Jimi extends AbstractJimi {
    protected Guitar createGuitar() {
    return new Guitar();
    }
    }

    Still not as ‘clean’ as you’d like, I know, coming with the cost of an extra class. But it does allow you to mock Guitar in a unit test without reflection, and it doesn’t require a factory interface/mocked factory/factory implementation trio. I think this one just comes down to preference at this point.

    -Matt McGill

  21. David Billskog Says:

    I’m a bit new to dependency injection but why don’t we just inject a ioc container to every class that has a dependency? We could then mock/stub the container when testing. This would also reduce the need for the extra buzz of factories everywhere we need to create objects.

    Pros:
    Doesn’t pollute constructor with more then one parameter (replacing constructor injection).
    We have a consistent use for all classes so we don’t have to think about it and thus decreasing our cognitive load when programming.
    We may be able to remove some factories.

    Cons:
    Simple classes may be a tad more complex.
    It will have to be combined with a mock library.
    It may be harder to understand testcases before you know the approach.

    I bet there is something i have missed… :-)