Ir para o conteúdo

Decisões Arquiteturais

Este documento registra decisões arquiteturais importantes do projeto Billings Ease, incluindo contexto, alternativas consideradas e trade-offs.

Índice

  1. Backend em Go
  2. Clean Architecture Simplificada
  3. Repository Pattern
  4. JWT para Autenticação
  5. PostgreSQL como Banco Principal
  6. React Query para Estado do Frontend
  7. Radix UI para Componentes
  8. Railway para Deploy
  9. Cloudflare R2 para Storage

Backend em Go

Decisão

Usar Go (Golang) como linguagem do backend.

Contexto

Necessidade de: - Performance alta - Concorrência eficiente - Simplicidade de deploy - Tipagem estática

Alternativas Consideradas

  1. Node.js/TypeScript
  2. ❌ Performance inferior para cálculos
  3. ❌ Gerenciamento de memória menos eficiente
  4. ✅ Ecossistema grande

  5. Python (Django/FastAPI)

  6. ❌ Performance inferior
  7. ❌ GIL limita concorrência
  8. ✅ Fácil desenvolvimento

  9. Java/Kotlin

  10. ❌ Mais verboso
  11. ❌ Startup mais lento
  12. ✅ Performance excelente

Trade-offs

Vantagens: - Performance excelente - Concorrência nativa (goroutines) - Compilação para binário único - Tipagem estática forte

Desvantagens: - Curva de aprendizado - Ecossistema menor que Node.js - Menos bibliotecas prontas

Status

✅ Implementado e funcionando bem.


Clean Architecture Simplificada

Decisão

Adotar Clean Architecture de forma simplificada (Handlers → Services → Repositories → Models).

Contexto

Necessidade de: - Separação de responsabilidades - Testabilidade - Manutenibilidade - Sem over-engineering

Alternativas Consideradas

  1. MVC Tradicional
  2. ❌ Menos separação de responsabilidades
  3. ✅ Mais simples

  4. Clean Architecture Completa

  5. ❌ Muito complexo para o tamanho do projeto
  6. ✅ Máxima separação

  7. Hexagonal Architecture

  8. ❌ Similar complexidade
  9. ✅ Boa separação

Trade-offs

Vantagens: - Separação clara de responsabilidades - Fácil de testar - Fácil de entender - Escalável

Desvantagens: - Mais camadas que MVC simples - Requer disciplina

Status

✅ Implementado. Funciona bem para o tamanho atual do projeto.


Repository Pattern

Decisão

Usar Repository Pattern para abstrair acesso a dados.

Contexto

Necessidade de: - Testabilidade (mock de repositories) - Flexibilidade (trocar implementação) - Separação de lógica de negócio e acesso a dados

Alternativas Consideradas

  1. Acesso Direto ao GORM
  2. ❌ Difícil de testar
  3. ❌ Lógica de acesso misturada com negócio
  4. ✅ Mais simples

  5. Active Record Pattern

  6. ❌ Menos flexível
  7. ✅ Mais direto

Trade-offs

Vantagens: - Fácil de mockar em testes - Pode trocar implementação (ex: de GORM para SQL puro) - Separação clara

Desvantagens: - Mais código boilerplate - Camada adicional

Status

✅ Implementado. Facilita muito os testes.


JWT para Autenticação

Decisão

Usar JWT (JSON Web Tokens) para autenticação stateless.

Contexto

Necessidade de: - Autenticação stateless (escalável) - Funcionar em múltiplos clientes (web, mobile) - Sem necessidade de sessões no servidor

Alternativas Consideradas

  1. Sessões no Servidor (cookies)
  2. ❌ Requer armazenamento no servidor
  3. ❌ Menos escalável
  4. ✅ Mais seguro (revogação fácil)

  5. OAuth 2.0 Completo

  6. ❌ Mais complexo
  7. ✅ Padrão da indústria

Trade-offs

Vantagens: - Stateless (escalável) - Funciona em múltiplos clientes - Padrão da indústria

Desvantagens: - Revogação mais difícil (precisa de blacklist) - Tokens podem ser roubados (XSS)

Status

✅ Implementado. Funciona bem. Considerar refresh tokens com blacklist no futuro.


PostgreSQL como Banco Principal

Decisão

Usar PostgreSQL como banco de dados principal.

Contexto

Necessidade de: - Relacionamentos complexos - Transações ACID - Suporte a JSON (para regras flexíveis) - Confiabilidade

Alternativas Consideradas

  1. MySQL
  2. ❌ Suporte JSON inferior
  3. ✅ Muito popular

  4. MongoDB (NoSQL)

  5. ❌ Sem transações ACID completas
  6. ❌ Relacionamentos mais complexos
  7. ✅ Flexível para esquema

  8. SQLite

  9. ❌ Não adequado para produção multi-usuário
  10. ✅ Simples

Trade-offs

Vantagens: - Relacionamentos complexos - Transações ACID - JSON nativo (JSONB) - Confiável e maduro

Desvantagens: - Requer servidor dedicado - Mais complexo que SQLite

Status

✅ Implementado. PostgreSQL atende todas as necessidades.


React Query para Estado do Frontend

Decisão

Usar TanStack Query (React Query) para gerenciar estado de servidor.

Contexto

Necessidade de: - Cache automático de dados do servidor - Sincronização - Loading states - Refetch automático

Alternativas Consideradas

  1. Redux
  2. ❌ Muito boilerplate
  3. ❌ Overkill para dados do servidor
  4. ✅ Padrão da indústria

  5. Context API + useState

  6. ❌ Sem cache automático
  7. ❌ Sem sincronização
  8. ✅ Nativo do React

  9. SWR

  10. ✅ Similar ao React Query
  11. ❌ Menos features

Trade-offs

Vantagens: - Cache automático - Sincronização - Loading/error states - Refetch inteligente

Desvantagens: - Dependência externa - Curva de aprendizado

Status

✅ Implementado. Simplifica muito o código do frontend.


Radix UI para Componentes

Decisão

Usar Radix UI como base para componentes acessíveis.

Contexto

Necessidade de: - Componentes acessíveis - Customizáveis - Headless (sem estilos)

Alternativas Consideradas

  1. Material UI
  2. ❌ Estilos pré-definidos difíceis de customizar
  3. ✅ Muito completo

  4. Chakra UI

  5. ✅ Boa customização
  6. ❌ Menos componentes

  7. Componentes próprios

  8. ❌ Muito trabalho
  9. ✅ Controle total

Trade-offs

Vantagens: - Acessibilidade built-in - Totalmente customizável - Headless (sem estilos)

Desvantagens: - Precisa estilizar tudo - Menos componentes prontos

Status

✅ Implementado. Funciona bem com Tailwind CSS.


Railway para Deploy

Decisão

Usar Railway para deploy do backend e frontend.

Contexto

Necessidade de: - Deploy simples - Gerenciamento de variáveis de ambiente - Escalabilidade - Custo razoável

Alternativas Consideradas

  1. AWS (EC2, ECS, Lambda)
  2. ❌ Mais complexo
  3. ❌ Mais caro
  4. ✅ Muito flexível

  5. Heroku

  6. ❌ Mais caro
  7. ✅ Muito simples

  8. DigitalOcean

  9. ❌ Mais configuração manual
  10. ✅ Mais barato

Trade-offs

Vantagens: - Deploy simples (Git push) - Gerenciamento de env vars - Escalabilidade automática - Preço razoável

Desvantagens: - Menos controle que AWS - Vendor lock-in

Status

✅ Implementado. Funciona bem para o tamanho atual.


Cloudflare R2 para Storage

Decisão

Usar Cloudflare R2 para armazenamento de arquivos (imagens de símbolos).

Contexto

Necessidade de: - Armazenamento de imagens - URLs públicas - Custo baixo - Compatível com S3

Alternativas Consideradas

  1. AWS S3
  2. ❌ Mais caro (egress fees)
  3. ✅ Padrão da indústria

  4. Google Cloud Storage

  5. ❌ Mais complexo
  6. ✅ Integração com Google

  7. Armazenamento local

  8. ❌ Não escalável
  9. ✅ Simples

Trade-offs

Vantagens: - Sem egress fees - Compatível com S3 API - Preço baixo - CDN integrado

Desvantagens: - Vendor lock-in - Menos maduro que S3

Status

✅ Implementado. Funciona bem e reduz custos.


Referências