What is the Dependency Injection (DI) principle?
The Dependency Injection principle is a software design pattern that promotes loose coupling and high modularity in object-oriented programming.
With simple words, we provide dependencies to a class from the outside rather than create in the class itself.
Instead of this:
class UserService {
logging(message) {
console.log(message);
}
addUser(user) {
// Add user logic...
this.log(`User added: ${user}`);
}
}
const userService = new UserService(); // Create the UserService
// Usage
userService.addUser("John Doe");
We do this:
// Logger class
class Logger {
logging(message) {
console.log(message);
}
}
// UserService class with Logger dependency
class UserService {
constructor(logger) {
this.logger = logger;
}
addUser(user) {
// Add user logic...
this.logger.logging(`User added: ${user}`);
}
}
// Creating instances and injecting dependencies
const logger = new Logger();
// Create a Logger instance
const userService = new UserService(logger);
// Inject the Logger instance into UserService
// Usage
userService.addUser("John Doe");
The reason for such an abstraction is to achieve separations of concerns. We want our addUser function to be part of our UserServices class, but our logging function being too fundamental to fix into only one class, should be abstracted away from UserServices class into its own class.
Why? The answer is re-usability. Therefore, we abstract logging function and inject it as a dependency via the constructor.
Constructor
The constructor, thus, is a crucial tool since it not only initialises class properties but also serves as an entrypoint for its class' dependencies on other classes (the UserService doesn't create a Logger instance internally but relies on the Logger instance provided to it).
Summary
We go from thigh coupling (logger function being an integral part of UserService class) to loose coupling (The Logger instance is independent of the UserService, and we can easily replace it with a different Logger implementation without modifying the UserService code), thus, achieving reusability and abstraction.
Top comments (0)