Too many dependencies?

Over the weekend I blogged about a recurrent issue I encounter when looking at tests, which is the encapsulation of the Arrange part of the Arrange-Act-Assert pattern in either setup methods or base classes. Although there are justified use-cases for it, the majority of times it’s a sign of a code smell.

The example I put was one of a Controller having too many dependencies, and I was asked a few times how to avoid this problem. The purpose of the blog post was not around this issue itself but around test setups. However, it is a valid question, and one that has been raised over the past months questioning the usage of IoC Containers.

So I wonder, do you think this is a problem? If so, how many dependencies is too many? How would you avoid it?

 

16 thoughts on “Too many dependencies?

  1. alastairs

    Mark Seemann (@ploeh) talks about this very problem in his book Dependency Injection in .NET. He talks about refactoring away from Constructor Over-injection by introducing Facade services that provide the necessary behaviour.

    So, for example, I suspect that the AccountService, EmailerService and AddressService could be combined under one simpler CustomerAccount interface; the SalesService, IncentiveService (which doesn’t appear to be actually used!) and CartService likewise under a simpler CheckoutService. The idea is to find related responsibilities so that you haven’t just moved the “WTF?” moment to the Facade services instead and there is a measure of coherence to the Facade.

    You should ultimately be able to get the number of dependencies down to a more sensible level using this technique.

    Reply
  2. Frank L. Quednau (@fquednau)

    The above problem is rather a symptom than a problem of itself. It shows a controller that does a lot more than setting up adequate views. What can also help is having some infrastructure that allows to express commands that can run in a different context than the controller (see e.g. ayende’s stuff on reducing abstractions)

    Reply
  3. Mogens Heller Grabe (@mookid8000)

    Yes, too many dependencies is definitely a (sign that there might be a) problem.

    I avoid it by having an automated test that reflects on constructors of all classes that will be put in my container, Assert.Fail-ing with a nice explanation for all types that violates a max 4 dependencies rule, referring to a chapter in Mark Seeman’s book where he talks about the “Facade Service” pattern 🙂

    Whether 3, 4, or 5 dependencies is too many isn’t so important in my opinion – it should be high enough that you can get some actual work done, and low enough that you get a slap in the face if you’re doing something stupid 🙂

    Reply
  4. uluhonolulu

    The problem is not with the dependencies, but rather with too many responsibilities. Many dependencies is just a smell.

    If you have many methods each depending on one or two of these services, it’s time to split your controller into several ones. If you have just one method that uses all these services, the method is probably too big.

    Reply
  5. seanparsons (@seanparsons)

    I wrote a gist demonstrating this exact issue in small scale: https://gist.github.com/2127688
    That seems sensible, but now start adding caching, split your reads and writes out, add metrics…All those things keep getting bolted in and make it hideous beyond all imagining.

    OOP is the problem here, it effectively encourages anti-patterns like the big ball of mud, as programmers we’re fighting against that gravity.

    Reply
    1. alastairs

      I disagree that OOP is the problem, and I don’t believe it does encourage anti-patterns in and of itself. It’s true there is a lot of poor OO code out there, but OOP provides a huge number of benefits in writing and reasoning about code, and it feels a bit like throwing the baby out with the bathwater to call OOP the problem.

      Further responsibilities such as caching, auditing, performance counting, etc., can be added in a SOLID way through the use of Decorator classes, or, better still, via dynamic interception with an IoC container.

      Reply
      1. seanparsons (@seanparsons)

        All of the benefits you describe above can be done more easily and in my opinion more correctly with functional code. Dynamic interception through IoC is the most complex way to solve the simplest problem and Decorator classes are more easily represented by a function.

  6. Craig

    That controller scares me. If you have services to handle your business processes, why does the controller have to marshall that many services? Either the controller doesn’t have a single responsibility and should be split up, or the services are too specific and should be generalised (or, as alastairs says. combined into Facades).

    I would say that as soon as you have more than 2 or 3 dependencies, you need to justify why.

    Reply
  7. craignicol

    That controller scares me. If you have services to handle your business processes, why does the controller have to marshall that many services? Either the controller doesn’t have a single responsibility and should be split up, or the services are too specific and should be generalised (or, as alastairs says. combined into Facades).

    I would say that as soon as you have more than 2 or 3 dependencies, you need to justify why.

    Reply
  8. jeyoung

    A bridge class is the correct place to manage so many collaborations between the controller (UI) and the various services (subsystems).

    I would have a controller constructor like the one below.

    public CheckoutController(ICheckoutControllerOut checkOutControllerOut) {

    }

    The implementation of ICheckOutControllerOut will be instantiated with the proper relationships to the various service classes.

    This way, the controller (UI) is completely decoupled from the services (subsystems). See Shlaer-Mellor writings for more details.

    Reply
  9. Pingback: Solving the Too many dependencies problem « Hadi Hariri's Blog

  10. Pingback: Dealing with the “Too many dependencies” problem « Hadi Hariri's Blog

  11. Marc Chouteau (@chouteau)

    What scares me is people who can say it takes 3 per class dependencies, it is dogmatism that leads to “Analysis Paralysis”.

    What matters is to respect ISP, each service must have its liability established.
    Regarding the case of a cart management there are a number of constraints that are unavoidable, you can return the problem in every sense, a one point you will deal.

    – The management of the basket
    – User management
    – The management of conversion command
    – The coupon management
    – The fraud management
    – Methods of payment
    – Management of shipping

    I pass on technical classes such as caching or sending email.

    To this I add that the number of steps may be different for different customers

    If someone has the solution to reduce these problematics in 3 dependencies I’m interested;)

    Reply
    1. hhariri Post author

      3 is a sample. I don’t vindicate 3 or 4 or 5 or 2. It’s about knowing when something is wrong. And I think in this case, you have a lot of concerns that do not belong to the controller.

      Reply
  12. jeyoung

    The orchestration of the collaboration between these various services is definitely not a responsibility of the controller.

    The controller is a UI concern. Its remit should be limited to triggering events to a “bridge” class telling it what is happening in the UI and to synchronise the display of views or redirects based on the response.

    Hadi is right in that the decoupling should be more than just about implementation, it should be also about responsibility decoupling.

    Reply
  13. nrolland

    It is a legitimate concern, that arises for legitimate reason.

    Sir Mark Seeman calls that constructor over injection.

    If you have not read his book I suggest you take a look it is worth it. He actually uses this refactor operation as a nice opportunity to get domain insights.. 😉

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s