Skip to content

Perebati/fc-clean-arch-nodejs

Repository files navigation

Curso Full Cycle 3.0 - Módulo Clean Architecture

Este projeto representa uma implementação prática dos conceitos de Clean Architecture em TypeScript, demonstrando como aplicar os princípios fundamentais dessa arquitetura em uma aplicação Node.js real.

Clean Architecture

A Clean Architecture é um termo criado por Robert C. Martin (Uncle Bob) em 2012, que posteriormente se tornou um livro. Embora seja frequentemente tratada como uma buzzword, sua essência está na proteção do domínio da aplicação, no baixo acoplamento entre as camadas e na orientação a casos de uso.

Curiosidades sobre o livro

Uma observação interessante é que Robert C. Martin fala especificamente sobre Clean Architecture em apenas 7 páginas do livro. Tudo que ele aborda especificamente sobre Clean Architecture está literalmente disponível em um artigo em seu blog.

Porque estudar Clean Architecture

O estudo da Clean Architecture é fundamental para reforçar conhecimento e remover gaps básicos que muitas vezes nem percebemos ter. Os principais benefícios incluem:

  • Melhor compreensão sobre componentes
  • Entendimento aprofundado sobre arquitetura
  • Conhecimento sobre limites arquiteturais
  • Percepção aprimorada sobre regras de negócios

Pontos importantes sobre arquitetura

A arquitetura define o formato que o software terá, incluindo a divisão de componentes e a comunicação entre eles. Uma boa arquitetura facilita o processo de desenvolvimento, deploy, operação e manutenção.

Objetivos de uma boa arquitetura

O objetivo principal da arquitetura é dar suporte ao ciclo de vida do sistema. Uma boa arquitetura torna o sistema fácil de entender, fácil de desenvolver, fácil de manter e fácil de implantar. O objetivo final é minimizar o custo de vida útil do sistema e maximizar a produtividade do programador.

Regras versus Detalhes

As regras de negócio trazem o real valor para o software, enquanto os detalhes ajudam a suportar essas regras. Os detalhes não devem impactar nas regras de negócio. Frameworks, banco de dados e APIs não devem impactar as regras principais. Como enfatizado no DDD (Domain-Driven Design), é preciso atacar a complexidade no coração do software.

Use Cases

Os Use Cases representam a intenção e a clareza de cada comportamento do software. Eles são fundamentais para manter os detalhes separados das regras de negócio, garantindo que frameworks, banco de dados e APIs não impactem as regras principais.

Use Cases e o Princípio da Responsabilidade Única (SRP)

Existe uma tendência de reaproveitar Use Cases por serem muito parecidos. Por exemplo, "Alterar" versus "Inserir": ambos consultam se o registro existe e persistem dados, mas são Use Cases diferentes. Isso ocorre porque, de acordo com o SRP (Single Responsibility Principle), eles mudam por razões diferentes. É importante distinguir entre duplicação real e acidental.

Limites arquiteturais

Tudo que não impacta diretamente nas regras de negócio deve estar em um limite arquitetural diferente. Por exemplo, não será o frontend ou o banco de dados que mudarão as regras de negócio da aplicação.

Input e Output

No final do dia, tudo se resume a um input que retorna um output. Por exemplo: criar um pedido (dados do pedido como input) resulta em um pedido criado (dados de retorno do pedido). Simplifique seu raciocínio ao criar um software sempre pensando em Input e Output.

DTO - Data Transfer Object

Os DTOs são utilizados para trafegar dados entre os limites arquiteturais. São objetos anêmicos, sem comportamento, que contêm dados (Input ou Output). Eles não possuem regras de negócio, não possuem comportamento e não fazem nada além de transportar dados.

O fluxo típico é: API → Controller → Use Case → Entity. O Controller cria um DTO com os dados recebidos e envia para o Use Case. O Use Case executa seu fluxo, pega o resultado, cria um DTO para output e retorna para o Controller.

Presenters

Os Presenters são objetos de transformação que adequam o DTO de Input no formato correto para entregar o resultado. É importante lembrar que um sistema pode ter diversos formatos de entrega: XML, JSON, Protobuf, GraphQL, CLI, etc.

Exemplo de uso:

input = new CategoryInputDTO('name')
output = CreateCategoryUseCase(input)
jsonResult = CategoryPresenter(output).toJson()
xmlResult = CategoryPresenter(output).toXML()

Entities

As Entities da Clean Architecture são diferentes das Entities do DDD. A Clean Architecture define Entity como camada de regras de negócio que se aplicam em qualquer situação. Não há definição explícita de como criar as Entities, mas normalmente utilizamos táticas do DDD. Na prática, Entities equivalem a Agregados + Domain Services.

Estrutura de Pastas

src/
├── domain/              # Camada de Domínio
│   ├── @shared/        # Componentes compartilhados
│   ├── customer/       # Agregado Customer
│   ├── product/        # Agregado Product
│   └── checkout/       # Agregado Checkout
├── infra/              # Camada de Infraestrutura
│   ├── api/           # API REST (Express)
│   ├── customer/      # Repositórios de Customer
│   ├── product/       # Repositórios de Product
│   └── order/         # Repositórios de Order
└── usecase/           # Casos de Uso
    ├── customer/      # Use Cases de Customer
    └── product/       # Use Cases de Product

Camadas da Arquitetura

Domain Layer

  • Entities: Regras de negócio fundamentais
  • Value Objects: Objetos imutáveis que representam conceitos do domínio
  • Domain Services: Lógica de negócio que não pertence a uma entidade específica
  • Repository Interfaces: Contratos para persistência de dados
  • Domain Events: Eventos que representam mudanças no domínio

Use Cases Layer

  • Application Services: Orquestração de fluxos de negócio
  • DTOs: Objetos de transferência de dados
  • Input/Output Boundaries: Interfaces para entrada e saída de dados

Infrastructure Layer

  • Database: Implementação de repositórios com Sequelize
  • API: Controllers e rotas REST
  • External Services: Integrações com serviços externos

Tecnologias Utilizadas

  • Node.js - Runtime JavaScript
  • TypeScript - Superset tipado do JavaScript
  • Express - Framework web
  • Sequelize - ORM para banco de dados
  • SQLite - Banco de dados para desenvolvimento
  • Jest - Framework de testes
  • Yup - Validação de esquemas
  • UUID - Geração de identificadores únicos

Instalação

Pré-requisitos

  • Node.js 18+
  • Yarn ou npm

Passos para instalação

  1. Clone o repositório:
git clone <repository-url>
cd CleanArch
  1. Instale as dependências:
yarn install
# ou
npm install
  1. Execute os testes:
yarn test
# ou
npm test
  1. Inicie o servidor de desenvolvimento:
yarn dev
# ou
npm run dev

Testes

O projeto possui cobertura completa de testes incluindo:

  • Unit Tests: Testes unitários para entities e use cases
  • Integration Tests: Testes de integração para use cases
  • E2E Tests: Testes end-to-end para APIs
# Executar todos os testes
yarn test

# Executar testes específicos
yarn test -- --testNamePattern="Customer"

Conceitos Implementados

Clean Architecture Principles

Entities

  • Representam as regras de negócio mais importantes
  • Independentes de frameworks e tecnologias
  • Aplicam-se em qualquer contexto
  • Exemplo: Customer, Product, Order

Use Cases

  • Representam a intenção do sistema
  • Orquestram o fluxo entre entities
  • Independentes de detalhes de implementação
  • Seguem o princípio SRP (Single Responsibility Principle)

Interface Adapters

  • Controllers: Adaptam dados da web para use cases
  • Presenters: Formatam dados para diferentes tipos de saída
  • Repositories: Abstraem acesso a dados

Frameworks & Drivers

  • Banco de dados (SQLite/Sequelize)
  • Framework web (Express)
  • Ferramentas externas

Design Patterns Implementados

Factory Pattern

  • CustomerFactory: Criação de customers
  • ProductFactory: Criação de products
  • OrderFactory: Criação de orders

Observer Pattern

  • EventDispatcher: Gerenciamento de eventos de domínio
  • EventHandler: Manipuladores de eventos específicos

Repository Pattern

  • Abstrações para acesso a dados
  • Implementações específicas por tecnologia
  • Inversão de dependência

DTO Pattern

  • Transferência de dados entre camadas
  • Objetos anêmicos sem comportamento
  • Input e Output bem definidos

Fluxo de Dados

HTTP Request → Controller → Use Case → Entity → Repository → Database
                    ↓           ↓         ↓
                   DTO    →   Domain   →  Events
                    ↓           ↓         ↓
HTTP Response ← Presenter ← Use Case ← Event Handler

Exemplo de Fluxo

  1. Input: Cliente faz uma requisição HTTP
  2. Controller: Cria um DTO com os dados recebidos
  3. Use Case: Executa a lógica de negócio
  4. Entity: Aplica regras de domínio
  5. Repository: Persiste dados
  6. Output: Retorna resultado formatado pelo Presenter

Regras vs Detalhes

Regras de Negócio

  • Trazem o real valor para o software
  • Devem ser protegidas e isoladas
  • Não devem ser impactadas por detalhes técnicos

Detalhes

  • Frameworks, banco de dados, APIs
  • Suportam as regras de negócio
  • Podem ser alterados sem impactar o core

Benefícios da Clean Architecture

  • Testabilidade: Fácil de testar isoladamente
  • Manutenibilidade: Código organizado e limpo
  • Flexibilidade: Fácil de adicionar novos recursos
  • Independência: Desacoplado de frameworks
  • Escalabilidade: Preparado para crescimento

Referências

Licença

Este projeto está sob a licença MIT. Veja o arquivo LICENSE para mais detalhes.

About

Repositório dedicado ao modulo sobre Clean Architecture no curso Full Cycle 3.0.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published