How to deal with constructor over-injection in .NET
Asked Answered
A

5

15

I'm sorry if that question was already discussed, but I didn't find exactely what I wanted. The problem I'm facing is more about patterns and design choices than about .NET itself. I just would like to have your advice to know where to start my refactorings.

Today I opend one of the classes in my actual application and found that it has 13 dependencies injected by constructor !!! In fact each developper added the dependecy it needed in method that he was writing.

One point of my understanding of DI is that when we inject a dependency by constructor it means that it's a mandatory dependency and should be used in all methods of the class. If we need a particular dependency just in one method of the given class, what does it mean for you ?

  • The given class does too much ? I should consider to create a new type just with a needed dependency ?
  • I should inject by property ? But in that particular method a dependency is mandatory so I don't think it's a good choice.
  • I should inject by method ?

What's difficult is to find the right balance. In reallity sometimes it's not possible to encapsulate the bahaviour in the clean way.

I was considering to create something like service aggregator to hind related dependency behind one of them but would like if you have other advices. Thanks in advance.

Alburga answered 5/1, 2011 at 11:29 Comment(1)
Related: #2420693Pewter
P
27

You are correct: if you need to inject 13 dependencies into a class, it's a pretty sure sign that you are violating the Single Responsibility Principle. Switching to Property Injection will not help, as it will not decrease the number of dependencies - it will only imply that those dependencies are optional instead of mandatory.

Basically, there are two ways to deal with this type of problem:

  • Refactor to Facade Services. This is basically a non-breaking refactoring as it maintains the functionality of the Controller. However, it changes the responsibility toward coordinating/orchestrating the interaction between services instead of managing the nitty-gritty details of the implementation.
  • Split up the class into independent classes. If each of the services were introduced by different developers to support a subset of the methods, it's a sign of low cohesion. In this case, it would be better to split up the class into several independent classes.

Specifically for ASP.NET MVC you may not want to split up an Controller because it will change your URL scheme. That's fair enough, but consider what this implies: it means that the single responsibility of the Controller should be to map URLs to application code. In other words, that's all a Controller should do, and it then follows that the correct solution is to refactor to Facade Services.

Pewter answered 5/1, 2011 at 11:44 Comment(0)
T
11

Just because a dependency is mandatory doesn't mean it should be used in all the methods of a class, IMO. It should just be logically part of the configuration of the class itself.

On the other hand, if a class has 13 dependencies it may well be doing too much. Do any of those dependencies logically belong together? Perhaps the dependencies themselves should be "chunkier" - or quite possibly your class should do less.

Theosophy answered 5/1, 2011 at 11:33 Comment(1)
I'll try to break it down to smaller classes but as far as I see the injected dependencies also depends on each other. For example one dependecy need another one to complete it's task and I afraid that after the breaking down into smaller classes I still should inject the same dependencies. Maybe not 13 but some of them.Undies
M
5

This sounds like a case of a class having too many dependencies i.e. it's a God class. Try and break it down into more discrete responsibilities.

Muliebrity answered 5/1, 2011 at 11:34 Comment(2)
Yes I consider to do it. The other difficulty I'm facing is that injected dependencies mix together. In one method I need dependency A and D and in the next one C and A. I think the problem is more important and just refactoring the God class wouldn't be just enough because I'll find myself to inject the same dependencies to the smaller classes ?Undies
You are the only one that can analyze the dependencies, but I would guess that only subsets of the dependencies would be needed if you break the class down. The fact that many developers are adding dependencies is a very strong God class smell that will only get worse over time. Eventually you will reach tipping point where there is not enough time in the Universe to refactor all the God classes.Muliebrity
P
0

If your class has 13 dependencies you definitely have a problem. Clearly your class serves too many responsibilities. Marc Seemann has discussed this problem in his book "Dependency injection in .NET" paragraph 6.4. If your class starts to have 3 parameters in the constructor you must start to wonder. Is my class still serving one responsibility? If you start to have 4 or more parameters in your constructor refactor your class by start using the facade or composition pattern.

Pigeonhole answered 1/12, 2013 at 10:36 Comment(0)
C
0

Its just the way DI works. Its a fact. So accept it. Its fully legit in a service like a Pdf Service, Look at this code:

public PdfService(ILocalizationService localizationService, 
        ILanguageService languageService,
        IWorkContext workContext,
        IOrderService orderService,
        IPaymentService paymentService,
        IDateTimeHelper dateTimeHelper,
        IPriceFormatter priceFormatter,
        ICurrencyService currencyService, 
        IMeasureService measureService,
        IPictureService pictureService,
        IProductService productService, 
        IProductAttributeParser productAttributeParser,
        IStoreService storeService,
        IStoreContext storeContext,
        ISettingService settingContext,
        IAddressAttributeFormatter addressAttributeFormatter,
        CatalogSettings catalogSettings, 
        CurrencySettings currencySettings,
        MeasureSettings measureSettings,
        PdfSettings pdfSettings,
        TaxSettings taxSettings,
        AddressSettings addressSettings)
Cosmorama answered 28/11, 2017 at 11:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.