62

I've been using manual constructor injection DI for a little bit now. One thing that I notice is that my constructors are starting to get rather long.

I have a class that depends on a bunch of little objects - anywhere between 6 and 10 sometimes. As I continue to break my application into smaller chunks, I could see this number increasing over time. Is this a common problem?

Obviously this is going to depend a great deal on the project. However, the basic question is this:

When do you start to get uncomfortable with the number of dependencies that a class has? What are some strategies that you use to reduce these dependencies?

Runcible
  • 7,006
  • 12
  • 42
  • 62

6 Answers6

27

I would not worry about it.

Instead, I would worry about the class being too complex.

A class with many dependencies that uses them all but has no loops or if statements is fine. In some code I was working on recently there were around 14 dependencies in a class. However, there was only one path through the code and no logical way to group the dependencies into better classes.

A class with a small number of dependencies that contains many branch statements or complex loop conditions should be simplified.

WW.
  • 23,793
  • 13
  • 94
  • 121
24

This may be a sign that the class with the 6-10 dependencies itself needs to be refactored.

Jacob B
  • 2,005
  • 13
  • 12
  • 1
    what if there you cannot find logical way to group them into multiple classes like WW. mentioned? Do you agree that then its ok to have many dependencies? I mean lets say dependencies are car brands: BMW, OPEL, VW, etc. They are all cars. Maybe not the best example, but I hope you get the idea. – Dariux Oct 13 '14 at 08:55
  • 2
    @Darius.V - If you have a `Cars` class that has 50 brand dependencies, then clearly you have violated the SRP. You need to group them into common characteristics (i.e. `ElectricCars`, `HybridCars`, `DieselCars`, `GasolineCars`), so your top-level `Cars` class only has a few dependencies that each have common properties and methods. Below that, you can use the [strategy pattern](https://stackoverflow.com/a/31971691) to simplify multiple similar cars into a single dependency (for example, just have a single `GasolineCarsStrategy` that is injected into your cars class that manages all gas cars). – NightOwl888 Jun 06 '17 at 15:12
5

A class with 6-10 dependencies is a code smell. It is an indication that the class is probably violating the Single Responsibility Principle.

What are some strategies that you use to reduce these dependencies?

Mark Seemann has made that task clear in his post Refactoring to Aggregate Services and moreso in his book Dependency Injection in .NET. The fact your class has so many dependencies indicates there are more than one responsibilities within the class. Often there is an implicit domain concept waiting to be made explicit by identifying it and making it into its own service. Generally speaking, most classes should never need more than 4-5 dependencies.

NightOwl888
  • 55,572
  • 24
  • 139
  • 212
  • 6
    About SRP: Say you have an API controller with 10 HttpGet methods and 10 dependencies -- one to process the logic for each method. Each of the methods are relevant to the controller, but they each request data from different sources, thus they need their own handling. All 10 of the dependencies use the same generic interface, but with different models. No logic is performed in the controller. In cases like this, I would still consider this controller SOLID, regardless of having many dependencies. – fix Apr 19 '19 at 13:45
  • Thank you very much for the reference to the blog and the book ! – herve Jul 09 '23 at 09:21
5

I would think no more than three or four. If you are getting more than that, I would start thinking about how well you are abstracting your concerns. A single repository object, for example, should fulfill all of your data retrieval needs within the class in question.

tinonetic
  • 7,751
  • 11
  • 54
  • 79
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • 7
    Presumably, if an object requires access to a database and some way to communicate externally (say, Repository and IO) that's already 2 dependencies out of the allotted 4. Besides - isn't one of the side-effects of making sure that each class has a single responsibility (single concern) going to result in more classes rather than fewer? Ultimately, there needs to be a class that can orchestrate all these smaller pieces...and that class will have many dependencies in order to function. – Runcible Jun 05 '09 at 00:09
  • @Runcible, quite correct. And if the consolidation you describe takes place, you will indeed have fewer things to inject into the constructor. What you are describing BTW is an Inversion of Control container (like Windsor, for example). – Robert Harvey Jun 05 '09 at 01:07
  • 3
    @Runcible, I've been struggling with this issue of dependency over injection lately. I've found two posts that have been quite helpful. http://blog.ploeh.dk/2010/01/20/RebuttalConstructorover-injectionanti-pattern/ & http://blog.ploeh.dk/2010/02/02/RefactoringtoAggregateServices/ One other note, I believe the intent of SRP is not to have a class that does one thing, but has one reason to change from the business perspective. – GetFuzzy Jul 24 '14 at 04:09
4

Runcible,

Here is a link to the Castle Windsor project. It is an Inversion of Control container. These containers allow factory classes to collect your dependencies together and inject them as a single object into your constructor.

http://www.castleproject.org/container/index.html

I have heard good things about Windsor. Spring also makes an IoC container, and there are others.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
0

You may also want to see if any of the parameters to your constructor should be combined into a single class as well (assuming that the parameters make sense as a class).

It might also be that you want to look at using the ServiceLocator pattern for some of your dependencies. This is particularly true if you're having to pass the dependencies down a long chain of constructors.

Rob Scott
  • 449
  • 3
  • 4
  • 5
    The Service Locator pattern is sort of in opposition to the Dependency Injection principles. Service Locator violates the Law of Demeter: http://www.youtube.com/watch?v=RlfLCWKxHJ0 – Runcible Jun 05 '09 at 00:06
  • Very nice video, Runcible. Very understandable explanation of DI, IOC, Service Locator. – Alexanderius Feb 12 '14 at 13:04