Arquitetura Limpa no Frontend: Conceitos e Implementação
Inspirado no livro Arquitetura Limpa de Robert C. Martin (Uncle Bob), no curso Domine a Arquitetura Limpa e Hexagonal da Cod3r Cursos Online, e em artigos de referência sobre Clean Architecture no Frontend [[DEV.to](https://dev.to/miasalazar/clean-architecture-in-front-end-development-523n), [Medium](https://eduardo-ottaviani.medium.com/a-definitive-guide-to-front-end-clean-architecture-3a62418becb4)], este artigo apresenta como aplicar esses conceitos em projetos modernos de React/Next.js.
O que é Clean Architecture?
A Arquitetura Limpa organiza o sistema em camadas concêntricas, separando regras de negócio dos detalhes de implementação. O objetivo é criar sistemas:
- Independentes de frameworks
- Fáceis de testar
- Fáceis de manter e evoluir
- Com baixo acoplamento e alta coesão
O núcleo do sistema (regras de negócio) nunca deve depender de detalhes externos como UI, banco de dados ou APIs.
Camadas da Clean Architecture
- Entidades (Domain Layer): Modelos e regras de negócio mais genéricas. Exemplo:
export type User = { email: string; password: string; }; export const isValidEmail = (email: string): boolean => { return email.includes('@'); }; - Casos de Uso (Application Layer): Orquestram o fluxo entre domínio e UI, encapsulando regras específicas da aplicação.
export const loginUser = async ( email: string, password: string ): Promise=> { if (!isValidEmail(email)) { throw new Error('Invalid email'); } const user: User = { email, password }; return await loginApi(user); }; - Adaptadores de Interface (Presentation Layer): Componentes, view models, presenters. Exemplo:
export const LoginForm = () => { // ... const handleLogin = async () => { try { const success = await loginUser(email, password); alert(success ? 'Logged in!' : 'Login failed'); } catch (error) { alert((error as Error).message); } }; // ... }; - Frameworks & Drivers (Infrastructure Layer): Detalhes de implementação (fetch, axios, localStorage, etc).
export const loginApi = async (user: User): Promise=> { const response = await fetch('/api/login', { method: 'POST', body: JSON.stringify(user), headers: { 'Content-Type': 'application/json', }, }); return response.ok; };
Benefícios
- Testabilidade: Teste regras de negócio sem depender de UI ou browser.
- Manutenibilidade: Troque frameworks ou APIs com impacto mínimo.
- Escalabilidade: Cresça o código sem perder clareza.
Aplicando no Frontend (React/Next.js)
- Domínio isolado: Crie pastas para entidades e casos de uso, sem dependências de React.
- Interfaces (ports): Defina contratos para comunicação com o mundo externo.
- Adaptadores: Implemente adaptadores para conectar interfaces ao mundo real (HTTP, localStorage, UI).
- UI como detalhe: Componentes React consomem casos de uso, sem conhecer detalhes de implementação.
Exemplo de estrutura:
src/
domain/
entities/
usecases/
ports/
infra/
adapters/
services/
ui/
components/
pages/
Dicas e Boas Práticas
- Teste o domínio isoladamente, usando mocks.
- Evite dependências cruzadas: domínio nunca importa infra ou UI.
- Adapte para o seu contexto: nem sempre é preciso seguir 100% do modelo, mas os princípios são universais.
Estrutura de Pastas Sugerida
src/
pages/
home/
services/
entities/
stores/
components/
shared/
utils/
services/
entities/
stores/
components/
Comece específico e mova para shared conforme necessário, facilitando a manutenção e remoção de páginas inteiras sem dependências ocultas.
Bônus: Design System Agnóstico
O Design System deve ser desacoplado de frameworks, exportando tokens, tipografia, cores e componentes atômicos em CSS puro, permitindo uso em qualquer stack.
Conclusão
Arquitetura Limpa no frontend é sobre separar responsabilidades, empurrar frameworks para as bordas e proteger o domínio das mudanças externas. Isso resulta em aplicações mais robustas, testáveis e fáceis de evoluir.
Referências: