DB Designer
Ferramenta para criação, visualização e gerenciamento de Diagramas Entidade-Relacionamento (DER).
Neste documento, detalho minha análise arquitetural, os padrões de design e as decisões técnicas implementadas no DB Designer, uma ferramenta do lado do cliente voltada para a criação, visualização e gerenciamento de Diagramas Entidade-Relacionamento (ERD).
Utilidade e Funcionamento Geral
O propósito principal pelo qual construí o DB Designer é atender à necessidade de modelar esquemas de banco de dados de forma rápida, visual e sem depender de infraestrutura em nuvem. Com frequência, observo que as ferramentas de design de banco de dados exigem configurações complexas, contas de usuário ou conexões com bancos de dados reais. Decidi mitigar essa barreira projetando o sistema para operar completamente offline e persistir as informações localmente usando IndexedDB.
O fluxo de trabalho principal que estruturei é direto:
- Inicialização: O usuário acessa o painel principal, onde pode visualizar projetos anteriores ou iniciar um novo (do zero ou a partir de modelos predefinidos).
- Modelagem Visual: No editor que programei, o usuário adiciona nós que representam tabelas. Implementei a adição dinâmica de campos em cada tabela, permitindo especificar seu nome, tipo de dado e se atua como Chave Primária (PK) ou Chave Estrangeira (FK).
- Relacionamentos Interativos: Ao conectar nós, meu sistema gera automaticamente representações visuais dos relacionamentos (por exemplo, 1:N), inferindo a semântica a partir da conexão gráfica. Desenvolvi um sistema de roteamento inteligente (Smart Edges) para otimizar visualmente o posicionamento dos pontos de conexão.
- Visualização e Exportação: O usuário pode pré-visualizar o código SQL gerado a partir do modelo visual e exportar o diagrama completo como imagem, recurso que adicionei para garantir que o design possa ser facilmente integrado a documentação externa.
Análise Aprofundada da Arquitetura e dos Modelos
Concebi este projeto sob uma arquitetura do lado do cliente focada na autonomia do navegador, aproveitando os recursos do App Router do Next.js, mas transferindo a carga computacional e de armazenamento inteiramente para o cliente.
Arquitetura Geral
O design da aplicação que criei reflete padrões-chave para manter um código desacoplado, manutenível e eficiente:
- Arquitetura Local-First: Deleguei a persistência de dados inteiramente ao navegador do usuário usando
IndexedDBpor meio da bibliotecaidb. Integrei essa abordagem para garantir privacidade desde o design, baixa latência e disponibilidade offline (viabilizada por PWA). Evitei intencionalmente acoplar um backend para gerenciar o estado central. - Gerenciamento de Estado Previsível: Utilizo
Zustandpara o estado global (como nós, arestas e histórico de desfazer/refazer), evitando o prop drilling e facilitando as atualizações reativas exigidas pelo canvas interativo (React Flow). - Separação de Responsabilidades: Isolei os componentes visuais (UI) em componentes reutilizáveis (Botões, Seletores, Popovers). Extraí a lógica matemática dos diagramas (posicionamento automático via
dagree cálculo de arestas inteligentes) para módulos puros localizados em/app/lib/.
graph TD
UI[Interface do Usuário React/Tailwind] --> RF[Canvas React Flow]
RF --> |Eventos de mutação| Zustand[Gerenciador de Estado Zustand]
Zustand --> |Assinatura/Salvamento| IDB[(IndexedDB Local)]
UI --> |Exportação| H2I[html-to-image]
UI --> |Pré-visualização SQL| Monaco[Monaco Editor]
subgraph "Lógica de Negócio (lib)"
AutoLayout[Auto-layout Dagre]
SmartEdges[Cálculo de Conexões]
end
Zustand <--> AutoLayout
RF <--> SmartEdges
Modelagem de Dados e Lógica
Consolidei as definições do modelo de domínio em tipos estritos de TypeScript (/app/types.ts), o que me permite garantir a consistência em todo o fluxo de dados. Organizei as entidades principais em torno da estrutura de um diagrama ER:
- Project: A entidade raiz que contém os metadados do diagrama (ID, nome, datas de criação e atualização), bem como a coleção de nós e arestas.
- TableNodeData: O payload principal de cada nó do React Flow. Contém o rótulo da tabela, sua cor semântica e um array de colunas.
- Column: Define os atributos de uma tabela, incluindo seu tipo de dado SQL, identificadores e flags booleanas para restrições primárias ou estrangeiras.
classDiagram
class Project {
+String id
+String name
+Number createdAt
+Number updatedAt
+AppNode[] nodes
+AppEdge[] edges
+EdgeSettings edgeSettings
}
class AppNode {
+String id
+String type
+Object position
+TableNodeData data
}
class TableNodeData {
+String label
+String color
+Column[] columns
}
class Column {
+String id
+String name
+ColumnType type
+Boolean isPk
+Boolean isFk
}
Project "1" *-- "*" AppNode : contém
AppNode "1" *-- "1" TableNodeData : payload
TableNodeData "1" *-- "*" Column : define
Trato o estado dos nós de forma imutável. Os eventos interativos da interface (como adicionar um campo pressionando “Enter”) disparam ações granulares que programei para atualizar apenas o segmento relevante do meu store Zustand.
Stack Tecnológico
As decisões tecnológicas que tomei refletem meu foco em interatividade avançada e experiência do desenvolvedor:
| Ferramenta | Papel Técnico na Arquitetura |
|---|---|
| Next.js 16.1 (App Router) | Escolhido como framework base para o roteamento de páginas, a estrutura do projeto e a configuração de PWA. |
| React 19 | Biblioteca principal de UI; utilizada para gerenciar a reatividade, componentes de portal e eventos do DOM. |
| Zustand | Utilizado para o gerenciamento de estado global assíncrono e síncrono. Suporta o sistema de Desfazer/Refazer do editor que implementei. |
| React Flow (@xyflow/react) | Integrado como motor central de renderização do editor visual de grafos. Permite gerenciar o canvas interativo, os nós e as conexões. |
| IndexedDB (idb) | Fornece armazenamento local assíncrono no navegador. Sustenta minha decisão de persistência local-first para o modelo Project. |
| Tailwind CSS v4 | Sistema de design baseado em utilitários; utilizado para gerenciar variáveis CSS semânticas aplicadas aos modos claro/escuro. |
| Monaco Editor | Componente de editor de código integrado para oferecer uma pré-visualização robusta da sintaxe SQL. |
| Dagre | Utilizado como motor de posicionamento automático (Auto-Layout) para grafos direcionados, ordenando visualmente esquemas de diagramas complexos. |
Impacto das Decisões de Design
A arquitetura que projetei maximiza a velocidade de resposta em um ambiente com um alto número de mutações rápidas na interface (arrastar nós, editar texto interativo). Ao aplicar persistência local assíncrona e um gerenciador de estado leve, evitei completamente gargalos de rede. O uso extensivo de tipos estritos em TypeScript e a separação de camadas (isolando a apresentação do cálculo de geometria visual) garantem que o projeto mantenha alta estabilidade. Essa estrutura me permite estender o sistema no futuro, adicionando novas funcionalidades analíticas ou generativas aos esquemas de banco de dados sem realizar refatorações destrutivas.
Arraste para mover o diagrama. Use + e − para dar zoom, as setas para movê-lo e 0 para redefinir a visualização.
Vamos trabalhar juntos
Engenheiro de Software e desenvolvedor Senior Full-Stack, trabalho remotamente a partir de Santa Cruz, Bolívia. Aberto a novas oportunidades.