I am somewhat new to Dependency Injection. I have set it up for some classes that pass in their dependencies as parameters in the constructor, but I have some constructors that take primitives like String
or boolean
. Obviously these need to be removed from the constructor if I am to use Dependency Injection for that class.
For a case like this, what is a "best" practice? Make the constructor just take the dependencies and provide a setter method for all of the primitives that the class requires?
My observation is that in most cases, classes that have a constructor that takes both dependencies and primitives, break the Single Responsibility Principle or at least result in a design that is less clean, which leads to container configurations that are more fragile and harder to understand.
In most (if not all) cases, those primitives are configuration values, such as connection strings, debug options, and such.
There are a few ways you can change your design to solve this:
NotifyCustomerHandler
takes anstring notificationServiceUrl
, while thatstring
should have been encapsulated into some sort ofNotificationService
.NotifyCustomerHandler
, it could take a dependency on anINotifyCustomerHandlerConfiguration
. In the past I used to have a singleIMyApplicationConfiguration
interface, with all configuration values the application needed, but I came to the conclusion that this is a bad idea. This breaks the Interface Segregation Principle and your unit tests will start to suffer in terms of readability and maintainability.Class should take whatever dependencies it needs, in order to perform its function. Both other services it delegates some tasks to, as well as primitive dependencies (which are usually some configuration values).
Any non-trivial container will cater for this scenario and allow you to do this. Here's for example how Castle Windsor does it.
No, not "Obviously". You can keep these parameters in as well as have the injected dependencies.
If the class requires these parameters for proper initialization, they need to be part of the constructor.