Linguagem DOT do Graphviz: o guia prático que a documentação oficial não te dá
🇬🇧 English • 🇮🇹 Italiano • 🇪🇸 Español • 🇩🇪 Deutsch
Para desenvolvedores, analistas e arquitetos de software que querem produzir diagramas profissionais, claros e bonitos de ver
O que é a linguagem DOT? O que é o Graphviz?
DOT é uma linguagem textual de descrição de grafos. Ela permite descrever nós, arestas e atributos visuais com uma sintaxe simples e legível. É o formato padrão usado pelo Graphviz.
Graphviz (Graph Visualization Software) é um conjunto open source de ferramentas para visualização de grafos. Desenvolvido originalmente no AT&T Labs, o Graphviz lê arquivos DOT e gera imagens em vários formatos (SVG, PNG, PDF). É a ferramenta mais usada no mundo para gerar diagramas a partir de código.
Por que usar DOT e Graphviz em vez de ferramentas gráficas?
- Versionável: arquivos DOT são texto puro, perfeitos para o Git
- Reproduzível: o mesmo arquivo sempre gera o mesmo diagrama
- Automatizável: gere diagramas no seu pipeline de CI/CD
- Rápido: escreva código, em vez de arrastar caixas com o mouse
- Profissional: saída de alta qualidade para documentação técnica
Prefácio
Por que escrevi este manual? Porque guias de DOT e Graphviz existem, mas cobrem de tudo: biologia, química, redes sociais, árvores genealógicas. Toda vez eu tinha que garimpar o que realmente importa para quem desenvolve software. Então decidi escrever este guia, juntando tudo o que usei ao longo dos anos e que precisei procurar de novo, e de novo. Deu trabalho, mas espero que valha a pena. Agora estou compartilhando.
A vantagem de gerar diagramas a partir de código? O arquivo DOT mora no repositório, junto com o código-fonte. Quando você muda a arquitetura, atualiza o diagrama no mesmo commit, ele passa pelo mesmo code review, segue o mesmo workflow. Não é um PowerPoint esquecido em algum drive que ninguém nunca mais vai abrir. Faz parte do projeto.
E tem mais. Arquivos DOT são texto, então você pode gerá-los programaticamente. O seu software pode produzir diagramas que mostram o estado atual do sistema, as fases de um processo, o caminho de uma requisição pelos microsserviços, as dependências entre módulos carregados em runtime. Já vi times gerando automaticamente mapas de migrações de banco de dados, grafos das feature flags ativas e até diagramas de filas de mensagens em tempo real. As possibilidades não têm fim.
Se você também está cansado de screenshots que ficam desatualizados no dia seguinte, aqui vai encontrar tudo o que precisa para começar. E, quando dominar o DOT, vai descobrir que os diagramas deixam de ser documentação estática: viram uma parte viva do seu sistema.
Daniele Teti
Novembro de 2025
Introdução
No dia a dia de quem desenvolve software, seja você analista, desenvolvedor backend, desenvolvedor frontend, especialista em banco de dados ou arquiteto, sempre chega o momento em que um diagrama se torna indispensável.
Você precisa dele quando tem que:
- explicar um fluxo complexo,
- desenhar o pipeline de CI/CD,
- descrever a arquitetura para um colega novo,
- analisar as dependências entre módulos,
- documentar um banco de dados,
- preparar uma apresentação técnica,
- raciocinar sobre uma refatoração,
- identificar gargalos.
O Graphviz e a sua linguagem DOT são ferramentas ideais: textuais (versionáveis), rápidas de escrever, bonitas de renderizar, flexíveis.
Instalando o Graphviz
Antes de começar, confira se o Graphviz está instalado:
- Windows: baixe o instalador em graphviz.org/download ou use
winget install graphviz - macOS:
brew install graphviz - Linux:
sudo apt install graphviz(Debian/Ubuntu) ousudo dnf install graphviz(Fedora/RHEL)
Confira a instalação com dot -V: deve aparecer a versão instalada.
Este manual pretende ser o guia definitivo para quem trabalha com software e quer tirar o máximo da linguagem DOT. Você vai encontrar:
- explicação detalhada dos atributos com todas as opções relevantes,
- exemplos completos, reutilizáveis e comentados,
- boas práticas para gráficos profissionais,
- dicas sobre o uso dos layout engines,
- cenários concretos do mundo do desenvolvimento (design, refatoração, análise, arquitetura).
A linguagem DOT: bases sólidas
O DOT descreve grafos com uma sintaxe muito simples:
digraph Name {
nodeA -> nodeB;
}
Ou não direcionado:
graph Name {
nodeA -- nodeB;
}
Conceitos-chave:
- nós (nodes): entidades (funções, objetos, microsserviços, tabelas do banco)
- arestas (edges): relações, chamadas, fluxos
- atributos: aparência visual ou metadados
Quick Start: seu primeiro diagrama em 30 segundos
Teste agora mesmo online (sem instalar nada)
Todos os exemplos deste artigo podem ser testados direto online com o Edotor.net:
Acesse edotor.net
Copie o código DOT de qualquer exemplo deste artigo
Cole na área da esquerda (substituindo o código que já está lá)
Veja a renderização imediata na área da direita
É o jeito mais rápido de experimentar sem instalar o Graphviz. Quando estiver pronto para produção, instale o Graphviz localmente.
Primeiro exemplo para testar
Copie este código e teste no edotor.net:
digraph MyFirstGraph {
node [shape=box, style=rounded, fillcolor=lightblue, style="rounded,filled"];
edge [color=blue];
Start -> Process -> End;
Process -> Error [style=dashed, label="on failure"];
Error -> Process [label="retry"];
}
Ou use a linha de comando local
Crie um arquivo hello.dot com o código acima e gere a imagem SVG:
dot -Tsvg hello.dot -o hello.svg
Abra hello.svg no navegador e você verá o seu primeiro fluxograma! Daqui em diante, tudo se baseia em variações e combinações desses conceitos.
Atributos fundamentais (com as opções completas)
Os atributos podem ser aplicados globalmente a:
graphnodeedge- elementos individuais
Exemplo:
digraph demo {
graph [rankdir=LR];
node [shape=box];
edge [color=grey];
A -> B;
}
A seguir, uma lista dos atributos mais importantes, com as opções mais úteis no desenvolvimento de software.
Atributos dos nós (node)
shape: forma do nó
Opções úteis:
boxellipsecirclediamond(decisões nos fluxos)record(diagramas de classes, estruturas de dados)plaintext(conteúdo totalmente personalizado com HTML-label)notefolder(disponível em alguns builds)
Exemplo:
node [shape=box];
Usos típicos:
- box → módulos de software
- ellipse → estados
- diamond → decisões
style: estilo gráfico
Opções comuns:
filleddasheddottedboldrounded- combinações:
"filled,rounded"
Exemplo:
node [style="filled,rounded"];
fillcolor: cor de preenchimento
Formatos:
- nomes (por exemplo
"lightgrey") - HEX (por exemplo
"#AABBCC") - RGB (
"#rrggbb") - HSL (em alguns builds)
fontname, fontcolor, fontsize
Por exemplo:
node [fontname="Segoe UI", fontsize=12, fontcolor="#333333"];
margin
Margem interna do nó.
node [margin="0.2,0.1"];
width e height: dimensões do nó
Controlam o tamanho dos nós. Por padrão, o Graphviz dimensiona os nós automaticamente de acordo com o conteúdo.
node [width=1.5, height=0.8];
fixedsize: força as dimensões exatas:
fixedsize=false(padrão): o nó cresce para acomodar o conteúdo, tratando width/height como valores mínimosfixedsize=true: o nó tem exatamente as dimensões de width/height, independentemente do conteúdofixedsize=shape: vale só para a forma, não para o label
Casos de uso práticos:
- Aparência uniforme: use
fixedsize=truecomwidthpara deixar todos os nós do mesmo tamanho (essencial em diagramas de estados e fluxogramas) - Tamanho adaptável: use o padrão
fixedsize=falsepara os nós se adaptarem ao comprimento do conteúdo - Só largura fixa: combine com
heightpara controlar a proporção
// Todos os estados do mesmo tamanho (FSM profissional)
node [shape=circle, fixedsize=true, width=0.9];
// Tamanho mínimo, mas pode crescer
node [shape=box, width=1.0, fixedsize=false];
label e xlabel: labels dos nós
label: o label padrão, mostrado dentro do nó ou perto dele:
A [label="State A"];
Labels em várias linhas: use \n para quebrar a linha:
A [label="Main Title\nSubtitle or description"];
xlabel: label externo, posicionado fora da borda do nó. O Graphviz encontra sozinho a melhor posição para evitar sobreposições com arestas e outros nós. Muito útil em diagramas de estados, quando você quer manter os estados limpos:
A [xlabel="State A"];
Exemplo prático comparando label e xlabel:
digraph LabelComparison {
graph [rankdir=LR, fontname="Segoe UI"];
node [shape=circle, fontsize=11, fontname="Segoe UI"];
edge [fontname="Segoe UI"];
subgraph cluster_standard {
label="Using label (internal)";
style=filled;
fillcolor="#F5F5F5";
S1 [label="Idle"];
S2 [label="Running"];
S3 [label="Done"];
S1 -> S2 [label="start"];
S2 -> S3 [label="finish"];
S3 -> S1 [label="reset"];
}
subgraph cluster_external {
label="Using xlabel (external)";
style=filled;
fillcolor="#F5F5F5";
X1 [xlabel="Idle"];
X2 [xlabel="Running"];
X3 [xlabel="Done"];
X1 -> X2 [label="start"];
X2 -> X3 [label="finish"];
X3 -> X1 [label="reset"];
}
}
Quando usar o xlabel:
- Diagramas de estados: para manter os círculos dos estados visualmente limpos
- Grafos complexos: para reduzir a poluição visual dentro dos nós
- Posicionamento automático: para deixar o Graphviz encontrar o melhor lugar para o label
- Nós pequenos: quando labels internos deixariam os nós grandes demais
Adicionando notas e anotações aos nós
Existem várias técnicas para acrescentar notas explicativas, descrições ou anotações aos nós dos seus diagramas, especialmente úteis em mapas mentais, documentação e arquiteturas complexas.
Técnica 1: labels em várias linhas com \n
A abordagem mais simples: colocar quebras de linha dentro do label.
Concept [label="Main Concept\n(This is a note explaining the concept)"];
Técnica 2: tooltip com o atributo tooltip
Adicione um tooltip que aparece ao passar o mouse (funciona no SVG aberto no navegador):
Node [label="Cloud Storage", tooltip="Amazon S3, Azure Blob, Google Cloud Storage"];
Técnica 3: nó de nota separado, ligado com uma aresta tracejada
Crie um nó dedicado à nota, visualmente diferente dos nós principais:
MainNode [label="User Service"];
Note1 [shape=note, label="Handles authentication\nand user profiles", fillcolor="#FFFACD"];
MainNode -> Note1 [style=dashed, arrowhead=none, color="#CCCCCC"];
Técnica 4: labels estilo HTML com a forma record
Use records estruturados para separar o título da descrição:
node [shape=record];
Concept [label="{Concept Name|Description or note\labout this concept}"];
Exemplo completo: mapa mental com notas
graph MindMapWithNotes {
graph [layout=fdp, K=0.6, fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#E3F2FD", fontsize=11, fontname="Segoe UI"];
edge [color="#888888", fontname="Segoe UI"];
// Conceito principal (central)
Central [label="Project\nArchitecture", fillcolor="#BBDEFB", fontsize=14, width=2.0, height=1.0, pin=true, pos="0,0!"];
// Subconceitos (ao redor do centro)
Frontend [label="Frontend\nReact + TypeScript", width=1.8];
Backend [label="Backend\nNode.js + Express", width=1.8];
Database [label="Database\nPostgreSQL", width=1.5];
DevOps [label="DevOps\nDocker + CI/CD", width=1.5];
// Nós de nota (ligados aos conceitos)
FrontendNote [shape=note, label="Uses Redux\nfor state mgmt", fillcolor="#FFFACD", fontsize=10];
BackendNote [shape=note, label="RESTful API\n+ WebSocket", fillcolor="#FFFACD", fontsize=10];
DatabaseNote [shape=note, label="PostgreSQL\n+ migrations", fillcolor="#FFFACD", fontsize=10];
DevOpsNote [shape=note, label="Automated\ndeployments", fillcolor="#FFFACD", fontsize=10];
// Conexões principais (ramos do mapa mental)
Central -- Frontend;
Central -- Backend;
Central -- Database;
Central -- DevOps;
// Notas ligadas com linhas tracejadas (sem setas)
Frontend -- FrontendNote [style=dashed, color="#CCCCCC"];
Backend -- BackendNote [style=dashed, color="#CCCCCC"];
Database -- DatabaseNote [style=dashed, color="#CCCCCC"];
DevOps -- DevOpsNote [style=dashed, color="#CCCCCC"];
}
Quando usar cada técnica:
| Técnica | Ideal para | Prós | Contras |
|---|---|---|---|
\n em várias linhas | Notas curtas (1-2 linhas) | Simples, sempre visível | Pode deixar os nós grandes demais |
tooltip | Explicações longas | Não polui o diagrama | Só funciona em SVG interativo |
| Nó de nota separado | Anotações importantes | Bem visível, estilizável | Aumenta a complexidade visual |
| Record HTML | Dados estruturados | Separação limpa | Sintaxe mais complexa |
Atributos das arestas (edge)
arrowsize
Escala da seta. Padrão ~1.0
edge [arrowsize=0.8];
arrowhead / arrowtail
Opções úteis:
normalempty(triângulo vazado, muito legível)diamondonormalcrow(diagramas ER)teenone
style e color
edge [style=dashed, color="#888888"];
label
Label da aresta.
A -> B [label="calls"];
Atributos do grafo (graph)
rankdir
Direção do layout (só no dot):
TB(cima → baixo)BT(baixo → cima)LR(esquerda → direita)RL(direita → esquerda)
Por exemplo:
graph [rankdir=LR];
splines
Controla a forma das arestas:
true(padrão)false(linhas retas)polylineortho(ortogonais, ótimas para diagramas “de arquiteto”)
ranksep, nodesep
Espaçamento horizontal/vertical.
graph [ranksep=0.8, nodesep=0.6];
Como definir estilos para grupos de nós em DOT?
Uma das dúvidas mais comuns de quem usa o Graphviz é: como aplico o mesmo estilo a um grupo de nós sem repetir para cada um?
A resposta é simples: liste os nós na mesma linha, seguidos da definição dos atributos. O DOT aplica esses atributos a todos os nós listados.
Sintaxe para estilizar grupos de nós
Método 1: redefinir os padrões dos nós (recomendado)
// Redefine os padrões dos nós antes de cada grupo
node [shape=box, style=filled, fillcolor="#E8F4F8"];
A; B; C;
node [shape=ellipse, style=filled, fillcolor="#FFF4E6", fontname="Segoe UI"];
D; E; F;
node [shape=diamond, style=filled, fillcolor="#FFE8E8"];
G; H; I;
Método 2: listar os nós com os atributos
// Alternativa: listar os nós separados por ponto e vírgula, o último com os atributos
A; B; C [shape=box, style=filled, fillcolor="#E8F4F8"];
D; E; F [shape=ellipse, style=filled, fillcolor="#FFF4E6"];
G; H; I [shape=diamond, style=filled, fillcolor="#FFE8E8"];
Observação: o Método 1 é mais confiável entre as diferentes versões do Graphviz e facilita acrescentar nós a uma categoria depois.
Essa técnica é essencial quando você tem diagramas complexos, com dezenas de nós pertencentes a categorias diferentes.
Exemplo prático: categorizando os nós por papel
Imagine que você precisa desenhar uma arquitetura com três tipos de componentes: serviços (caixas azuis), bancos de dados (cilindros verdes), filas/mensagens (elipses laranja).
digraph Architecture {
graph [rankdir=LR, nodesep=0.8, fontname="Segoe UI"];
node [fontname="Segoe UI"];
edge [fontname="Segoe UI"];
// Serviços: caixas azuis
node [shape=box, style="filled,rounded", fillcolor="#E3F2FD"];
AuthService; UserService; OrderService; NotificationService;
// Bancos de dados: cilindros verdes
node [shape=cylinder, style=filled, fillcolor="#E8F5E9"];
UserDB; OrderDB; SessionCache;
// Filas de mensagens: elipses laranja
node [shape=ellipse, style=filled, fillcolor="#FFF3E0"];
EmailQueue; SMSQueue; PushQueue;
// Relações
AuthService -> SessionCache;
UserService -> UserDB;
OrderService -> OrderDB;
OrderService -> EmailQueue;
NotificationService -> EmailQueue;
NotificationService -> SMSQueue;
NotificationService -> PushQueue;
}
O que este exemplo faz: define três categorias de nós com estilos diferentes em só três linhas. Os serviços são caixas azuis arredondadas, os bancos de dados são cilindros verdes, as filas são elipses laranja. Cada categoria é reconhecível de imediato.
Por que usar essa técnica?
- Código DRY (Don’t Repeat Yourself): você não repete
shape=box, style=filledem cada nó - Manutenibilidade: mudar a cor de todos os serviços exige uma única edição
- Legibilidade: o código DOT se autodocumenta (você vê na hora quais nós são serviços e quais são bancos)
- Escalabilidade: acrescentar um serviço novo é só adicionar o nome à lista
Combinando com atributos padrão
Você pode combinar essa técnica com atributos padrão para ter o máximo de flexibilidade:
digraph Mixed {
// Padrão para todos os nós
node [fontname="Segoe UI", fontsize=11];
// Depois especializa por grupo
Input; Validation [shape=parallelogram, fillcolor="#B3E5FC", style=filled];
Process; Transform [shape=box, fillcolor="#C8E6C9", style=filled];
Output; Export [shape=parallelogram, fillcolor="#FFCCBC", style=filled];
Error [shape=octagon, fillcolor="#FFCDD2", style=filled];
Input -> Validation -> Process -> Transform -> Output -> Export;
Validation -> Error;
Process -> Error;
}
O que este exemplo faz: define um padrão comum (fonte Arial 11pt) e depois três grupos: input/output como paralelogramos (convenção dos fluxogramas), processos como caixas, erros como octógonos vermelhos.
Layout Engines: escolhendo o certo
O Graphviz não tem um único motor de renderização: oferece vários, cada um otimizado para tipos específicos de grafo. Escolher o engine certo significa ter diagramas mais legíveis e profissionais.
Você indica o engine com a flag -K na CLI:
dot -Kdot -Tsvg file.dot -o output.svg
dot -Kneato -Tsvg file.dot -o output.svg
Ou no próprio arquivo DOT:
graph G {
layout=neato;
// ...
}
A seguir, os principais engines e quando usar cada um.
Layout engines disponíveis
dot: layout hierárquico (padrão)
O que faz: organiza os nós de forma hierárquica, seguindo a direção das arestas. É o mais usado.
Perfeito para:
- Fluxogramas e diagramas de fluxo
- Pipelines de CI/CD
- Call graphs (grafo das chamadas entre funções)
- Arquiteturas em camadas (apresentação → negócio → dados)
- Processos sequenciais
- Diagramas de dependências com direção clara
Comando de exemplo:
dot -Tsvg flowchart.dot -o flowchart.svg
Exemplo visual:
digraph DotExample {
graph [rankdir=TB, fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#E3F2FD", fontname="Segoe UI"];
A -> B -> C;
A -> D -> C;
B -> E;
D -> E;
}
O que você vê: nós organizados em camadas hierárquicas claras, de cima para baixo. Perfeito para mostrar fluxo e dependências.
Quando evitar: se o grafo não tem uma estrutura hierárquica clara ou contém muitos ciclos.
neato: layout force-directed
O que faz: posiciona os nós simulando forças físicas (repulsão/atração), gerando layouts orgânicos e simétricos.
Útil para:
- Grafos não direcionados (sem setas)
- Redes conceituais e mapas mentais
- Relações não hierárquicas entre entidades
- Grafos pequenos/médios em que você quer destacar os agrupamentos naturais
Comando de exemplo:
dot -Kneato -Tsvg concepts.dot -o concepts.svg
Exemplo visual (o mesmo grafo de antes, com outro engine):
graph NeatoExample {
graph [layout=neato, fontname="Segoe UI"];
node [shape=ellipse, style=filled, fillcolor="#FFF4E6", fontname="Segoe UI"];
A -- B -- C;
A -- D -- C;
B -- E;
D -- E;
}
O que você vê: nós distribuídos de forma orgânica no espaço 2D, com agrupamentos naturais. Perfeito para mapas mentais e redes conceituais em que as relações não são hierárquicas.
Quando evitar: com grafos muito grandes (>100 nós) ou fortemente direcionais.
fdp: force-directed placement
O que faz: parecido com o neato, mas usa outro algoritmo (Fruchterman-Reingold). Em geral é mais rápido em grafos médios.
Útil para:
- Grafos não direcionados de tamanho médio
- Visualizações de redes sociais (amizades, conexões)
- Análise de dependências sem uma direção forte
Comando de exemplo:
dot -Kfdp -Tsvg network.dot -o network.svg
sfdp: scalable force-directed placement
O que faz: versão do fdp otimizada para grafos muito grandes (milhares de nós).
Ótimo para:
- Análise de dependências em codebases complexas
- Grafo de classes de um projeto enterprise
- Redes complexas (infraestrutura, microsserviços)
- Quando o
neatoou ofdpficam lentos demais
Comando de exemplo:
dot -Ksfdp -Tsvg dependencies.dot -o dependencies.svg
Dica: use o sfdp quando tiver mais de 100-200 nós.
circo: layout circular
O que faz: organiza os nós em círculos concêntricos ao redor de um nó central.
Ideal para:
- Visualizar módulos satélites ao redor de um núcleo central
- Arquiteturas hub-and-spoke
- Representar componentes que dependem de um serviço central
Comando de exemplo:
dot -Kcirco -Tsvg modules.dot -o modules.svg
Exemplo visual:
graph CircoExample {
graph [layout=circo, fontname="Segoe UI"];
node [shape=circle, style=filled, fillcolor="#E8F5E9", fontname="Segoe UI"];
Core -- Module1;
Core -- Module2;
Core -- Module3;
Core -- Module4;
Core -- Module5;
Module1 -- Module2;
Module3 -- Module4;
}
O que você vê: o nó central (Core) no meio, com os satélites dispostos em círculo ao redor. Perfeito para arquiteturas hub-and-spoke.
twopi: layout radial
O que faz: cria um layout de árvore radial, com o nó raiz no centro e os níveis se expandindo para fora.
Perfeito para:
- Árvores hierárquicas (organograma, sistema de arquivos)
- Taxonomias
- Mapas mentais estruturados
- Visualizar expansões a partir de um ponto central
Comando de exemplo:
dot -Ktwopi -Tsvg tree.dot -o tree.svg
Exemplo visual:
digraph TwopiExample {
graph [layout=twopi, ranksep=2.0, fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#FFEBEE", fontsize=11, width=1.0, height=0.5, fontname="Segoe UI"];
edge [color="#666666", fontname="Segoe UI"];
CEO [label="CEO", fillcolor="#FFCDD2"];
CEO -> Engineering [label=""];
CEO -> Sales [label=""];
CEO -> Marketing [label=""];
Engineering -> Dev1 [label=""];
Engineering -> Dev2 [label=""];
Sales -> Rep1 [label=""];
Sales -> Rep2 [label=""];
Marketing -> Designer [label=""];
Marketing -> Writer [label=""];
}
O que você vê: o CEO no centro, com os departamentos (Engineering, Sales, Marketing) no primeiro anel e os membros dos times no anel externo. Uma hierarquia radial clara, perfeita para organogramas.
Como escolher na prática
| Tipo de grafo | Engine recomendado |
|---|---|
| Fluxograma, pipeline, processos | dot |
| Arquiteturas em camadas | dot |
| Call graph, árvore de dependências | dot |
| Rede conceitual, brainstorming | neato |
| Rede social, grafos médios não direcionados | fdp |
| Grafos grandes (>200 nós) | sfdp |
| Hub central com satélites | circo |
| Árvores hierárquicas, organograma | twopi |
Regra prática: se você tem setas e uma direção clara → use dot. Caso contrário, teste neato ou fdp.
Tipos de diagrama e quando usá-los na vida real de um desenvolvedor
Esta é a seção mais substancial. Para cada tipo de diagrama você vai encontrar:
- Quando usar na vida real
- Atributos recomendados
- Exemplo completo
Fluxograma: entendendo o comportamento
No trabalho do dia a dia, é comum precisar explicar um fluxo de decisão complexo: um procedimento de validação com vários ramos, um processo de onboarding de usuário ou simplesmente o comportamento de uma função cheia de if/else aninhados. O fluxograma é a ferramenta ideal para isso.
Quando você precisa de um fluxograma:
Você está na fase de análise de requisitos e precisa entender todos os casos possíveis. Está depurando uma lógica que parece ter enlouquecido e quer ver visualmente onde o fluxo se ramifica. Precisa escrever a documentação de um processo de negócio complexo. Está fazendo o onboarding de um colega novo e quer mostrar como funciona o sistema de autenticação.
O fluxograma mostra visualmente as decisões (losangos), os processos (retângulos arredondados) e o fluxo lógico (setas). É imediato, claro, universal.
Atributos recomendados para fluxogramas profissionais:
Use rankdir=TB (de cima para baixo) para seguir a convenção padrão dos fluxogramas. Use shape=diamond para os nós de decisão (condições if/else). Use style=rounded para as etapas do processo, para que se destaquem dos losangos. Use cores suaves (fillcolor) para realçar o início (verde claro), os erros (vermelho claro) e o fim (cinza).
Exemplo completo:
digraph Flow {
graph [rankdir=TB, nodesep=0.6];
node [fontname="Segoe UI"];
Start [shape=oval, style=filled, fillcolor="#C1F2C7"];
Check [shape=diamond, label="Valid input?"];
Process [shape=box, style="filled,rounded", fillcolor="#F0F4FF"];
Error [shape=box, fillcolor="#FFEAEA", style=filled];
End [shape=oval, fillcolor="#DDDDDD", style=filled];
Start -> Check;
Check -> Process [label="yes"];
Check -> Error [label="no"];
Process -> End;
}
O que este exemplo faz: parte de um estado inicial (Start), passa pela validação (Check) e se divide em dois caminhos: sucesso (Process) ou erro (Error). Usa as cores para deixar claro de imediato o que é positivo e o que é negativo.
Grafos de dependências: entendendo o software como sistema
Quando você trabalha em um projeto existente, uma das primeiras perguntas que se faz é: “O que depende do quê?” Se precisa refatorar um módulo, quer saber quem o usa. Se precisa atualizar uma biblioteca, quer entender o impacto em cascata. Se está projetando uma funcionalidade nova, quer ver onde ela se encaixa na arquitetura existente.
O grafo de dependências é o mapa do seu sistema. Ele mostra módulos, serviços, classes ou microsserviços como nós e as dependências como setas. É essencial para:
Refatoração segura: antes de mexer em um módulo, veja quem o chama. Análise de impacto: se você modifica uma API, enxerga na hora todos os consumidores. Documentação automática: gere o grafo a partir do código (com ferramentas como Doxygen, Madge ou scripts próprios) e mantenha-o atualizado. Mapeamento da dependency injection: visualize como Spring, Angular ou .NET injetam as dependências.
Atributos úteis:
Use rankdir=LR (da esquerda para a direita) para ter um fluxo horizontal, típico das cadeias de dependências. Use shape=box para módulos/serviços. Use color e penwidth para destacar dependências críticas ou problemáticas (por exemplo, dependências circulares em vermelho). Use style=dashed para dependências opcionais ou fracas.
Exemplo:
digraph Deps {
graph [rankdir=LR];
node [shape=box, style=filled, fillcolor="#F7FAFF", fontname="Segoe UI"];
edge [color="#555555"];
UI -> API;
API -> Auth;
API -> UserService;
UserService -> Database [color="#FF5555", penwidth=2, label="critical"];
}
O que este exemplo faz: mostra uma arquitetura web clássica: a UI chama a API, a API depende de Auth e de UserService, o UserService conversa com o Database. A dependência crítica (UserService → Database) está destacada em vermelho com linha grossa: se o banco cair, tudo desaba.
Arquitetura de software: clusters e camadas
Quando você projeta uma arquitetura ou documenta a que já existe, precisa mostrar agrupamentos lógicos e a separação em camadas. Um sistema web típico tem Presentation, Business, Data. Um projeto de microsserviços tem fronteiras lógicas (edge, serviços, datastores). Um sistema legado pode ter módulos separados por domínio.
O diagrama de arquitetura com clusters permite:
Visualizar camadas separadas: Presentation Layer, Business Layer, Data Layer. Cada camada é uma caixa colorida que contém os seus componentes. Mostrar as fronteiras dos microsserviços: Edge Gateway, Services, Datastores. Cada fronteira é um cluster. Documentar módulos legados: isole os módulos por responsabilidade (Auth, Orders, Reporting) para ficar claro quem faz o quê. Apresentar a arquitetura aos stakeholders: um diagrama em camadas é universal e compreensível até por quem não é técnico.
Atributos úteis:
Use subgraph cluster_* para criar agrupamentos visuais. Use compound=true para permitir arestas que atravessam clusters. Use splines=ortho para linhas ortogonais, típicas dos diagramas “de arquiteto”. Use shape=cylinder para bancos de dados, para que sejam reconhecidos na hora.
Exemplo de arquitetura em camadas:
digraph Architecture {
graph [
rankdir=TB,
ranksep=0.8,
nodesep=0.6,
overlap=false,
splines=true,
sep="+0.2"
];
node [shape=box, style="rounded,filled", fillcolor="#F0F4FF", fontname="Segoe UI"];
subgraph cluster_presentation {
label="Presentation Layer";
style=filled;
color=lightgrey;
fillcolor="#E8F4F8";
UI;
}
subgraph cluster_business {
label="Business Layer";
style=filled;
color=lightgrey;
fillcolor="#FFF4E6";
ServiceA; ServiceB;
}
subgraph cluster_data {
label="Data Layer";
style=filled;
color=lightgrey;
fillcolor="#F0F0F0";
DB [shape=cylinder, fillcolor="#D0E8FF"];
}
UI -> ServiceA;
UI -> ServiceB;
ServiceA -> DB;
ServiceB -> DB;
}
O que este exemplo faz: define três camadas com subgraph cluster_*. Presentation contém a UI, Business contém dois serviços, Data contém o DB (com shape=cylinder). As setas mostram o fluxo: UI → Services → DB. A arquitetura se entende de imediato.
Mapa de microsserviços: entendendo um ecossistema distribuído
Se você trabalha com microsserviços, tem dezenas de serviços conversando entre si: API Gateway, serviços de domínio (Orders, Users, Notifications), bancos de dados, filas, caches. Quando acontece um incidente em produção, a primeira pergunta é: “Quem fala com quem? Onde está o gargalo?”
O mapa de microsserviços é o seu GPS no caos distribuído. Você precisa dele para:
Design arquitetural: antes de escrever código, desenhe o mapa. Identifique as fronteiras lógicas (edge, serviços core, datastores). Documentação das APIs: mostre quem chama qual serviço e por qual protocolo (REST, gRPC, eventos). Análise de performance: durante um incidente, você olha o mapa e entende na hora se o problema está no API Gateway, em um serviço específico ou no banco compartilhado. Post-mortem: depois de um downtime, o mapa ajuda a reconstruir a cadeia da falha.
Atributos úteis:
Use cluster para separar as fronteiras lógicas (Edge, Services, Data). Use shape=cylinder para bancos de dados, shape=box para serviços. Use labels nas arestas para indicar o protocolo (HTTP, gRPC, Kafka). Use shape=plaintext com tabela HTML para serviços complexos com várias portas.
Exemplo:
digraph Micro {
// Configurações globais (valem para todos)
graph [rankdir=LR, splines=true, nodesep=1.2, ranksep=1.8, overlap=false, sep="+0.4", fontname="Segoe UI"];
node [shape=box, style="rounded,filled", fillcolor="#E3F2FD", fontname="Segoe UI", fontsize=11];
edge [color="#555555", arrowsize=0.8, fontsize=10, fontcolor="#333333", fontname="Segoe UI"];
subgraph cluster_gateway {
label="Edge Layer";
fillcolor="#FFF3E0";
color="#FF9800";
Gateway [label="API Gateway", fillcolor="#FFE0B2"];
}
subgraph cluster_services {
label="Microservices Layer";
fillcolor="#E8F5E9";
color="#4CAF50";
OrderService [label="Order Service", fillcolor="#C8E6C9"];
UserService [label="User Service", fillcolor="#C8E6C9"];
NotificationService [label="Notification Service", fillcolor="#C8E6C9"];
}
subgraph cluster_data {
label="Data Layer";
fillcolor="#F5F5F5";
color="#9E9E9E";
DB [shape=cylinder, label="Postgres\nDB", fillcolor="#BBDEFB"];
Cache [shape=cylinder, label="Redis\nCache", fillcolor="#FFCCBC"];
}
// Edge para Services
Gateway -> UserService [label="HTTP"];
Gateway -> OrderService [label="HTTP"];
// Service para Data
OrderService -> DB [label="SQL"];
UserService -> Cache [label="GET/SET"];
// Service para Service
NotificationService -> UserService [label="gRPC"];
OrderService -> NotificationService [label="Event", style=dashed];
}
O que este exemplo faz: organiza um ecossistema de microsserviços em três camadas coloridas:
- Edge Layer (laranja): o API Gateway como ponto de entrada
- Microservices Layer (verde): três serviços com responsabilidades claras
- Data Layer (cinza): banco Postgres e cache Redis (cilindros para diferenciar visualmente)
Padrões de comunicação mostrados:
- Gateway → Services: chamadas HTTP (setas sólidas)
- Services → Data: queries SQL e operações de cache
- Serviço para serviço: chamada síncrona gRPC e evento assíncrono (seta tracejada)
Os clusters coloridos mostram na hora as fronteiras arquiteturais, e as setas com label deixam os protocolos explícitos. Perfeito para onboarding, revisões de arquitetura ou análise de incidentes.
Diagramas de estados: modelando comportamentos
Muitos sistemas têm comportamento baseado em estados: uma requisição HTTP pode estar Idle, Loading, Success, Error. Um pedido de e-commerce passa de Draft → Pending → Confirmed → Shipped. Um sistema embarcado tem estados de power-on, standby, operação e erro. Uma interface de usuário tem estados de carregamento, pronto e erro.
O diagrama de estados modela esses comportamentos como um grafo: cada nó é um estado, cada aresta é uma transição com o label do evento que a provoca. É essencial para:
Projetar máquinas de estados: antes de implementar o state pattern no código, desenhe o diagrama. Documentar protocolos: protocolos de rede (TCP, WebSocket, próprios) têm máquinas de estados precisas. O diagrama as torna explícitas. Modelar o fluxo de UI/UX: ao projetar um app, desenhe os estados da interface: loading, ready, error, empty. Depurar sistemas embarcados: se um dispositivo trava em um estado, o diagrama ajuda a entender quais transições estão faltando.
Ligação com a teoria da Ciência da Computação e com os design patterns:
Os diagramas de estados em DOT representam diretamente conceitos fundamentais da Ciência da Computação e do design de software:
FSM (Finite State Machine): um modelo computacional com um número finito de estados. O diagrama mostra todos os estados possíveis e as transições entre eles. Usado em compiladores, parsers, implementações de protocolos.
DFA (Deterministic Finite Automaton): um tipo específico de FSM em que cada estado tem exatamente uma transição para cada símbolo de entrada. Os diagramas de estados são a representação visual dos DFAs usados na teoria das linguagens formais e nos engines de expressões regulares.
State Pattern (design pattern GoF): um design pattern orientado a objetos que permite a um objeto mudar de comportamento quando o seu estado interno muda. O diagrama de estados vira a planta para implementar o pattern: cada círculo é uma classe que implementa a interface State, cada seta é um método de transição de estado.
Quando você desenha um diagrama de estados, não está só fazendo documentação: está criando uma especificação formal que pode ser traduzida direto em código (State Pattern), usada para validação (DFA) ou analisada para verificar a correção (teoria das FSM).
Atributos úteis:
Use shape=circle para os estados (convenção padrão das FSM). Use rankdir=LR para um layout horizontal, típico dos diagramas de estados. Use label nas arestas para mostrar o evento que provoca a transição. Use shape=doublecircle para os estados finais/terminais. Use fixedsize=true com width para garantir círculos do mesmo tamanho e manter a coerência visual.
Representando estados iniciais e finais (padrão FSM/DFA):
Segundo as convenções das máquinas de estados finitos e dos DFA:
- Estado inicial: use
shape=pointcomwidthpequeno (por exemplo 0.2) para criar um ponto preto que representa o ponto de entrada - Estado final/de aceitação: use
shape=doublecirclepara criar uma borda de círculo duplo que indica os estados terminais/de aceitação - Estados comuns: use
shape=circlecomfixedsize=trueem todos os estados intermediários (garante uma aparência uniforme)
Exemplo completo com a notação FSM correta:
digraph States {
graph [rankdir=LR, fontname="Segoe UI"];
node [shape=circle, fontsize=12, fixedsize=true, width=0.9, fontname="Segoe UI"];
edge [fontname="Segoe UI"];
// Estado inicial (ponto preto)
START [shape=point, width=0.2, fixedsize=true];
// Estado final (círculo duplo)
END [shape=doublecircle, fixedsize=true, width=0.9];
// Estados comuns
Idle; Loading; Ready; Error;
// Transições
START -> Idle;
Idle -> Loading [label="start"];
Loading -> Ready [label="success"];
Loading -> Error [label="fail"];
Error -> Idle [label="reset"];
Ready -> END [label="finish"];
}
O que este exemplo faz: modela o ciclo de vida de uma requisição assíncrona seguindo as convenções FSM/DFA:
- START (
shape=point): ponto preto que indica o ponto de entrada da máquina de estados - END (
shape=doublecircle): círculo duplo que indica o estado de aceitação/terminal - Estados comuns (Idle, Loading, Ready, Error): círculos uniformes (
fixedsize=true, width=0.9) que representam os estados intermediários - Transições com label: setas que mostram os eventos que disparam as mudanças de estado
A máquina começa em START, entra em Idle e depois passa para Loading. De Loading pode dar certo (→ Ready) ou falhar (→ Error). Os erros podem ser resetados, voltando para Idle. O sucesso leva ao estado final END.
Do diagrama ao código (implementação do State Pattern):
Este diagrama pode ser traduzido direto no State Pattern:
// Cada círculo vira uma classe State
interface State {
void start();
void success();
void fail();
void reset();
void finish();
}
class IdleState implements State { ... }
class LoadingState implements State { ... }
class ReadyState implements State { ... }
class ErrorState implements State { ... }
// As transições viram implementações de métodos
class LoadingState implements State {
void success() {
context.setState(new ReadyState());
}
void fail() {
context.setState(new ErrorState());
}
}
O diagrama serve ao mesmo tempo como documentação e como especificação para a implementação.
Diagramas de classes com record
Quando você projeta um sistema orientado a objetos, ou quer documentar o domínio de uma aplicação, o diagrama de classes é o padrão. Ele mostra as classes com atributos e métodos e as relações entre elas (herança, composição, dependência).
DOT não é UML, mas com shape=record você consegue algo muito parecido e perfeitamente legível. É útil para:
Design inicial: antes de escrever código, desenhe as principais classes do domínio. Identifique atributos, métodos, relações. Refatoração: quando precisa reestruturar um módulo, desenhe o estado atual e o desejado. Compare os dois diagramas. Domain-Driven Design (DDD): modele entidades, value objects, aggregates. O diagrama ajuda a visualizar as fronteiras do domínio. Documentação: gere o diagrama automaticamente a partir do código (com ferramentas como o Doxygen) e mantenha-o atualizado.
Atributos úteis:
Use shape=record para criar caixas com seções separadas (nome da classe | atributos | métodos). Use fontname="Segoe UI" ou uma fonte monoespaçada para parecer código. Use arrowhead=onormal para a herança (seta vazada, padrão UML). Use \l (barra invertida + l) para alinhar o texto à esquerda dentro dos records.
Exemplo:
digraph Classes {
node [shape=record, fontname="Segoe UI"];
Person [label="{Person|name: string\l age: int\l|greet()}"];
Employee [label="{Employee|id: int\l role: string\l|work()}"];
Person -> Employee [arrowhead="onormal"];
}
O que este exemplo faz: define duas classes: Person (com os atributos name, age e o método greet) e Employee (com id, role e o método work). Person é a superclasse de Employee (seta com arrowhead=onormal, o padrão UML para herança). O \l alinha o texto à esquerda dentro dos records.
Diagramas ER profissionais com HTML-label
Se você trabalha com bancos de dados, mais cedo ou mais tarde precisa desenhar o esquema das tabelas: primary keys, foreign keys, relações 1:N ou N:N. O diagrama Entidade-Relacionamento (ER) é o padrão para isso.
O DOT aceita tabelas HTML dentro dos nós com shape=plaintext, o que permite criar diagramas ER limpos e profissionais. É essencial para:
Design de banco de dados: antes de escrever as migrations, desenhe o esquema. Identifique entidades, atributos, relacionamentos. Valide o design com o time. Modelagem de dados: ao projetar um módulo novo, comece pelo modelo de dados. O diagrama ER ajuda a raciocinar sobre normalização e performance. Engenharia reversa: quando você herda um banco legado sem documentação, gere o diagrama ER a partir do próprio banco (com ferramentas como SchemaSpy ou pg_dump + script) para entender a estrutura. Documentação: o diagrama ER é compreensível até por quem não é desenvolvedor (product managers, analistas de negócio).
Atributos úteis:
Use shape=plaintext para habilitar o label HTML. Use a <TABLE> HTML para criar caixas estruturadas com cabeçalho (nome da tabela) e linhas (campos). Use arrowhead=crow para relações 1:N (padrão dos diagramas ER). Use label="1:N" nas arestas para deixar a cardinalidade explícita.
Exemplo:
digraph ER {
node [shape=plaintext];
User [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD><B>User</B></TD></TR>
<TR><TD>id PK</TD></TR>
<TR><TD>email</TD></TR>
</TABLE>
>];
Order [label=<
<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0">
<TR><TD><B>Order</B></TD></TR>
<TR><TD>id PK</TD></TR>
<TR><TD>user_id FK</TD></TR>
</TABLE>
>];
User -> Order [label="1:N", arrowhead="crow"];
}
O que este exemplo faz: define duas tabelas (User e Order) usando HTML. Cada tabela tem um cabeçalho em negrito e uma linha para cada campo. A seta com arrowhead=crow e label="1:N" mostra a relação: um User tem muitos Orders (foreign key user_id em Order).
Diagramas de pipeline de CI/CD
Se você trabalha em um time que faz integração e deploy contínuos, tem um pipeline que executa etapas automáticas: build, testes, análise estática, empacotamento, deploy, monitoramento. Quando algo quebra, ou quando chega um desenvolvedor novo, você precisa de um diagrama que mostre o pipeline inteiro.
O diagrama de CI/CD visualiza o fluxo automático do commit até o deploy. É útil para:
DevOps e SRE: documentar o pipeline existente. Identificar gargalos (qual etapa demora mais?). Onboarding do time: um desenvolvedor novo olha o diagrama e entende na hora o que acontece depois de um git push. Otimização: quer paralelizar algumas etapas? O diagrama mostra quais dependem de quais. Depuração: o pipeline está falhando? O diagrama ajuda a entender em qual etapa e por quê (seta tracejada para os retries).
Atributos úteis:
Use rankdir=LR para um fluxo horizontal (típico dos pipelines). Use shape=box com style=filled para as etapas, colorindo por tipo (build=azul, test=verde, deploy=vermelho). Use style=dotted com label="retry" para mostrar os mecanismos de retry automático. Use label nas arestas para indicar condições (por exemplo “só no branch master”).
Exemplo:
digraph CICD {
graph [rankdir=LR];
node [shape=box, style=filled, fillcolor="#F8FBFF"];
Code -> Build -> Test -> Package -> Deploy -> Monitor;
Test -> Build [style=dotted, label="retry"];
}
O que este exemplo faz: mostra um pipeline clássico: Code → Build → Test → Package → Deploy → Monitor. A seta tracejada de Test para Build mostra um retry automático em caso de falha nos testes. É um fluxo linear, que se entende de imediato.
Reduzindo a complexidade: mapas conceituais e análise
Nem todo diagrama precisa ser hierárquico ou direcional. Às vezes você precisa visualizar relações conceituais sem uma estrutura fixa: durante um brainstorming, quando faz design coletivo com o time ou quando quer mapear as dependências conceituais entre áreas tecnológicas.
O mapa conceitual não tem “início” nem “fim”: é uma rede de nós ligados de forma orgânica. É útil para:
Brainstorming: comece de uma ideia central e vá acrescentando nós ligados enquanto discute com o time. O mapa cresce naturalmente. Design coletivo: durante uma sessão de design, mapeie os componentes e as suas relações. Você ainda não conhece a hierarquia, mas sabe que “o Backend conversa com o Database e com a API”. Análise de dependências conceituais: você quer entender quais áreas tecnológicas estão ligadas (por exemplo Security → Logging → Observability). Documentação de alto nível: para stakeholders não técnicos, um mapa conceitual é mais acessível que um grafo hierárquico.
Atributos úteis:
Use o engine neato ou fdp em vez do dot, para ter um layout orgânico baseado em forças físicas. Use shape=ellipse para os nós conceituais (não são processos). Use style=filled com cores suaves para os agrupamentos visuais. Use grafos não direcionados (graph em vez de digraph) se as relações forem bidirecionais.
Exemplo com o engine neato:
graph Concepts {
layout=neato;
node [shape=ellipse, style=filled, fillcolor="#EFEFFF"];
Backend -- Database;
Backend -- API;
API -- Security;
Security -- Logging;
Logging -- Observability;
}
Evitando sobreposições: overlap e splines
Um dos problemas mais comuns ao desenhar grafos complexos é a sobreposição de setas, textos e nós. O Graphviz oferece atributos específicos para controlar esse comportamento e deixar os diagramas mais legíveis.
O problema: sobreposições indesejadas
Quando há muitos nós e setas, principalmente com layouts hierárquicos ou com splines=ortho, as setas podem passar por cima dos labels dos clusters ou dos nós. Veja um exemplo típico do problema:
digraph OverlapProblem {
graph [rankdir=TB, splines=ortho];
node [shape=box, style=rounded];
subgraph cluster_a {
label="Component A";
A1; A2;
}
subgraph cluster_b {
label="Component B";
B1; B2;
}
subgraph cluster_c {
label="Component C";
C1; C2;
}
A1 -> B1;
A2 -> B2;
B1 -> C1;
B2 -> C2;
A1 -> C1;
}
Problema: com splines=ortho, as setas podem cruzar os labels dos clusters e deixar o diagrama confuso.
A solução: overlap e splines
O Graphviz oferece vários atributos para resolver esse problema:
overlap: evita sobreposições entre nós
graph [overlap=false];
Opções principais:
falseouvoronoi: evita sobreposições (qualidade melhor, mais lento)scale: escala o grafo para evitar sobreposiçõesscalexy: escala com proporções diferentes em X e Ytrue(padrão): permite sobreposições
splines: controla a forma das arestas
graph [splines=true];
Opções:
trueouspline: curvas suaves que desviam dos nós (recomendado)curved: arestas levemente curvaspolyline: linhas quebradasortho: linhas ortogonais (podem causar sobreposições!)lineoufalse: linhas retas
sep: margem extra entre os elementos
graph [sep="+0.2"];
Acrescenta margem entre nós e arestas (em polegadas). O + significa “somar ao valor padrão”.
ranksep e nodesep: espaçamento entre níveis e entre nós
graph [ranksep=0.8, nodesep=0.6];
Aumenta o espaço vertical (ranksep) e horizontal (nodesep) entre os elementos.
Exemplo melhorado
Aqui está o mesmo grafo com atributos otimizados para evitar sobreposições:
digraph OverlapSolved {
graph [
rankdir=TB,
ranksep=0.8,
nodesep=0.6,
overlap=false,
splines=true,
sep="+0.2"
];
node [shape=box, style=rounded];
subgraph cluster_a {
label="Component A";
style=filled;
fillcolor="#E8F4F8";
A1; A2;
}
subgraph cluster_b {
label="Component B";
style=filled;
fillcolor="#FFF4E6";
B1; B2;
}
subgraph cluster_c {
label="Component C";
style=filled;
fillcolor="#F0F0F0";
C1; C2;
}
A1 -> B1;
A2 -> B2;
B1 -> C1;
B2 -> C2;
A1 -> C1;
}
Resultado: agora as setas desviam dos nós e dos labels, e o grafo fica mais espaçado e legível. As cores de fundo ajudam a distinguir os clusters.
Quando usar o quê
| Cenário | Atributos recomendados |
|---|---|
| Diagramas complexos com muitos nós | overlap=false, splines=true |
| Grafos hierárquicos (fluxogramas, arquiteturas) | ranksep=0.8, nodesep=0.6, splines=true |
| Grafos com clusters | overlap=false, sep="+0.2" |
| Diagramas “de arquiteto” com linhas retas | splines=polyline (evite ortho) |
| Grafos pequenos e simples | padrão (não precisa mexer) |
Regra prática: comece sempre com overlap=false e splines=true se tiver mais de 10 nós ou usar clusters.
Exemplo completo com todas as boas práticas
Aqui está um exemplo real que combina todos os atributos recomendados: arquitetura de microsserviços com 4 camadas, muitos nós e arestas, clusters coloridos, espaçamento otimizado:
digraph CompleteExample {
graph [
rankdir=TB,
ranksep=1.0,
nodesep=0.7,
overlap=false,
splines=true,
sep="+0.25"
];
node [shape=box, style="rounded,filled", fillcolor="#F0F4FF", fontname="Segoe UI", fontsize=11];
edge [color="#555555", arrowsize=0.8];
subgraph cluster_frontend {
label="Frontend Layer";
style=filled;
fillcolor="#E8F4F8";
color="#5A9FD4";
WebUI [label="Web UI"];
MobileApp [label="Mobile App"];
}
subgraph cluster_api {
label="API Gateway Layer";
style=filled;
fillcolor="#FFF4E6";
color="#E8A87C";
Gateway [label="API Gateway"];
LoadBalancer [label="Load Balancer"];
}
subgraph cluster_services {
label="Microservices Layer";
style=filled;
fillcolor="#F0F8E8";
color="#90C290";
AuthService [label="Auth Service"];
UserService [label="User Service"];
OrderService [label="Order Service"];
PaymentService [label="Payment Service"];
}
subgraph cluster_data {
label="Data Layer";
style=filled;
fillcolor="#F5F5F5";
color="#999999";
UsersDB [shape=cylinder, fillcolor="#D0E8FF", label="Users DB"];
OrdersDB [shape=cylinder, fillcolor="#D0E8FF", label="Orders DB"];
Cache [shape=box, fillcolor="#FFE8D0", label="Redis Cache"];
}
// Frontend para Gateway
WebUI -> LoadBalancer [label="HTTPS"];
MobileApp -> LoadBalancer [label="HTTPS"];
// Gateway para Services
LoadBalancer -> Gateway;
Gateway -> AuthService [label="gRPC"];
Gateway -> UserService [label="REST"];
Gateway -> OrderService [label="REST"];
// Dependências entre serviços
OrderService -> PaymentService [label="API call"];
UserService -> AuthService [label="validate"];
PaymentService -> AuthService [label="validate"];
// Acesso a dados
AuthService -> UsersDB;
UserService -> UsersDB;
UserService -> Cache [style=dashed, label="cache"];
OrderService -> OrdersDB;
OrderService -> Cache [style=dashed, label="cache"];
}
Linha de comando:
dot -Tsvg overlap_complete.dot -o overlap_complete.svg
O que este exemplo demonstra:
- overlap=false: nenhuma sobreposição entre nós, mesmo com 13 nós e 4 clusters
- splines=true: setas curvas que desviam com elegância dos nós e dos labels
- sep="+0.25": margem extra que mantém tudo legível
- ranksep=1.0, nodesep=0.7: espaçamento generoso entre camadas e entre nós
- Clusters coloridos: cada camada tem uma cor própria, para identificação imediata
- Labels nas arestas: protocolos (HTTPS, gRPC, REST) e tipo de conexão explícitos
- Estilo tracejado para o cache: as dependências opcionais aparecem de forma diferente
- Forma de cilindro para o DB: os bancos de dados são reconhecidos na hora
Este é o template perfeito para documentar arquiteturas complexas de forma profissional e legível.
Color Schemes: paletas profissionais prontas para usar
O Graphviz inclui color schemes predefinidos, baseados nas paletas profissionais do ColorBrewer. Em vez de escolher as cores na mão, você pode usar paletas testadas para legibilidade, acessibilidade e aspecto profissional.
Como os color schemes funcionam
Use o atributo colorscheme para escolher uma paleta e depois use os números de 1 a 9 (ou mais, depende do esquema) em vez dos códigos hex:
node [colorscheme=set39, fillcolor=1, color=2];
Os color schemes são organizados em categorias:
- Qualitativos (set1, set2, set3, pastel1, pastel2, dark2, paired, accent): para categorias distintas
- Sequenciais (blues3-9, greens3-9, reds3-9, purples3-9, oranges3-9): para valores progressivos
- Divergentes (rdylgn3-11, spectral3-11, rdbu3-11): para dados com um ponto central
Referência completa: graphviz.org/docs/attrs/colorscheme/
Exemplos práticos com color schemes profissionais
Cada exemplo usa o mesmo diagrama (um processo de 5 etapas), mas com paletas diferentes. Compare e escolha a que mais combina com o seu caso de uso.
Exemplo 1: Set39 (qualitativo, vibrante)
Ótimo para distinguir categorias diferentes, apresentações coloridas, dashboards.
digraph ProcessSet39 {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=set39, fontname=Arial];
edge [colorscheme=set39, penwidth=2];
Start [fillcolor=1, label="Start"];
Validate [fillcolor=2, label="Validate"];
Process [fillcolor=3, label="Process"];
Store [fillcolor=4, label="Store"];
Notify [fillcolor=5, label="Notify"];
Start -> Validate [color=1];
Validate -> Process [color=2];
Process -> Store [color=3];
Store -> Notify [color=4];
}
Linha de comando:
dot -Tsvg colorscheme_set39.dot -o colorscheme_set39.svg
Exemplo 2: Pastel19 (qualitativo, suave)
Cores pastel para documentação técnica, wikis, posts de blog. Chamam menos atenção, mas cansam menos a vista na leitura longa.
digraph ProcessPastel {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=pastel19, fontname=Arial, fontcolor="#333333"];
edge [colorscheme=dark28, penwidth=2];
Start [fillcolor=1, label="Start"];
Validate [fillcolor=3, label="Validate"];
Process [fillcolor=5, label="Process"];
Store [fillcolor=7, label="Store"];
Notify [fillcolor=9, label="Notify"];
Start -> Validate [color=1];
Validate -> Process [color=3];
Process -> Store [color=5];
Store -> Notify [color=7];
}
Linha de comando:
dot -Tsvg colorscheme_pastel.dot -o colorscheme_pastel.svg
Exemplo 3: Blues9 (sequencial, progressão)
Ideal para mostrar intensidade crescente, prioridades, fases de maturidade.
digraph ProcessBlues {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=blues9, fontname=Arial];
edge [color="#2171B5", penwidth=2];
Start [fillcolor=2, fontcolor=black, label="Start"];
Validate [fillcolor=4, fontcolor=white, label="Validate"];
Process [fillcolor=6, fontcolor=white, label="Process"];
Store [fillcolor=8, fontcolor=white, label="Store"];
Notify [fillcolor=9, fontcolor=white, label="Notify"];
Start -> Validate -> Process -> Store -> Notify;
}
Linha de comando:
dot -Tsvg colorscheme_blues.dot -o colorscheme_blues.svg
Exemplo 4: RdYlGn9 (divergente, semáforo)
Perfeito para estados de sucesso/aviso/erro, health checks, monitoramento.
digraph ProcessStatus {
graph [rankdir=LR, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=rdylgn9, fontname=Arial, fontcolor=black];
edge [penwidth=2, color="#666666"];
Idle [fillcolor=5, label="Idle\n(neutral)"];
Starting [fillcolor=7, label="Starting\n(ok)"];
Running [fillcolor=9, label="Running\n(good)"];
Warning [fillcolor=4, label="Warning"];
Error [fillcolor=1, label="Error"];
Idle -> Starting -> Running;
Running -> Warning [style=dashed];
Warning -> Error [style=dashed];
Running -> Idle [label="stop"];
}
Linha de comando:
dot -Tsvg colorscheme_rdylgn.dot -o colorscheme_rdylgn.svg
Exemplo 5: Paired12 (qualitativo, pares)
Usa pares de cores coordenadas. Ótimo para comparações, versões A/B, relações.
digraph ProcessPaired {
graph [rankdir=TB, bgcolor=white];
node [shape=box, style="rounded,filled", colorscheme=paired12, fontname=Arial];
edge [colorscheme=paired12, penwidth=2];
subgraph cluster_v1 {
label="Version 1.x";
style=filled;
fillcolor="#F0F0F0";
V1_Start [fillcolor=1, label="Start v1"];
V1_Process [fillcolor=1, label="Process v1"];
V1_End [fillcolor=1, label="End v1"];
V1_Start -> V1_Process -> V1_End;
}
subgraph cluster_v2 {
label="Version 2.x";
style=filled;
fillcolor="#F8F8F8";
V2_Start [fillcolor=2, label="Start v2"];
V2_Process [fillcolor=2, label="Process v2"];
V2_End [fillcolor=2, label="End v2"];
V2_Start -> V2_Process -> V2_End;
}
V1_Start -> V2_Start [label="upgrade", color=4, style=dashed];
}
Linha de comando:
dot -Tsvg colorscheme_paired.dot -o colorscheme_paired.svg
Exemplo 6: Accent8 (qualitativo, contrastes fortes)
Contraste máximo entre os elementos. Para destacar diferenças importantes.
digraph ProcessAccent {
graph [rankdir=LR, bgcolor="#F5F5F5"];
node [shape=box, style="rounded,filled", colorscheme=accent8, fontname=Arial, fontcolor=black];
edge [colorscheme=accent8, penwidth=2];
Input [fillcolor=1, label="Input"];
Parse [fillcolor=2, label="Parse"];
Transform [fillcolor=3, label="Transform"];
Validate [fillcolor=4, label="Validate"];
Output [fillcolor=5, label="Output"];
Input -> Parse [color=1];
Parse -> Transform [color=2];
Transform -> Validate [color=3];
Validate -> Output [color=4];
Validate -> Parse [color=6, label="retry", style=dashed];
}
Linha de comando:
dot -Tsvg colorscheme_accent.dot -o colorscheme_accent.svg
Quando usar cada color scheme
| Cenário | Color scheme recomendado |
|---|---|
| Categorias diferentes, apresentações | set39, set28, dark28 |
| Documentação técnica, wikis | pastel19, pastel28 |
| Progressão, prioridades, níveis | blues9, greens9, purples9, oranges9 |
| Estados (ok/warning/error) | rdylgn9, rdylbu9, spectral9 |
| Comparações, versões A/B | paired12, paired11 |
| Contraste máximo | accent8, set39 |
| Acessibilidade (daltonismo) | set2, dark2 (seguros segundo o ColorBrewer) |
Combinando color schemes
Você pode usar esquemas diferentes para nós e arestas:
node [colorscheme=pastel19, fillcolor=3];
edge [colorscheme=dark28, color=2];
Dica: teste sempre as cores no ColorBrewer para verificar acessibilidade e qualidade de impressão.
Técnicas avançadas: portas, ranks, compound edges
Portas nos records: ligue as arestas a campos específicos de um record com a sintaxe node:port:
ClassA:field1 -> ClassB:field2;
Forçar nós no mesmo nível: use rank=same para posicionar vários nós na mesma linha horizontal:
{ rank=same; A; B; C; }
Compound edges entre clusters: ligue clusters inteiros em vez de nós individuais com lhead e ltail:
edge [lhead=cluster_B, ltail=cluster_A];
Arestas ortogonais: crie arestas com ângulos retos para um estilo “de arquiteto”:
graph [splines=ortho];
Estilo profissional: dicas práticas
- Use paletas coerentes.
- Evite gradientes chamativos demais.
- Use
Inter,ArialouRobotopela legibilidade. - Use
orthopara arestas “de arquiteto”. - Mantenha margens adequadas (
nodesep,ranksep). - Prefira SVG para ter qualidade em blogs.
- Mantenha os arquivos DOT versionados.
Estilos gráficos prontos para usar
Aqui estão 5 variações de estilo para o mesmo diagrama de estados, prontas para copiar e adaptar aos seus diagramas. Cada estilo define cores, fontes, tamanhos e formas para criar um visual coerente.
Estilo 1: Corporate Blue (profissional, formal)
Paleta azul/cinza, fonte Arial, estilo limpo para apresentações corporativas.
digraph CorporateBlue {
graph [
rankdir=LR,
bgcolor="#F8F9FA",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#E3F2FD",
color="#1976D2",
fontname="Segoe UI",
fontsize=11,
fontcolor="#1565C0",
penwidth=2
];
edge [
color="#1976D2",
fontname="Segoe UI",
fontsize=10,
fontcolor="#424242"
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Linha de comando:
dot -Tsvg style_corporate.dot -o style_corporate.svg
Estilo 2: Dark Mode (moderno, tech)
Fundo escuro, texto claro, paleta verde/ciano para UIs modernas e ferramentas para desenvolvedores.
digraph DarkMode {
graph [
rankdir=LR,
bgcolor="#1E1E1E",
fontname="Consolas",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#2D2D30",
color="#00D9FF",
fontname="Consolas",
fontsize=11,
fontcolor="#E0E0E0",
penwidth=2
];
edge [
color="#00D9FF",
fontname="Consolas",
fontsize=10,
fontcolor="#B0B0B0"
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Linha de comando:
dot -Tsvg style_dark.dot -o style_dark.svg
Estilo 3: Warm Minimal (suave, legível)
Paleta quente laranja/bege, sans-serif, ótima para documentação técnica.
digraph WarmMinimal {
graph [
rankdir=LR,
bgcolor="#FFFBF5",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#FFE8CC",
color="#FF8C42",
fontname="Segoe UI",
fontsize=11,
fontcolor="#6B4423",
penwidth=1.5
];
edge [
color="#FF8C42",
fontname="Segoe UI",
fontsize=10,
fontcolor="#8B5A3C",
penwidth=1.5
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Linha de comando:
dot -Tsvg style_warm.dot -o style_warm.svg
Estilo 4: Monochrome (elegante, imprimível)
Preto e branco, tons de cinza, perfeito para impressão e documentação formal.
digraph Monochrome {
graph [
rankdir=LR,
bgcolor="white",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#F5F5F5",
color="#333333",
fontname="Segoe UI",
fontsize=11,
fontcolor="#000000",
penwidth=2
];
edge [
color="#333333",
fontname="Segoe UI",
fontsize=10,
fontcolor="#666666",
penwidth=1.5
];
Idle [label="Idle"];
Processing [label="Processing"];
Complete [label="Complete"];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Linha de comando:
dot -Tsvg style_mono.dot -o style_mono.svg
Estilo 5: Vibrant Gradient (criativo, marcante)
Cores vibrantes com gradientes, ótimo para apresentações e slides que precisam chamar a atenção.
digraph VibrantGradient {
graph [
rankdir=LR,
bgcolor="#FAFAFA",
fontname="Segoe UI",
fontsize=12
];
node [
shape=box,
style="rounded,filled",
fillcolor="#A8E6CF:#56CCF2",
gradientangle=90,
color="#2D6A9F",
fontname="Segoe UI",
fontsize=11,
fontcolor="#1A3A52",
penwidth=2.5
];
edge [
color="#9B59B6",
fontname="Segoe UI",
fontsize=10,
fontcolor="#5B3A72",
penwidth=2
];
Idle [label="Idle"];
Processing [label="Processing", fillcolor="#FFD93D:#FF6B9D", gradientangle=90];
Complete [label="Complete", fillcolor="#6BCF7F:#4ECDC4", gradientangle=90];
Idle -> Processing [label="start"];
Processing -> Complete [label="finish"];
Complete -> Idle [label="reset"];
Processing -> Idle [label="cancel"];
}
Linha de comando:
dot -Tsvg style_vibrant.dot -o style_vibrant.svg
Como usar estes estilos
Copie o bloco graph, node, edge do estilo que preferir e aplique aos seus diagramas. Depois você pode personalizar:
- Cores: troque os códigos hex pela sua paleta
- Fontes: use
fontname="FontName"(Arial, Helvetica, Courier, Times, Verdana, Consolas) - Tamanhos:
fontsizepara o texto,penwidthpara a espessura das bordas e das setas - Forma:
box,ellipse,circle,diamond,cylinder,record - Gradientes: use
fillcolor="color1:color2"comgradientangle(só em alguns formatos de saída)
Observações sobre a compatibilidade das fontes
As fontes precisam estar instaladas no sistema em que você gera as imagens:
- Fontes universais (funcionam em qualquer lugar):
Arial,Helvetica,Times,Times-Roman,Courier - Fontes modernas (confira a disponibilidade):
Verdana,Consolas,Roboto,Inter - Windows: a maioria das fontes já vem instalada
- macOS: ótimo suporte às fontes padrão
- Linux: instale
fonts-liberationoufonts-dejavupara ter equivalentes de Arial/Helvetica - CI/CD: use fontes básicas ou inclua as fontes no container Docker
Se uma fonte não estiver disponível, o Graphviz usa um fallback (normalmente Times). Para não ter surpresas, use sempre fontes básicas ou teste a geração no ambiente de produção.
Workflow: como integrar o Graphviz no trabalho real
Coloque os arquivos
.gvno repositório.Gere os SVGs automaticamente no CI:
dot -Tsvg diagram.gv -o diagram.svgInsira os SVGs na documentação (README, wiki, blog).
Atualize os diagramas a cada refatoração.
Use diff e versionamento nos arquivos DOT como faria com o código.
Troubleshooting: erros comuns e soluções
Erro: “syntax error in line X near…”
- Causa: sintaxe DOT inválida
- Solução: procure ponto e vírgula faltando, chaves não fechadas, aspas sem par
- Exemplo:
A -> Bdeve terminar com;→A -> B;
Erro: “Warning: Unable to find font…”
- Causa: a fonte indicada não está instalada no sistema
- Solução: use fontes universais (Arial, Helvetica, Times) ou instale a fonte necessária
- Confira as fontes disponíveis:
dot -vmostra as fontes disponíveis
O diagrama fica grande/pequeno demais
- Solução 1: adicione
graph [size="8,6"]para limitar as dimensões (em polegadas) - Solução 2: use
graph [ratio=compress]para compactar automaticamente - Solução 3: gere um PNG com DPI personalizado:
dot -Tpng -Gdpi=150 file.dot -o file.png
As setas passam por cima dos nós
- Solução: adicione
graph [overlap=false, splines=true](veja a seção “Evitando sobreposições”)
Os nós ficam todos alinhados na horizontal em vez de na vertical
- Solução: use
graph [rankdir=TB]para ir de cima para baixo (o padrão é LR = da esquerda para a direita)
O cluster não aparece
- Causa: o nome do cluster não começa com
cluster_ - Solução: renomeie
subgraph mygroupparasubgraph cluster_mygroup
Saída SVG grande demais (tamanho do arquivo)
- Causa: SVG com muitos elementos
- Solução 1: use PNG em vez de SVG para grafos muito complexos
- Solução 2: otimize com o
svgo:svgo input.svg -o output.svg
O grafo não é gerado (nenhuma saída, nenhum erro)
- Causa: comando incorreto ou redirecionamento errado
- Confira: use
-vpara o modo verbose:dot -v -Tsvg input.dot -o output.svg - Teste rápido:
echo "digraph{A->B}" | dot -Tsvg > test.svg
Os labels das arestas não aparecem
- Causa: labels longos demais ou fonte pequena demais
- Solução: aumente o
fontsizedas arestas ou use\npara quebrar os labels em várias linhas
Boas práticas para um código DOT limpo
Don’t Repeat Yourself (DRY)
Defina os atributos uma vez só, no nível mais alto, em vez de repeti-los em cada elemento.
❌ Ruim (repetitivo):
digraph {
node [fontname="Segoe UI"];
A [fontname="Segoe UI", shape=box];
B [fontname="Segoe UI", shape=box];
C [fontname="Segoe UI", shape=box];
}
✅ Bom (DRY):
digraph {
// Define uma vez, vale para todos
graph [fontname="Segoe UI"];
node [fontname="Segoe UI", shape=box];
edge [fontname="Segoe UI"];
A; B; C; // Herda todos os atributos
}
Princípio-chave: use as declarações graph, node e edge para definir os padrões. Sobrescreva só quando um elemento específico precisar de atributos diferentes.
Use comentários
Adicione comentários para explicar as seções complexas:
digraph {
// Estilo global
graph [rankdir=LR, fontname="Segoe UI"];
// Componentes principais
A -> B;
// Caminho de tratamento de erros
B -> Error [style=dashed, color=red];
}
Organize os grafos grandes
Agrupe as declarações relacionadas:
digraph {
// === Configuração ===
graph [rankdir=TB];
node [shape=box];
// === Serviços ===
ServiceA; ServiceB; ServiceC;
// === Bancos de dados ===
DB1 [shape=cylinder];
DB2 [shape=cylinder];
// === Conexões ===
ServiceA -> DB1;
ServiceB -> DB2;
}
Templates DOT + comandos do Graphviz (CLI)
Cada template traz:
O trecho DOT
O comando da CLI para gerar a imagem
Por coerência uso o formato SVG, mas você pode trocar -Tsvg por:
-Tpng-Tpdf-Tjpg-Tgif
E pode salvar o input DOT em template.dot ou usar um pipe.
Fluxograma
Template 1: Processo básico
digraph FlowBasic {
graph [rankdir=TB];
node [shape=rectangle, style=rounded, fontsize=12];
Start [label="Start", shape=circle];
Step1 [label="Input validation"];
Step2 [label="Process request"];
Step3 [label="Persist data"];
End [label="End", shape=doublecircle];
Start -> Step1 -> Step2 -> Step3 -> End;
}
Linha de comando:
dot -Tsvg FlowBasic.dot -o FlowBasic.svg
Template 2: Ramificação (if/else)
digraph FlowIfElse {
graph [rankdir=TB];
node [fontsize=12, style=rounded];
Start [shape=circle];
Check [shape=diamond, label="Is valid?"];
A [label="Handle valid case"];
B [label="Handle error"];
End [shape=doublecircle];
Start -> Check;
Check -> A [label="Yes"];
Check -> B [label="No"];
A -> End;
B -> End;
}
Linha de comando:
dot -Tsvg FlowIfElse.dot -o FlowIfElse.svg
Template 3: Processo com seções
digraph FlowSections {
graph [rankdir=TB];
node [fontsize=11, style=rounded];
subgraph cluster_input {
label="Input Stage";
color=lightgrey;
style=filled;
A1 [label="Receive request"];
A2 [label="Validate payload"];
A1 -> A2;
}
subgraph cluster_processing {
label="Processing Stage";
color=lightblue;
style=filled;
P1 [label="Transform data"];
P2 [label="Apply business rules"];
P1 -> P2;
}
subgraph cluster_output {
label="Output Stage";
color=lightyellow;
style=filled;
O1 [label="Persist"];
O2 [label="Return response"];
O1 -> O2;
}
A2 -> P1 -> O1;
}
Linha de comando:
dot -Tsvg FlowSections.dot -o FlowSections.svg
Máquina de estados
Template 4: Máquina de estados básica
digraph StateMachine {
graph [rankdir=LR];
node [shape=circle, fontsize=12];
Idle;
Loading;
Error;
Success;
Idle -> Loading [label="start"];
Loading -> Success [label="ok"];
Loading -> Error [label="fail"];
Error -> Idle [label="retry"];
}
Linha de comando:
dot -Tsvg StateMachine.dot -o StateMachine.svg
Template 5: Estados aninhados
digraph NestedStates {
graph [rankdir=LR];
node [fontsize=11];
subgraph cluster_ready {
label="Ready state";
style=dashed;
R1 [shape=circle, label="Idle"];
R2 [shape=circle, label="Primed"];
R1 -> R2 [label="prepare"];
}
subgraph cluster_active {
label="Active state";
style=dashed;
A1 [shape=circle, label="Running"];
A2 [shape=circle, label="Paused"];
A1 -> A2 [label="pause"];
A2 -> A1 [label="resume"];
}
R2 -> A1 [label="activate"];
}
Linha de comando:
dot -Tsvg NestedStates.dot -o NestedStates.svg
Diagrama de sequência (DOT)
Template 6: Sequência horizontal
digraph Sequence {
graph [rankdir=LR];
node [shape=box, fontsize=11];
Client -> API [label="POST /login"];
API -> AuthService [label="Check credentials"];
AuthService -> DB [label="Query user"];
DB -> AuthService [label="Result"];
AuthService -> API [label="Token"];
API -> Client [label="200 OK"];
}
Linha de comando:
dot -Tsvg Sequence.dot -o Sequence.svg
Template 7: Sequência com ativações
digraph SequenceActivation {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
User -> Frontend [label="Login"];
Frontend -> Backend [label="POST /login"];
Backend -> Backend [label="validate()"];
Backend -> DB [label="SELECT user"];
DB -> Backend [label="row found"];
Backend -> Frontend [label="JWT"];
Frontend -> User [label="Welcome"];
}
Linha de comando:
dot -Tsvg SequenceActivation.dot -o SequenceActivation.svg
Grafo de dependências
Template 8: Módulos
digraph DependencyTree {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=12];
App -> ModuleA;
App -> ModuleB;
ModuleA -> LibA;
ModuleA -> LibB;
ModuleB -> LibB;
}
Linha de comando:
dot -Tsvg DependencyTree.dot -o DependencyTree.svg
Template 9: Microsserviços
digraph MicroservicesDep {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
Gateway -> Auth;
Gateway -> Orders;
Auth -> UsersDB;
Orders -> ProductsService;
Orders -> Payments;
Payments -> BankAPI;
}
Linha de comando:
dot -Tsvg MicroservicesDep.dot -o MicroservicesDep.svg
Diagrama de arquitetura
Template 10: Em camadas
digraph Layered {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=12];
subgraph cluster_presentation {
label="Presentation Layer";
style=filled;
color=lightyellow;
UI;
API;
}
subgraph cluster_business {
label="Business Layer";
style=filled;
color=lightblue;
Services;
}
subgraph cluster_data {
label="Data Layer";
style=filled;
color=lightgrey;
DB;
Cache;
}
UI -> API -> Services -> DB;
Services -> Cache;
}
Linha de comando:
dot -Tsvg Layered.dot -o Layered.svg
Template 11: Hexagonal
digraph Hexagonal {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
AppCore [label="Core Domain"];
PortIn [label="Inbound Ports"];
PortOut [label="Outbound Ports"];
AdapterIn [label="Inbound Adapters"];
AdapterOut [label="Outbound Adapters"];
DB [label="Database"];
UI [label="Frontend/UI"];
UI -> AdapterIn -> PortIn -> AppCore;
AppCore -> PortOut -> AdapterOut -> DB;
}
Linha de comando:
dot -Tsvg Hexagonal.dot -o Hexagonal.svg
Diagramas ER
Template 12: 1:N
digraph ER_OneToMany {
graph [rankdir=LR];
node [shape=record, fontsize=11];
User [label="{User|id PK|name|email}"];
Order [label="{Order|id PK|user_id FK|total}"];
User -> Order [label="1:N"];
}
Linha de comando:
dot -Tsvg ER_OneToMany.dot -o ER_OneToMany.svg
Template 13: N:N
digraph ER_ManyToMany {
graph [rankdir=LR];
node [shape=record, fontsize=11];
Student [label="{Student|id PK|name}"];
Course [label="{Course|id PK|title}"];
Enroll [label="{Enroll|student_id FK|course_id FK}"];
Student -> Enroll;
Course -> Enroll;
}
Linha de comando:
dot -Tsvg ER_ManyToMany.dot -o ER_ManyToMany.svg
Call graph
Template 14: Básico
digraph CallGraph {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=11];
main -> init;
main -> loadConfig;
loadConfig -> readFile;
readFile -> parseJson;
}
Linha de comando:
dot -Tsvg CallGraph.dot -o CallGraph.svg
Template 15: Com categorias
digraph CategorizedCalls {
graph [rankdir=TB];
node [shape=box, style=rounded, fontsize=11];
subgraph cluster_io {
label="I/O Functions";
color=lightgrey;
readFile;
writeFile;
}
subgraph cluster_logic {
label="Business Logic";
color=lightblue;
compute;
validate;
}
main -> compute -> validate;
compute -> readFile;
validate -> writeFile;
}
Linha de comando:
dot -Tsvg CategorizedCalls.dot -o CategorizedCalls.svg
Diagrama de rede
Template 16: Básico
digraph Network {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
Client -> LoadBalancer;
LoadBalancer -> AppServer1;
LoadBalancer -> AppServer2;
AppServer1 -> DB;
AppServer2 -> DB;
}
Linha de comando:
dot -Tsvg Network.dot -o Network.svg
Template 17: Com protocolos
digraph NetworkProto {
graph [rankdir=LR];
node [shape=box, fontsize=11];
Client -> API [label="HTTPS"];
API -> Auth [label="gRPC"];
API -> Orders [label="REST"];
Orders -> DB [label="TCP"];
}
Linha de comando:
dot -Tsvg NetworkProto.dot -o NetworkProto.svg
Timeline / Roadmap
Template 18: Timeline
digraph Timeline {
graph [rankdir=LR];
node [shape=box, style=rounded, fontsize=11];
Start -> Milestone1 -> Milestone2 -> Milestone3 -> Release;
}
Linha de comando:
dot -Tsvg Timeline.dot -o Timeline.svg
Template 19: Roadmap
digraph Roadmap {
graph [rankdir=LR];
node [shape=box, fontsize=11];
subgraph cluster_backend {
label="Backend";
B1 [label="Auth module"];
B2 [label="Payments"];
}
subgraph cluster_frontend {
label="Frontend";
F1 [label="Login UI"];
F2 [label="Dashboard"];
}
B1 -> B2;
F1 -> F2;
}
Linha de comando:
dot -Tsvg Roadmap.dot -o Roadmap.svg
Mapa mental
Template 20: Mapa mental
graph MindMap {
layout=twopi;
rankdir=LR;
node [shape=box, style=rounded, fontsize=11];
Central -- Idea1;
Central -- Idea2;
Central -- Idea3;
Idea2 -- Sub1;
Idea2 -- Sub2;
}
Linha de comando:
dot -Ktwopi -Tsvg MindMap.dot -o MindMap.svg
Diagrama de componentes
Template 21: Componentes
digraph Components {
graph [rankdir=LR];
node [shape=component, fontsize=11];
UI -> API;
API -> Service;
Service -> DB;
}
Linha de comando:
dot -Tsvg Components.dot -o Components.svg
Diagrama de classes
Template 22: Classes estilo UML
digraph Classes {
graph [rankdir=TB];
node [shape=record, fontsize=11];
Person [label="{Person|name:string|age:int}"];
Student [label="{Student|grade:int}"];
Person -> Student;
}
Linha de comando:
dot -Tsvg Classes.dot -o Classes.svg
Layouts
Template 23: Horizontal
digraph Horizontal {
graph [rankdir=LR];
node [shape=box, style=rounded];
}
Linha de comando:
dot -Tsvg Horizontal.dot -o Horizontal.svg
Template 24: Vertical
digraph Vertical {
graph [rankdir=TB];
node [shape=box, style=rounded];
}
Linha de comando:
dot -Tsvg Vertical.dot -o Vertical.svg
Template 25: Circular
graph Circular {
layout=circo;
node [shape=box, style=rounded];
}
Linha de comando:
dot -Kcirco -Tsvg Circular.dot -o Circular.svg
Estilos profissionais
Template 26: Tema moderno
digraph Modern {
graph [rankdir=LR];
node [
shape=box,
style="rounded,filled",
fillcolor="#eef3f8",
color="#6a8bbf",
fontsize=11
];
edge [color="#6a8bbf"];
A -> B -> C;
}
Linha de comando:
dot -Tsvg Modern.dot -o Modern.svg
Template 27: Tema escuro
digraph Dark {
bgcolor="#1e1e1e";
node [
shape=box,
style="rounded,filled",
fillcolor="#333333",
fontcolor="white",
color="#777777",
fontsize=11
];
edge [color="#999999"];
A -> B -> C;
}
Linha de comando:
dot -Tsvg Dark.dot -o Dark.svg
Recursos úteis
Documentação oficial
- Graphviz Homepage: graphviz.org: site oficial com downloads, documentação e novidades
- DOT Language Specification: graphviz.org/doc/info/lang.html: referência completa da sintaxe DOT
- Node Shapes Gallery: graphviz.org/doc/info/shapes.html: catálogo completo de todas as formas disponíveis
- Attributes Reference: graphviz.org/doc/info/attrs.html: lista completa de todos os atributos, com descrição
- Color Names: graphviz.org/doc/info/colors.html: paletas de cores predefinidas e códigos aceitos
Ferramentas online
- GraphvizOnline: dreampuf.github.io/GraphvizOnline: editor online com preview em tempo real
- Edotor: edotor.net: editor Graphviz online com exemplos e syntax highlighting
- WebGraphviz: webgraphviz.com: gera SVG/PNG no navegador, sem instalar nada
Integrações e bibliotecas
- Graphviz Visual Editor (VSCode): extensão para preview ao vivo no Visual Studio Code
- PlantUML: plantuml.com: usa o Graphviz para renderizar UML
- Mermaid: mermaid.js.org: alternativa ao Graphviz baseada em JavaScript, para grafos em Markdown
- Python graphviz: graphviz.readthedocs.io: biblioteca Python para gerar grafos programaticamente
- Go graphviz: github.com/goccy/go-graphviz: binding Go para o Graphviz
Galeria e exemplos
- Graphviz Gallery: graphviz.org/gallery: exemplos oficiais de grafos complexos
- GitHub Awesome Graphviz: github.com/topics/graphviz: repositórios e projetos que usam o Graphviz
Comunidade e suporte
- Stack Overflow: tag graphviz: perguntas e respostas da comunidade
- Reddit r/graphviz: reddit.com/r/graphviz: discussões, exemplos e ajuda
Ferramentas complementares
- dot2tex: dot2tex.readthedocs.io: converte DOT em LaTeX/TikZ
- SVGO: github.com/svg/svgo: otimizador de SVG para reduzir o tamanho dos arquivos
- Inkscape: inkscape.org: editor vetorial para retoques manuais nos SVGs
FAQ: perguntas frequentes sobre DOT e Graphviz
Como crio um diagrama com o Graphviz?
Crie um arquivo com extensão .dot contendo a descrição do grafo e depois execute dot -Tsvg file.dot -o output.svg. O comando gera uma imagem SVG a partir do código DOT.
Qual é a diferença entre digraph e graph em DOT?
digraph cria um grafo direcionado (com setas), graph cria um grafo não direcionado (com linhas sem setas). Use -> para arestas direcionadas e -- para arestas não direcionadas.
Como mudo a direção do layout no Graphviz?
Use o atributo rankdir: TB (de cima para baixo, padrão), BT (de baixo para cima), LR (da esquerda para a direita), RL (da direita para a esquerda). Exemplo: graph [rankdir=LR];
Como crio um fluxograma com losangos de decisão em DOT?
Use shape=diamond para os nós de decisão: Decision [shape=diamond, label="Valid?"];
Como agrupo nós em uma caixa (cluster) no Graphviz?
Use subgraph cluster_name { ... }. O prefixo cluster_ é obrigatório para o agrupamento aparecer.
Como crio diagramas ER (Entidade-Relacionamento) com DOT?
Use shape=plaintext com labels HTML para criar tabelas estruturadas e arrowhead=crow para as relações 1:N.
Como evito sobreposições entre setas e nós no Graphviz?
Adicione graph [overlap=false, splines=true, sep="+0.2"]; para evitar colisões.
Qual é o melhor layout engine para o meu diagrama?
- dot: fluxogramas, pipelines, hierarquias (padrão)
- neato/fdp: grafos não direcionados, mapas conceituais
- circo: estruturas hub-and-spoke
- twopi: árvores radiais, organogramas
Como gero PNG em vez de SVG com o Graphviz?
Troque a flag -T: dot -Tpng file.dot -o output.png. Também dá para indicar o DPI: dot -Tpng -Gdpi=150.
Posso usar o Graphviz online sem instalar?
Pode! Use o edotor.net ou o GraphvizOnline para testar código DOT no navegador.
Como integro o Graphviz no meu pipeline de CI/CD?
Instale o Graphviz no ambiente de CI (por exemplo apt install graphviz no Docker) e depois adicione uma etapa que execute dot -Tsvg *.dot. Versione os arquivos .dot e gere as imagens automaticamente.
Como crio diagramas de estados (máquina de estados) com DOT?
Use shape=circle para os estados, shape=point para o estado inicial, shape=doublecircle para o estado final. Coloque nas arestas o label dos eventos: Idle -> Loading [label="start"];
Como aplico o mesmo estilo a vários nós sem repetir?
Liste os nós na mesma linha, seguidos dos atributos: A; B; C [shape=box, fillcolor=lightblue, style=filled];
O DOT aceita cores HEX?
Aceita! Use códigos HEX como fillcolor="#E3F2FD" ou nomes predefinidos como fillcolor=lightblue.
Como crio diagramas UML com o Graphviz?
Use shape=record para os diagramas de classes: Class [label="{ClassName|attribute:type|method()}"];. Para UML completo, considere o PlantUML, que usa o Graphviz por baixo dos panos.
Artigo escrito por Daniele Teti, danieleteti.it
Comments