Comparativo de Abordagens de Organização
Para compreender o valor da nossa arquitetura de Domínios Isolados, é necessário contrastá-la com os modelos tradicionais de desenvolvimento React. Abaixo, analisamos as três principais formas de organizar features e como elas se comportam em sistemas de saúde de larga escala.
1. Arquitetura Convencional (Flat/Layered)
Neste modelo, o código é organizado puramente por "tipo técnico" (pasta de componentes, pasta de reducers, pasta de hooks).
src/
├── components/ # Botão de Login misturado com Header do Prontuário
├── store/ # Um único arquivo gigante (rootReducer) com tudo
├── services/ # Todas as chamadas de API (Consultas, Exames, Usuários)
└── pages/ # Rotas que importam de todos os lugaresCaracterísticas:
- Acoplamento Total: Qualquer alteração no
store/pode quebrar partes não relacionadas do sistema. - Dificuldade de Busca: Para entender a funcionalidade de "Prescrição", o desenvolvedor precisa pular entre 5 pastas distantes.
- Escalabilidade Baixa: Conforme o sistema cresce, as pastas
components/estore/tornam-se ingovernáveis (centenas de arquivos). - Sem Barreiras: Nada impede um componente de Login de acessar o estado de um Prontuário.
2. Feature por Pasta (Standard Modular)
Uma evolução onde cada "feature" tem sua própria pasta, mas ainda dentro do mesmo projeto/bundle.
src/
├── features/
│ ├── consultation/
│ │ ├── components/
│ │ ├── api.ts
│ │ └── store.ts
│ └── chat/
│ ├── components/
│ └── store.tsCaracterísticas:
- Melhor Localidade: O código relacionado está mais próximo.
- Acoplamento Lateral Silencioso: Embora em pastas diferentes, os desenvolvedores frequentemente importam arquivos de uma feature para outra (
import { X } from '../chat'). - Bundle Monolítico: Geralmente, todo o código das features é compilado em um único arquivo final, aumentando o tempo de carregamento inicial.
- Dificuldade de Reuso: Difícil extrair uma feature para outro App sem levar dependências "fantasmas".
3. Feature-Module Isolado (Nossa Abordagem)
Nossa arquitetura eleva as features ao nível de Pacotes Locais (Domains) em um monorepo, com barreiras físicas e regras de injeção.
packages/
├── domains/
│ ├── consultation/ (Pacote isolado com index.ts rigoroso)
│ └── chat/ (Pacote isolado)
├── contracts/ (Único ponto de compartilhamento de tipos)
└── core/ # Infraestrutura comumPor que esta é a melhor escolha para Saúde Digital?
| Critério | Convencional | Feature por Pasta | Domínios Isolados (Nossa) |
|---|---|---|---|
| Isolamento | Inexistente | Lógico (Fraco) | Físico (Rigoroso) |
| Comunicação | Chamada Direta | Importação Direta | Domain Events (Pub/Sub) |
| Performance | Carrega Tudo | Lazy Loading Simples | Injeção Dinâmica (State + UI) |
| Escalabilidade | Caótica | Moderada | Alta (Múltiplos Times) |
| Segurança/Auditoria | Difícil | Complexa | Nativa (XState + Guards) |
Resumo do Comparativo
- Isolamento Físico vs. Lógico: Em nossa arquitetura, se você tentar importar algo do
domain/chatdentro dodomain/consultation, o sistema de build (ou ESLint) irá barrar. No modelo "por pasta", isso é permitido, o que eventualmente cria um "emaranhado" de dependências impossível de desfazer. - Linguagem Ubíqua: Nossos domínios representam Bounded Contexts do DDD. O termo "Paciente" no domínio de
Schedulingpode ter propriedades diferentes do "Paciente" no domínio deClinical. O isolamento garante que esses conceitos não se confundam. - Preparação para o Futuro: Enquanto os outros modelos exigem uma refatoração massiva para virar Microfrontends, nossa arquitetura já nasce "Microfrontend-Ready". Cada domínio é virtualmente uma aplicação independente que apenas "mora" no mesmo repositório.
Conclusão
A abordagem de Domínios Isolados exige uma disciplina inicial maior, mas é a única que garante que um sistema de saúde complexo não se torne obsoleto ou excessivamente caro de manter após 2 anos de desenvolvimento por múltiplos times.