What is the tradeoff with Inversion of Control (IoC)


Recently, I caught wind of a discussion about use or overuse of Inversion of Control and Dependency Injection.  One small team was quite religious about using it, while another was, let's say, a bit more circumspect.  It made me think about where I would put IoC into the pantheon of silver bullets...


Inversion of Control is a good pattern.  You get more testable components and it reinforces good design.  IoC does not replace good design.  That said, the problems you can solve with IoC, while important, are a small subset of really big issues.  It is perfectly appropriate to care about using IoC patterns, and I’m a fan of Spring.Net and Unity.  However, IoC can only solve a small number of problems.  Its value is specific to the context in which it is applied.

When should it be used, and when should it be avoided?

All quality attributes must be examined with each effort.  How reliable is the software?  How secure is the software?  How maintainable?  Gabriel Morgan does a good job of describing 12 quality attributes that he thinks are important in this blog… and I quote him often.

To everything, there is a tradeoff.  IoC is very useful for software that is carefully crafted by hand and operates in an environment where limited and secure access to the environment is absolutely insured.  If you have a configuration file that controls the application, and a bit of malware works its way onto the box, a simple change to a config file can inject truly nasty functionality directly into an application.  Imagine that your application is an e-commerce web site, and the malware hijacks credit card info simply by changing the config file, thus inserting itself into the exe!  If the system is to be installed on the client machine, this problem becomes, if anything, worse.  This is because your name is on the “front” of the application, while anyone else’s code can be running in the guts, without any way for the user to “remove the add-on.”  It may not be acting as an add-on at all.  A malicious change to the config file can replace huge swaths of functionality, in a way that can be quite difficult to detect.  So, I’d say that IoC is a maintainability item with a solid tradeoff with application security.

IoC also has a complexity tradeoff.  Applications that are wired together with IoC may not be the easiest to understand or debug.  If every single class has to be injected, then you have added a layer of complexity to the coding and debugging effort.  Sure, you can train folks around that, but it is a tradeoff, and one that you have to consider.  I remember a “fad” where every class had to have a factory, because using the ‘new’ keyword was evil.  I also remember IT dev managers complaining that they had to spend double on a maintenance cycle to rip out about 80% of the factories because they added complexity for classes that were never reused.

I love IoC, but I’m not religious about it.  I use it sparingly, to inject major sections of code into an executable.  I do believe it is very easy to overuse IoC.  Think of it like over-the-counter pain medicine: take a little and a head ache goes away, but don’t overdose.

Comments (18)

  1. Casey says:

    Good points … but please be careful to contrast Dependency Injection or Dependency Inversion with an IoC container …

    Most of the problems you describe are related to poor use of a container, not around the DIP pattern itself.

  2. NickMalik says:

    You are right.  

    There is a difference between the Dependency Injection pattern and a lightweight container.  The latter is one way to implement the former.  

    To be fair: The original discussion that triggered this blog was around the use or overuse of the container as a software practice, not really about the pattern itself.  I’m a big fan of the dependency injection pattern.  

    Note that Martin also brings the two together in his online papers, discussing the concept of the pattern and then discussing how it plays out in the container software.  There’s a difference, conceptually.  In the minds of the folks doing the work, with fingers on keys, I think the distinction blends away.  Advice for one applies to the other.

    Good call out, Casey.  Thanks.

    — Nick

  3. Just wondering what your thoughts were to creating an application to manage dependencies (instead of configuration files).  I put together a quick POC to use a SQL Server 2008 db to stored and get my containers and type info.  I’m thinking about working on a front end for it.  Daydreaming about using something like VS.NET extensibility to use the vs ide to wire up the application.  Still just POC, but it is working out.

  4. Nick, I’m afraid I feel very differently then you do on this topic. If anything, I think that the Dependency Inversion Principle, IoC, and Dependency Injection are widely underused by the Microsoft community.

    I’m feeling that this post almost (keep that almost in mind) goes to the analogy of Theory of Evolution vs Theory of Creation.

    One is backed by vast quantities of scientific and empirical proof. The other by beliefs.

    In terms of learnability – well, new developers always take a month or two to get fully up to speed, no matter what you’re doing. If anything, working in a standardized way (and I know how much you like those) will decrease learning time (definitely in the long run, often short term as well).

    And on the point of security, well, if a hacker has write access to a users machine – it’s pretty much game over for that machine. If you aren’t using IoC, it won’t make any difference. Hackers can still show your splash screen and whatever else they want. They’ll have full access to the users data. In short, security is not a reason not to use IoC.

    Given all that, I wouldn’t upgrade some of the "gnashing of teeth" around containers to a full-blown tradeoff around IoC.

    Looking forward to a follow up post 🙂

  5. NickMalik says:

    Sounds interesting Mark.  I have no problems with it, and in a way, it is more secure than the config file.  It is a bit more complex, but the complexity could be hidden.  Also allows for remote configuration control, as well as shared configuration, which could be helpful if you have 100 servers, all of which must be configured in the same way.  If they refer to the same db record, or at least the same db, then it would be simpler for an administrator to update them all.  

  6. NickMalik says:

    Hi Udi,

    I have great respect for you, so I’m going to think about my response a bit before I post something to the blog.  You have given me food for thought.

    I don’t think that "gnashing of the teeth" is a good reason to avoid a good idea.  I remember when folks were gnashing their teeth at the idea of creating objects… procedures could do the same thing, after all.  (Yes, I’m that old).

    I also have fairly clear, and recent, memories of dev managers who had to live with young, eager developers who wildly overused certain patterns, especially factory patterns, to the detriment of the readability and maintainability of the code they were writing.

    Dependency injection is good for all the reasons I said in the post, and a dozen more.  I said that I love DIP and IoC, and I stand by that.  Is it underused, in general.  I don’t know.  I don’t work ‘in general.’  I work in a large, chaotic, and wildly creative IT department staffed with some of the most passionate and opinionated developers on the planet.  We seem to attract superstars.  It’s nice, but noisy.

    So religious debates, whether creation vs. evolution or DIP vs. OOP, are a topic to be treaded lightly.  Creating noise and heat does not deliver code, and it does little to nothing for quality.  Clear statements of benefit go a long way.

    So far, I’ve seen debates a-plenty on every topic under the sun.  This is better than that.  Very few numbers.  

    Are there numbers that show that software written using an IoC container is measurably easier for a team to maintain?  Does it matter if it is the same team?  Who studied it and how big was the study?  Did the study include the costs of training both the dev and support teams?  What are the costs of transitioning both dev and support over time, when there is a large base of existing, non-IoC code that will consume over 80% of the time of a support developer, no matter how much you train them?  These are the questions I get hit with when I propose a change.  So I propose changes carefully.

    If you have the facts and figures, I want to see them so I can use them.  Like I said, I’m a fan of IoC but I have no evidence that it works to increase quality, improve testability, or reduce costs of maintenance.  I’d love to get that.  If there is science on the side of IoC, I’d love to benefit from it.

    That said, this is NOT my main fight.  I think there are bigger fish to fry than whether the code is well written.  The fact that we are paying people to write code that no one needs… that is more important IMHO, and won’t be settled when we deliver REALLY CLEAN code that no one needs.

    — Nick

  7. Evan says:

    For the record, I hate it when people try and compare pragmatism and religion.  I don’t have any studies to show that increased usage of IoC increases maintainability, but I’d be willing to bet you don’t have any studies to show that "overuse" (whatever that means) hurts maintainability.  Sure you can argue that increased complexity hurts maintainability, but it’s still a study-less argument.  There aren’t studies on either side currently.

    I could make a similar comparison about the pragmatic use of "SOA" being borderline religious, but that too would largely be a pointless and vague argument.

    Although I would agree if you said: IoC increases maintainability. Not all applications place a high priority on maintainability.  Therefore, not all applications need liberal use of IoC.

    I do have to say though that I think the pattern is generally greatly underused in the enterprise business app world (where maintainability is usually one of the highest concerns).

  8. NickMalik says:

    Hi Evan,

    IoC, when used correctly, has the potential for improving the maintainability of business applications.  Some organizations may find it easier (or less expensive) than others to gain the maintainability benefits of IoC.  Therefore, each organization that is interested in systematically improving application maintainability should investigate if this technique would be useful, and if so, should implement and encourage the increased use of lightweight containers in all appropriate software development efforts where the tradeoffs are understood and accepted.

    Is that close enough?

    — Nick

  9. I started an interesting thread when I weighed in on the use of IoC and the Dependency Injection pattern

  10. I started an interesting thread when I weighed in on the use of IoC and the Dependency Injection pattern

  11. Max says:

    Nick,

    Before we start such debates, it would be nice to define what we mean by maintainability – I’m almost sure people contributing to this thread have different ideas.

    So, what is your definition?

    Max.

  12. NickMalik says:

    Hi Max,

    I made reference to Gabriel Morgan’s blog that defines the quality attributes, including maintainability.  

    Maintainability is:

    ·         The aptitude of a system to undergo repair and evolution. (Barbacci 2003)

    ·         The ease with which a software system or component can be modified to correct faults, improve performance or other attributes, or adapt to a changed environment. (2) The ease with which a hardware system or component can be retained in, or restored to, a state in which it can perform its required functions.  (IEEE Std. 610.12)

    Does that answer your question?

    — Nick

  13. Max says:

    Nick,

    This definition is very general and doesn’t really provide good basis for evaluation of which design is more maintainable or if certain mechanisms such IoC increases maintainability.

    When we talk about maintainability we first need to define likely changes that can occur over system lifetime and only then we can tell that design A is more maintainable than design B. If you believe you have a maintainable design, I will easily propose a change that will completely ruin it.

    I can think about certain changes that can be easily accomplished using IoC, but asserting that if we use IoC we will always end up with maintainable system is incorrect. BTW, same is true about SOA, as well as OO and other methods.

    Max.

  14. NickMalik says:

    Hi Max,

    You are right, of course.  There is no "magic bullet" for maintainability.  Everything is a tradeoff and "ultimate maintainability" is so expensive and difficult that you gain little by attempting to achieve it.  The same would apply if you focus in ANY of the quality attributes without considering other ones.  Ever tried "ultimate security?"  That puppy costs a lot!

    How about "ultimate auditability?"  I had requirements for that one once.  We pared back hard when we made it clear to the business that they could get "good enough auditability" for about 20% of the cost of what they spec’d.

    The definition is general because it is a guideline that helps architects create, on a system by system basis, a definition of "sufficient maintainability" useful for evaluating the design of a system.  Clearly, I’m blogging, and not about a particular system, so I’m in the same "general" space as that definition.

    I agree completely that the architect would create a useful definition that the system must use when evaluating if the coding practice is useful.

    That said, and I will not leave this point alone: a disruptive or revolutionary practice can ONLY deliver benefits if you consider the people, processes, and organization in which the code will be maintained.  If you use IoC in dev, and give it to a support team that doesn’t understand IoC, or cannot maintain the sufficient knowledge base to leverage it, you gain nothing.  IoC is dead on arrival in that case, regardless of the use case.

    Revolution requires indoctrination.

  15. Alex says:

    Security: The confguration does not have to be file based. It can also be stored as a resource in a [signed] assembly, or done in code. (Castle supports both directly.)

    Complexity: I’d like to see containers provide a way to dump upon request the graph of component instances and their wiring, as instantiated, preferrably in a way that can be visualized.

  16. NickMalik says:

    Alex,

    Certainly, placing the configuration into a resource file or into code will moderate the security risk.  That is a tradeoff as well, because it limits the ability to modify the configuration, especially "on the fly" or using remote config mgmt.  For those folks who are happy with this tradeoff, then you get the benefit of slightly more secure code.

    In hindsight, I probably should not have bothered with the security objection, because that is a "small" problem when compared to the organizational problem that comes with fundamentally different coding techniques.

    And that’s what exhibits as ‘complexity.’

  17. As Grigori Melnik noted on my blog previously as well as his own , there was a brand new drop of the

Skip to main content