Question
Is there ever a case for using 'new' when implementing dependency injection?
Answer
Dependency injection (DI) is a design pattern that promotes loose coupling and enhances testability in software applications. While DI champions using abstractions (like interfaces) over concrete implementations, there are scenarios where using 'new' can be justified. This article will explore these instances comprehensively.
class Logger {
log(message) {
console.log(message);
}
}
class UserService {
constructor() {
this.logger = new Logger(); // Direct instantiation with 'new'
}
createUser(user) {
this.logger.log(`User created: ${user.name}`);
}
}
Causes
- When the dependency's lifecycle is independent of the class using it.
- In performance-critical sections where the overhead of a DI container is significant.
- When a simple object is required that does not warrant the complexity of DI.
Solutions
- Utilize 'new' sparingly and ensure it does not violate the principles of loose coupling and high cohesion.
- Document and justify the use of 'new' clearly to avoid confusion for future developers.
- Refactor code to ensure that when 'new' is used, it's a clear, conscious choice rather than oversight.
Common Mistakes
Mistake: Overusing 'new' which leads to tightly coupled code making unit testing difficult.
Solution: Limit 'new' usage to cases where it is warranted and ensure dependencies can be mocked or replaced easily.
Mistake: Neglecting to document instances where 'new' is used in a DI context, leading to confusion among team members.
Solution: Always comment on the reasons for using 'new' in the constructor to maintain code clarity.
Helpers
- dependency injection
- using new in dependency injection
- dependency injection best practices
- dependency injection examples
- why use dependency injection