Hipóteses Técnicas e Alternativas
Para chegar à arquitetura atual, avaliamos diversas hipóteses e caminhos técnicos. Nesta página, detalhamos os "Porquês" por trás de cada escolha, comparando nossa solução com abordagens convencionais e alternativas descartadas.
1. Gestão de Estado: Redux vs. Context API
Hipótese A: Apenas React Context
- A Ideia: Usar o Context API nativo do React para gerenciar o estado global de cada domínio.
- Vantagem: Menor boilerplate, sem dependências externas, curva de aprendizado baixa.
- O Problema (Escala 100M): O Context API causa re-renderizações em massa quando o estado é atualizado, a menos que seja quebrado em centenas de pequenos contextos. Em uma tela de telemedicina com vídeo, chat e prontuário (dados mudando a cada milissegundo), a performance degradaria rapidamente. Além disso, falta o suporte a middlewares complexos e ferramentas de debug (DevTools) robustas.
- Veredito: Descartado para lógica de negócio complexa. Mantido apenas para dados estáticos (Tema, Autenticação básica).
Hipótese B: Redux Toolkit + Redux-Saga (Nossa Escolha)
- A Ideia: Centralizar a lógica assíncrona e o estado imutável.
- Vantagem: Previsibilidade total, ferramentas de depuração de nível industrial, e a capacidade de tratar efeitos colaterais (como WebSockets e Timers) de forma isolada da UI.
- Por que Saga?: Diferente do
Thunk, oSagapermite lidar com fluxos de "corrida" (race conditions) e cancelamentos de forma elegante, o que é vital quando um médico clica rápido demais ou a internet oscila.
2. Isolamento: Monólito Convencional vs. Domínios Isolados
Hipótese C: Arquitetura "Flat" (Tudo em um lugar só)
- A Ideia: Colocar todos os Reducers em um
rootReducere todos os componentes em/components. - Vantagem: Muito rápido para começar o projeto.
- O Problema: Conforme o sistema cresce para atender 26 estados e dezenas de especialidades, o bundle (arquivo JS final) torna-se gigantesco. Um erro em "Agendamento" pode impedir o carregamento da "Agenda". O acoplamento é inevitável.
- Veredito: Descartado. Inviável para 100 milhões de usuários com internet limitada.
Hipótese D: Domínios com Injeção Dinâmica (Nossa Escolha)
- A Ideia: Cada domínio (
Consultation,Chat,Users) é um "mini-app" que só entra na memória quando solicitado. - Vantagem: O navegador só processa o código necessário. Se o usuário é um Paciente, ele nunca baixa o código do módulo de "Prescrição Médica". Isso economiza bateria, memória e dados.
3. Fluxo de Processo: Booleans vs. State Machines
Hipótese E: Controle via Flags (isLoading, isFinished)
- A Ideia: Usar variáveis booleanas no Redux para controlar o que aparece na tela.
- Vantagem: Simples de entender inicialmente.
- O Problema: Gera "Estados Impossíveis". Como impedir que
isStartedeisFinishedsejam true ao mesmo tempo por um erro de lógica? Em saúde, isso pode levar a salvar dados em momentos errados. - Veredito: Descartado para fluxos críticos.
Hipótese F: XState (Máquinas de Estado - Nossa Escolha)
- A Ideia: Definir estados fixos e transições permitidas.
- Vantagem: O sistema é matematicamente seguro. Se não existe uma seta ligando "Agendado" a "Finalizado" sem passar por "Em Atendimento", o erro humano é bloqueado pelo próprio código.
4. Comunicação: Importação Direta vs. Event-Driven
Hipótese G: Importação Lateral (import { action } from '../other-domain')
- A Ideia: Um domínio chama funções de outro diretamente.
- Vantagem: Fácil de seguir o fluxo com "Go to Definition".
- O Problema: Cria um emaranhado de dependências. Para testar o "Chat", você acaba tendo que carregar o "Prontuário", porque um depende do outro. Se quiser remover o "Chat" no futuro, o sistema inteiro quebra.
- Veredito: Proibido.
Hipótese H: Domain Events (Nossa Escolha)
- A Ideia: Domínios emitem eventos ("Consulta Finalizada") e outros reagem se quiserem.
- Vantagem: Desacoplamento total. O módulo de Agendamento pode ser adicionado meses depois sem que o módulo de Consulta precise ser alterado.
5. Estrutura de Repositório: Multi-repo vs. Monorepo
Hipótese I: Multi-repo (Um projeto para cada app/package)
- A Ideia: Ter repositórios Git separados para
app-medical,app-patient,ui-library, etc. - Vantagem: Isolamento total de código e histórico de commits. Permite deploys e versões completamente independentes por time.
- O Problema (Escala 100M): Gerenciar versões de dependências compartilhadas vira um "inferno de atualizações". Se mudarmos a interface de um contrato de saúde em
packages/contracts, precisaríamos abrir 10 Pull Requests em repositórios diferentes e garantir que todos façam deploy na ordem certa. O "Type Safety" de ponta a ponta é perdido ou fica muito difícil de manter. - Veredito: Descartado para o estágio atual de desenvolvimento acelerado.
Hipótese J: Monorepo Modular (Nossa Escolha)
- A Ideia: Um único repositório com
apps/epackages/bem definidos. - Vantagem: Refatoração Atômica. Se eu mudar um tipo no contrato, o compilador me avisa instantaneamente em todos os apps que usam aquele tipo. O compartilhamento de código (DRY) é natural e a governança é centralizada em um único pipeline de CI/CD.
6. Renderização: Server-Side (SSR) vs. Client-Side (CSR)
Hipótese K: Server-Side Rendering (Next.js / Remix)
- A Ideia: Gerar o HTML no servidor para cada requisição.
- Vantagem: Melhor SEO (não crítico para apps logados) e percepção de carregamento inicial mais rápida em alguns casos.
- O Problema: Em sistemas de saúde com 100M de usuários, o custo de infraestrutura para processar milhões de renderizações no servidor é altíssimo. Além disso, telas de telemedicina são extremamente interativas e dependem de APIs de navegador (WebRTC, Bluetooth), que não existem no servidor, gerando complexidade de "hidratação" e erros de
window is not defined. - Veredito: Descartado para as áreas logadas.
Hipótese L: Client-Side Rendering (CSR) com SPA (Nossa Escolha)
- A Ideia: O servidor entrega arquivos estáticos (HTML/JS/CSS) e o navegador faz o trabalho pesado.
- Vantagem: Escalabilidade horizontal barata (arquivos estáticos em CDNs). Uma vez carregado, o app é instantâneo.
- Otimização para 100M: Usamos Lazy Loading agressivo para mitigar o problema do carregamento inicial do SPA, garantindo que o usuário só baixe o que precisa para sua região e seu papel (Médico/Paciente).
7. Estilização: CSS-in-JS vs. Utility-First (Tailwind)
Hipótese M: Styled-components / Emotion (Runtime CSS)
- A Ideia: Escrever CSS dentro do JavaScript.
- Vantagem: Escopo automático, facilidade para usar props do React no estilo.
- O Problema: Performance de Runtime. Em telas com centenas de campos de prontuário, o custo de processar estilos no JavaScript em cada renderização pode causar lentidão (lag) em celulares mais simples de usuários em regiões remotas do Brasil.
- Veredito: Descartado para componentes de alta performance.
Hipótese N: Tailwind CSS / CSS Modules (Nossa Escolha)
- A Ideia: CSS pré-processado ou classes utilitárias.
- Vantagem: Zero custo de runtime. O CSS é gerado no build. O Tailwind, especificamente, garante um bundle final minúsculo, pois as classes são reutilizadas exaustivamente, o que é perfeito para usuários com internet 3G instável nos 26 estados.
8. Estratégia de Micro-Frontends (MFE)
Hipótese O: Micro-Frontends desde o Dia 1 (Module Federation)
- A Ideia: Separar cada domínio em uma URL diferente e juntar tudo em runtime.
- O Problema: Complexidade prematura. Debugging difícil, orquestração de versões complexa e perda de performance no carregamento inicial (múltiplos requests de infraestrutura).
- Veredito: Mantido como "Norte" (Roadmap), mas não implementado agora.
Hipótese P: Modular Monolith (Nossa Escolha Atual)
- A Ideia: Código isolado logicamente, mas compilado em conjunto.
- Vantagem: Melhor equilíbrio entre isolamento e facilidade de desenvolvimento. Como nossos domínios já seguem o padrão de MFE (Injeção Dinâmica, Eventos), a migração para Module Federation no futuro será apenas uma mudança de configuração de build, e não uma reescrita de código.
Resumo Comparativo Atualizado
| Recurso | Abordagem Convencional | Nossa Abordagem (Escala 100M) | Motivo da Escolha |
|---|---|---|---|
| Estado | Context / Redux Global | Redux c/ Injeção Dinâmica | Performance e Memória |
| Lógica Assíncrona | useEffect / Thunks | Redux-Sagas | Controle de Race Conditions |
| Organização | Por Tipo (folders) | Por Domínio (Bounded Contexts) | Escalabilidade de Times |
| Processos | Variáveis de Status (booleanas) | State Machines (XState) | Segurança Clínica |
| Dependências | Importações Livres | Monorepo + Boundaries + Eventos | Manutenibilidade e Segurança |
| Renderização | SSR (Next.js) | CSR (SPA) + Lazy Loading | Escala Nacional (Custo/Offline) |
| Estilização | CSS-in-JS (Runtime) | Tailwind/CSS Modules (Zero Runtime) | Performance em Celulares |
| Evolução | Micro-Frontends Prematuros | Modular Monolith (MFE Ready) | Simplicidade e Velocidade |