Container de Injeção de Dependência para JavaScript (Node.js): Awilix
No desenvolvimento moderno com Node.js, manter a pureza da arquitetura e a testabilidade do código é criticamente importante. Um dos padrões-chave que ajudam nisso é a Injeção de Dependência (DI). Para implementar eficazmente esse padrão no ambiente JavaScript, foram criadas bibliotecas especializadas — os containers de Injeção de Dependência. Neste artigo, examinaremos detalhadamente uma das bibliotecas mais populares e leves — Awilix.
O que é Injeção de Dependência e para que serve um container?
Na abordagem tradicional, o próprio objeto cria suas dependências (por exemplo, usando o operador new). Isso leva a um forte acoplamento do código, dificultando os testes e a modificação. O padrão Injeção de Dependência propõe passar (injetar) as dependências externamente. O container automatiza esse processo: ele sabe como criar objetos e suas dependências, e fornece instâncias prontas sob demanda.
Awilix: um container DI leve e poderoso
Awilix é uma biblioteca para JavaScript (Node.js) que implementa o padrão Inversão de Controle (IoC) usando um container. Ela foi escrita do zero para Node.js, suporta resolução assíncrona de dependências, vários estilos de registro (classes, fábricas, valores) e descoberta automática de dependências através do construtor.
Principais funcionalidades:
- Injeção automática: O container analisa os parâmetros do construtor ou função e injeta automaticamente as dependências necessárias.
- Suporte a assincronismo: As dependências podem ser assíncronas (por exemplo, conexão com banco de dados), e o container aguarda corretamente sua resolução.
- Diferentes modos de registro: Você pode registrar classes (
asClass), funções fábrica (asFunction) ou valores prontos (asValue). - Escopos (Scopes): São suportados diferentes ciclos de vida dos objetos (singleton, transient, scoped).
- Modularidade: O container pode ser facilmente dividido em módulos e as dependências registradas em diferentes partes da aplicação.
Instalação e uso básico
A instalação do Awilix é feita via npm:
npm install awilixVamos considerar um exemplo simples. Suponha que temos um serviço para trabalhar com usuários, que depende de um logger e de um repositório.
const { createContainer, asClass, asFunction, asValue } = require('awilix');
// 1. Definindo as dependênciasclass Logger { log(message) { console.log(`[LOG]: ${message}`); }}
class UserRepository { constructor({ logger }) { this.logger = logger; }
findById(id) { this.logger.log(`Buscando usuário com ID: ${id}`); return { id, name: 'John Doe' }; }}
class UserService { constructor({ userRepository, logger }) { this.userRepository = userRepository; this.logger = logger; }
getUser(id) { this.logger.log('Requisição no UserService'); return this.userRepository.findById(id); }}
// 2. Criando o container e registrando as dependênciasconst container = createContainer();
container.register({ logger: asClass(Logger).singleton(), userRepository: asClass(UserRepository).singleton(), userService: asClass(UserService).singleton()});
// 3. Usando o container para obter o serviçoconst userService = container.resolve('userService');const user = userService.getUser(1);console.log(user);// Saída:// [LOG]: Requisição no UserService// [LOG]: Buscando usuário com ID: 1// { id: 1, name: 'John Doe' }< Também na biblioteca
Envio de Email em C# (.NET) com SmtpClient e MailKit
Migrações de banco de dados em C# (.NET): Entity Framework, FluentMigrator e outras abordagens
Internacionalização (i18n) em Rust: melhores bibliotecas e práticas
node-cron: Agendador de tarefas para JavaScript (Node.js)
Trabalho com imagens em PHP: redimensionamento e corte (resize, crop)