Pular para conteúdo

Aula 17 - NestJS / Express com Arquitetura Modular e DI 🧱

Objetivo Pedagógico

Objetivo: Construção de aplicações corporativas escaláveis em Node.js com padrão Clean Architecture, Injeção de Dependências e módulos encapsulados.


📑 1. Fundamentos Teóricos & Análise Técnica

O desenvolvimento de backends em Node.js com Express puro frequentemente degenera em código espaguete com acoplamento severo, devido à ausência de uma estrutura arquitetural prescritiva. O NestJS resolve essa deficiência estrutural ao trazer padrões consolidados da engenharia corporativa (fortemente inspirados no Angular e Spring Boot) para o ecossistema Node.js com TypeScript.

A arquitetura do NestJS baseia-se em três pilares fundamentais: 1. Módulos (@Module): Unidades lógicas coesas que encapsulam controllers, providers e serviços, exportando estritamente os componentes que outros módulos podem consumir. 2. Controladores (@Controller): Camada de entrada responsável pelo tratamento de rotas HTTP, extração de parâmetros (@Param, @Body, @Query) e delegação da execução para a camada de serviço. 3. Provedores / Serviços (@Injectable): Classes que implementam regras de negócio puras, instanciadas e gerenciadas automaticamente pelo contêiner de Injeção de Dependências (DI) do NestJS.

Essa separação viabiliza a implementação de Arquitetura Limpa (Clean Architecture) e testes unitários com isolamento total via mocks.

📐 Arquitetura Conceitual & Diagrama de Fluxo

graph TD
    Request["Requisição HTTP: POST /orders"] --> Controller["OrdersController (@Controller)"]
    Controller --> Pipe["ValidationPipe (Zod / class-validator)"]
    Pipe --> Service["OrdersService (@Injectable - DI)"]
    Service --> Repo["OrdersRepository (Data Access)"]
    Repo --> DB["Banco de Dados PostgreSQL"]
    style Request fill:#e1f5fe,stroke:#01579b
    style Controller fill:#fff3e0,stroke:#e65100
    style Service fill:#e8f5e9,stroke:#2e7d32
    style DB fill:#f3e5f5,stroke:#7b1fa2

🔍 Pilares e Diretrizes Técnicas

Nesta unidade, aprofundamos os seguintes conceitos fundamentais: - Inversão de Controle (IoC): O ciclo de vida dos serviços e suas dependências são administrados pelo contêiner de DI do NestJS. - Pipes de Validação Automática: Transformação e validação de DTOs antes de atingir a lógica do controlador. - Interceptors e Guards: Controle de autorização por papéis (@Roles) e manipulação declarativa de respostas. - Testabilidade Extrema: Substituição trivial de repositórios reais por implementações em memória nos testes com Test.createTestingModule.


🛠️ 2. Implementação Prática em Node.js, NestJS e TypeScript

Abaixo está a implementação técnica de referência, estruturada com padrões de engenharia de software e foco em robustez:

// users.service.ts (Serviço NestJS com Injeção de Dependência)
import { Injectable, NotFoundException } from '@nestjs/common';

export interface UserEntity { id: string; name: string; email: string; }

@Injectable()
export class UsersService {
  private readonly users: Map<string, UserEntity> = new Map();

  async findById(id: string): Promise<UserEntity> {
    const user = this.users.get(id);
    if (!user) {
      throw new NotFoundException(`Usuário com ID ${id} não foi encontrado.`);
    }
    return user;
  }

  async create(user: UserEntity): Promise<UserEntity> {
    this.users.set(user.id, user);
    return user;
  }
}

💡 Análise Passo a Passo do Código

  1. Decorador @Injectable: Registra a classe no contêiner IoC do NestJS como um provider elegível para injeção.
  2. Exceções HTTP Nativas: NotFoundException é capturada pelo Exception Filter global e serializada em HTTP 404 JSON padronizado.
  3. Separação de Preocupações: O serviço não manipula objetos de requisição HTTP (req, res), focando puramente no domínio.

🎯 3. Próximos Passos & Sequência Didática