Injeção de Dependência em JavaScript: Guia Completo com Exemplos

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Injeção de Dependência em JavaScript: Guia Completo



Injeção de Dependência (DI) é um poderoso padrão de projeto que está na base do princípio Inversão de Controle (IoC). Em vez de um objeto criar suas próprias dependências, a DI as "injeta" de fora. Isso torna o código mais flexível, testável e sustentável. Neste artigo, vamos analisar como implementar a Injeção de Dependência em JavaScript e Node.js, usando exemplos simples e claros.



O que é Injeção de Dependência e por que ela é necessária?



Imagine que você tem uma classe UserService que trabalha com um banco de dados. Sem DI, você provavelmente criaria uma instância do banco de dados diretamente dentro do serviço:



class UserService {  constructor() {    this.db = new Database(); // Acoplamento rígido  }

getUser(id) { return this.db.findUser(id); }}


Este código viola o Princípio da Inversão de Dependência (Dependency Inversion Principle). Ao testar o UserService, você não conseguirá substituir o banco de dados real por um objeto mock sem alterar o código da classe. A DI resolve este problema:



class UserService {  constructor(database) {    this.db = database; // A dependência é passada de fora  }

getUser(id) { return this.db.findUser(id); }}

// Usoconst db = new Database();const userService = new UserService(db);


Principais vantagens da DI:

  • Testabilidade: Fácil substituir dependências por mocks ou stubs.
  • Baixo acoplamento: As classes dependem de abstrações (interfaces), não de implementações concretas.
  • Flexibilidade: É possível alterar facilmente o comportamento do sistema substituindo implementações.
  • Reutilização de código: Os componentes tornam-se independentes e podem ser usados em diferentes contextos.


Formas de injeção de dependências em JavaScript



Em JavaScript, existem três formas principais de injetar dependências:



1. Injeção via construtor (Constructor Injection)

A forma mais comum e recomendada. As dependências são passadas no momento da criação do objeto.



class Logger {  log(message) {    console.log(`[LOG]: ${message}`);  }}

class OrderService { constructor(logger) { this.logger = logger; }

createOrder(data) { this.logger.log('Novo pedido criado'); // Lógica de criação do pedido }}

const logger = new Logger();const orderService = new OrderService(logger);orderService.createOrder({ product: 'Laptop', price: 1500 });


2. Injeção via setters (Setter Injection)

As dependências são definidas após a criação do objeto através de métodos setters. Adequado para dependências opcionais.



class EmailService {  constructor() {    this.transporter = null;  }

setTransporter(transporter) { this.transporter = transporter; }

send(email) { if (!this.transporter) { throw new Error('Transporter não configurado'); } this.transporter.sendMail(email); }}

const emailService = new EmailService();emailService.setTransporter(someMailTransporter);


3. Injeção via interface (Interface Injection — condicionalmente)

Em JavaScript não há interfaces nativas, mas é possível usar TypeScript ou documentação para descrever contratos. Na prática, isso se resume a verificar a existência de métodos.



Criando um contêiner DI simples em Node.js



Para gerenciar dependências em aplicações grandes, é conveniente usar um contêiner DI. Ele armazena todas as dependências e as resolve automaticamente. Aqui está uma implementação mínima:



class Container {  constructor() {    this.services = new Map();    this.singletons = new Map();  }

// Registro de fábrica para o serviço register(name,

Blogs

Book Recommendations