Dependency injection — pass dependencies instead of creating them inside.
Constructor injection:
1class UserService {2 constructor(userRepo, emailService) {3 this.userRepo = userRepo;4 this.emailService = emailService;5 }67 async createUser(data) {8 const user = await this.userRepo.create(data);9 await this.emailService.send(user.email, "Welcome!");10 return user;11 }12}1314// Composition root15const userRepo = new UserRepository(db);16const emailService = new EmailService(smtp);17const userService = new UserService(userRepo, emailService);
Using InversifyJS (IoC container):
1const { Container, injectable, inject } = require("inversify");23@injectable()4class UserService {5 @inject("UserRepository") userRepo;6 @inject("EmailService") emailService;7}89const container = new Container();10container.bind("UserService").to(UserService);11container.bind("UserRepository").to(UserRepository);1213const service = container.get("UserService");
Benefits: