Dependency Injection Makes You Incredibly Lazy
Nicklas Millard
published September 28, 2022
Dependency Injection is great. It really is. But, it’s also hell.
The idea of having some IoC container resolve all our explicit constructor object dependencies is amazing and strongly advocated for in the developer community.
And, it makes sense because it simplifies development at design-time.
The approach is essentially like this: make a class. Let it take some dependencies. Register them with the IoC container in a carefree manner. Never look back.
I’m not going to dwell on the details of IoC, DIP, dependency injection, and containers. I’m sure you’re already familiar with the extensive list of provided benefits.
However, there’s a big issue.
Dependency injection inspires developers to become lazy. Like, mind-boggling lazy.
Suddenly, it’s quite common to witness ‘service’ classes turn into what’s best described as logic dumpsters. Service class constructors often fall victim to constructor bloating. The everyday life of an engineer now involves thoughtlessly adding yet another explicit constructor dependency.
public class UserService
{
// fields
public UserService(
IUserRepository userRepository,
IUserManager userManager,
IPasswordHasher passwordHasher,
IEmailSender emailSender,
ITransactionService transactionService,
INotificationService notificationService,
ILogger<UserService>? logger = null
)
{
// Set fields
}
}
You’re regularly required to pass in six, seven, or more objects simply to invoke a service class method that only needs one of those dependencies to execute correctly.
It’s hell.
I think many developers entirely neglect how pain-inducing this practice is. Even writing the simplest of unit tests now requires you to either instantiate or mock several objects.
Dependency fatigue sets in.
Imagine you have a class with eight constructor arguments, and you need to test a single method. Writing the unit test is now so cumbersome that you start passing in nulls as constructor arguments because you know those seven other dependencies are not doing squat when testing this one particular method.
The fun really starts once you have a dependency on a class with a bloated constructor. For instance a service class depending on yet another service class. You may argue that is the result of poor design. Sure, it is. The poor design enabled by the ease of injecting dependencies without much thought.
On a side note, I will encourage you to stop using services classes, aka. logic dumpsters. They’re often poorly structured facades with no real benefit. Instead, try to split your service classes into multiple, specialized classes, as shown in this article:
I’m a huge advocate of explicit dependencies, DI, IoC, and all that good stuff.
By now, you were probably starting to think the opposite.
I’m advocating against the lazy habit of “I’m just gonna add one more constructor argument”. Nothing else.
To combat this poor habit, you should always try to evaluate how difficult it is to test a class or method. How much effort will it be to test your new method? How many classes do you need to mock versus how many are actually used?
Adding a constructor argument should not simply be a random act carried out in a hurry.
Parting words.
Are you happy with your classes taking a ton of constructor arguments? Fine, don’t change a thing then.
Take away anything that you find useful from this article, and ignore the rest.
Let's Stay in touch
You're always welcome to reach out at nicklas@mjukvare.com!