Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Busy constructors in Ioc - are they a code smell?

I have ended up with a constructor that looks like this whilst attempting to end up with an object i can easily test.

 public UserProvider(
            IFactory<IContainer> containerFactory,
            IRepositoryFactory<IUserRepository> userRepositoryFactory,
            IFactory<IRoleProvider> roleProviderFactory,
            IFactory<IAuthenticationProvider> authenticationProviderFactory,
            IFactory<IEmailAdapter> emailAdapterFactory,
            IFactory<IGuidAdapter> guidAdapterFactory,
            IRepositoryFactory<IVehicleRepository> vehicleRepositoryFactory,
            IRepositoryFactory<IUserVehicleRepository> userVehicleRepositoryFactory,
            IFactory<IDateTimeAdapter> dateTimeAdapterFactory)

This is all the dependencies the object will have and is the busiest constructor i have. But if someone saw this would it really raise a big wtf?

My aim was to end up with logic that is easy to test. Whilst it requires a good amount of mocks it is certainly very easy to verify my logic. However i am concerned that I may of ended up with too much of a good thing.

I am curious if this is normal for most people implementing ioc.

There are several simplifications I can make - such as I don't really need to pass in the factories for several of the adapters as i could just pass the adapter in directly as it has no internal state. But I am really asking in terms of the number of parameters.

Or more to the point i am looking for assurance that I am not going overboard ;)

But I am beginnign to get the impression that the UserProvider class should be broken down a bit - but then I end up with even more plumbing which is what is driving this concern.

I guess a sub question is maybe should I be considering using a service Locator pattern if I have these concerns?

like image 657
John Nicholas Avatar asked Nov 29 '25 02:11

John Nicholas


2 Answers

When using DI and constructor injection violation of the SRP becomes very visible. This is acutally a good thing, and it is not DI / IOC's fault. If you were not using constructor injection, the class would have the same dependencies, it would just not be as visible.

What you could do in your concrete example is hide some of the related dependencies behind facades. For example IVehicleRepository and IUserVehicleRepository could be hidden behind an IVehicle facade. It might also make sense to put IUserRepository, IRoleProvider and IAuthenticationProvider behind a facade.

like image 173
ThomasH Avatar answered Nov 30 '25 16:11

ThomasH


In my opinion that is a lot of parameters for a constructor. Here's how I would handle this to get good testability and reduce "code smell."

  1. Instead of passing in the factories to create instances of your classes just pass in the classes themselves. This automatically cuts your dependencies in half because the UserProvider would not be concerned with creating any objects that it needs (and subsequently disposing of them if necessary) it would just use what is given to it instead of using the factories that it needs to create object instances that it needs.
  2. Remove your adapters from the constructor and just create instances of these interfaces inside of the UserProvider. Think about how often are you going to need to change the way you format a guid for example. This would still be testable as long as your adapters don't have a lot of dependencies.

The point I'm making is to get a good balance of testability and practicality. When implementing Ioc try and determine where you've had trouble with testability in the past and where you've had issues maintaining and changing code because there were too many dependencies. That is where you'll see the most benefit.

like image 29
robbymurphy Avatar answered Nov 30 '25 15:11

robbymurphy



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!