Diagrama de rede como código

Nos últimos dois anos, comecei a me dedicar mais à documentação. Escrever um texto explicativo sobre como funciona um determinado sistema é, de maneira geral, bastante simples. Desenhar um diagrama que mostre todos os objetos chave e as relações entre esses objetos também é relativamente fácil.

Mas o maior problema é manter essa documentação atualizada. E não é só o texto, mas os diagramas também... Como toda a documentação está online, ou seja, em formato HTML, o texto vem acompanhado de imagens gif/jpeg/png, que são, na verdade, os diagramas. E os diagramas são desenhados em diversos programas como Visio ou em serviços online como o draw.io. Então você exporta o diagrama para um formato gráfico e anexa ao HTML. Tudo simples.

Qual é o problema?

Os diagramas geralmente são simples. Mais precisamente, não são muito complexos. Sim, o número de objetos é de uma dezena a duas, e o número de conexões é mais ou menos o mesmo. Além de legendas e algumas indicações. Diagramas simples podem ser descritos em palavras, mas os muito complexos, hã... (s) 'não entenderão'. Existem muitos diagramas, e as alterações precisam ser feitas periodicamente, ou seja, constantemente, pois eles acompanham o desenvolvimento dos nossos produtos.

Pode-se inserir HTML do serviço. Você já tentou?

Sim, claro. Para mim, por exemplo, eu gosto dos gráficos do gliffy.com. Mas para fazer alterações, você precisa acessar o serviço externo e editar lá. É mais difícil delegar as correções a um colega.

O que fazer?

Recentemente, encontrei no GitHub, em minhas recomendações, um repositório github.com/RaoulMeyer/diagram-as-code. Diagrama como código. Ou seja, descrevemos em JS o diagrama que precisamos. Esse JS é escrito diretamente no mesmo HTML onde está o resto do texto da documentação.

A propósito, eu não escrevo a documentação apenas em HTML. Normalmente, a documentação é um conjunto de arquivos com texto em markdown, que depois é convertido em um site completo de documentação por algum motor, como o wintersmith. Ou um sistema wiki.

Fica muito conveniente: escrevemos o texto e, em seguida, abrimos a tag script, onde está descrito o código JS do diagrama.

O que não está certo novamente?

Esse repositório eu gostei, mas não é o único exemplo de como um diagrama é desenhado com código ou uma representação textual. (No final do artigo, haverá links para projetos e artigos que encontrei sobre o tema diagram as code.)

E eu não sou o único que edita a documentação. Às vezes, meus colegas também contribuem — corrigem uma palavra, alteram uma descrição, inserem novas imagens. 

Portanto, gostaria de ver o diagrama em um formato de texto legível e compreensível, que não exigisse muito aprendizado. E, em alguns lugares, seria até possível simplesmente fazer copy-paste para acelerar a adição de um novo esquema. 

Além disso, um colega notou que código é bom, mas se usarmos uma estrutura, tudo pode ser muito rigoroso e expressivo.

Por isso, tentei apresentar o esquema como um conjunto de vários pequenos arrays que descrevem nós, conexões, grupos de nós e a disposição dos nós. Na minha modesta opinião, ficou bastante conveniente, embora, claro, sobre gosto e cor…

Como é que um diagrama fica em um array?

  • Cada nó é descrito por um identificador que o define de forma única.
  • Também é possível adicionar um ícone ao nó, adicionar uma legenda.
  • Entre dois nós, é possível indicar uma conexão.
  • Para a conexão no esquema, é possível definir uma cor e uma legenda.
  • A direção da conexão é definida do originador para o alvo. E o originador e o alvo são indicados pelos identificadores dos nós.
  • Um ou mais nós podem ser adicionados a um grupo.
  • A conexão também pode ser indicada de um grupo para um grupo.

Usando essas regras simples, obtemos um esquema como este. Simples? Absolutamente.

Diagrama de rede como código

E é descrito pelo seguinte código js. O principal aqui é o objeto elements, que contém os nodes — nós e edges — conexões.
 

  const elements = {
    nodes: [       // descrevemos os nós
      { id: 'client', type: 'smartphone', label: 'Aplicativo Móvel'},
      { id: 'server', type: 'server', label: 'Servidor Principal'},
      { id: 'db1', type: 'database', label: 'DB 1'},
      { id: 'db2', type: 'database', label: 'DB 2'},
    ],
    edges: [       // indicamos as conexões
      { source: 'client', target: 'server', label: 'solicitação' },
      { source: 'server', target: 'db1', label: 'solicitação' },
      { source: 'server', target: 'db2', label: 'solicitação' },
    ],
  };
  Diagram('scheme1', elements);

Claro, a renderização do esquema eu não inventei, utilizei uma biblioteca cytoscape.js — uma ferramenta de visualização muito poderosa. Eu uso apenas uma fração das suas possibilidades na minha solução. 

Claro, este é um exemplo simples. Podemos complicar um pouco?

Sim, claro. Para indicar posições, usamos positions, para indicar grupos, listamos grupos em groups, e para os próprios elementos usamos o atributo group.

Diagrama de rede como código

E este é o código:

<div id="scheme5" style="height:500px;width:800px;"></div>
<script>
  const elements5 = {
    groups: [
      { id: 'g1', label: 'Группа сервисов 1'},
      { id: 'g2', label: 'Группа сервисов 2'},
    ],
    nodes: [
      { id: 'man1', type: 'person', label: 'Человек'},
      { id: 'client', type: 'smartphone', label: 'Смартфон'},
      { id: 'agent-backend', type: 'server', group: 'g1', label: 'agent-backend'},
      { id: 'web', type: 'server', group: 'g1', label: 'Приложение admin'},
      { id: 'www', type: 'server', group: 'g1', label: 'страница загрузки'},
      { id: 'mongodb1', type: 'database', group: 'g1', label: 'Mongo DB 1'},
      { id: 'mongodb2', type: 'database', group: 'g1', label: 'Mongo DB 2'},
      { id: 'runner-integration1', type: 'worker', group: 'g1', label: 'отправка'},
      { id: 'runner-integration2', type: 'worker', group: 'g1', label: 'отправка'},
      { id: 'api', type: 'server', group: 'g1', label: 'API'},
      { id: 'server2', type: 'server', group:'g2', label: 'сервер'},
      { id: 'otherServer', type: 'server', group:'g2', label: 'сервер'},
      { id: 'firebase', type: 'cloud', label: 'Google Firebase'},
    ],
    edges: [
      { source: 'client', target: 'agent-backend', label: 'json', color: 'red' },
      { source: 'agent-backend', target: 'mongodb1', color: 'red' },
      { source: 'agent-backend', target: 'mongodb2',  color: 'red' },
      { source: 'mongodb1', target: 'runner-integration1', label: 'данные' },
      { source: 'mongodb2', target: 'runner-integration2', label: 'данные' },
      { source: 'mongodb1', target: 'web', label: 'данные для отображения' },
      { source: 'runner-integration1', target: 'server2', label: 'данные' },
      { source: 'runner-integration2', target: 'otherServer', label: 'данные' },
      { source: 'api', target: 'firebase', label: 'запросы', color: 'blue', },
      { source: 'firebase', target: 'client', label: 'push', color: 'blue'},
      { source: 'server2', target: 'api', label: 'уведомления', color: 'blue'},
      { source: 'man1', target: 'client', },
    ],
    positions: [
      { id: 'client', row: 2, col: 1,},
      { id: 'agent-backend', row: 2, col: 3,},
      { id: 'web', row: 6, col: 3,},
      { id: 'www', row: 1, col: 3,},
      { id: 'mongodb1', row: 1, col: 4,},
      { id: 'mongodb2', row: 2, col: 5,},
      { id: 'runner-integration1', row: 3, col: 3,},
      { id: 'runner-integration2', row: 4, col: 3,},
      { id: 'api', row: 5, col: 3,},
      { id: 'server2', row: 6, col: 7,},
      { id: 'otherServer', row: 4, col: 7,},
      { id: 'firebase', row: 5, col: 1,},
      { id: 'logger', row: 2, col: 7,},
      { id: 'crm', row: 5, col: 8,},
    ],
};
  Diagram('scheme5', elements5, {layout: 'grid'});
</script>

Esse esquema de um lado — é quase um par de telas de código no notebook, por outro lado, a estrutura semelhante a json permite preencher todos os dados por analogia, rapidamente e pode-se fazer copy-paste.

E por que positions está separado dos nós?

É mais conveniente. Primeiro, indicamos os nodes. Depois, podemos indicar um ou dois grupos e nomeá-los nos nós. Em seguida, definimos as conexões. E só depois, quando os objetos principais e as conexões entre eles estão definidos, começamos a posicionar esses objetos no diagrama. Ou vice-versa.

E dá para fazer sem positions?

Dá para fazer sem positions. Mas isso ficará um pouco bagunçado, é possível ver um exemplo desse tipo. Isso se deve ao fato de que para o cytoscape existe um algoritmo que posiciona os nós. fcose, que também leva em conta a presença de grupos. Indicar positions torna o diagrama mais controlável, mas na fase do primeiro esboço do diagrama, podemos ir sem positions.

Também é possível indicar positions no estilo Batalha Naval. Ou seja, um nó é posicionado em a1, e o outro em d5. Ajuda especialmente que o cytoscape forma objetos no canvas de forma movível, ou seja, podemos movê-los, ver diferentes opções de posicionamento e, em seguida, fixar no código o layout que gostar.

No geral, entendi. Podemos tentar?
 
Claro, para criar diagramas rapidamente, fiz um pequeno editor, que atualiza automaticamente o diagrama e armazena a última versão no navegador (no localStorage).

Tentou? Agora dá para adicionar na sua página.

Então, mais uma vez:

1. Conectamos o script

<script src="https://unpkg.com/@antirek/network-diagram@0.1.4/dist/code-full.min.js"></script>

2. Adicionamos ao código HTML

<div id="scheme1" style="height:300px;width:800px;"></div>
<script>      
  const elements = {    
    nodes: [
      { id: 'client', type: 'smartphone', label: 'Mobile App'},
      { id: 'server', type: 'server', label: 'Main Server'},
      { id: 'db1', type: 'database', label: 'DB 1'},
      { id: 'db2', type: 'database', label: 'DB 2'},
    ],
    edges: [
      { source: 'client', target: 'server', label: 'request' },
      { source: 'server', target: 'db1', label: 'request' },
      { source: 'server', target: 'db2', label: 'request' },
    ],
  };
  Diagram('scheme1', elements);
</script>

3. ajustamos o código para o diagrama que precisamos (acho que é mais fácil do que desenhar uma coruja 🙂

Mais detalhes em página do projeto no GitHub.

Qual é o resultado?

Alcancei meus objetivos — fazer a adição de diagramas inline na documentação, o formato é suficientemente simples e compreensível. Não serve para diagramas complexos, mas para diagramas pequenos que esclarecem a estrutura das conexões — é muito útil. Sempre é possível ajustar rapidamente e mudar algo com o tempo. E, sim, os colegas podem ajustar algo na doc, pelo menos as legendas dos objetos, sem precisar de muito treinamento. ))

O que pode ser melhorado?

Claro, há várias opções. Fazer a adição de ícones adicionais (todos os existentes foram adicionados inline no script). Escolher um conjunto de ícones mais expressivo. Criar uma opção de estilo de linha para as conexões. Adicionar uma imagem de fundo.

E o que você acha?
 
Já tenho algumas ideias para implementar nos issues, sinta-se à vontade para adicionar as suas nos comentários.

A minha solução é definitivamente aplicável em um espectro limitado de tarefas, e você pode encontrar uma ferramenta mais conveniente para desenhar diagramas, simplesmente codificando-os — como dizem, 'mostre-me seu diagrama como código'

  1. Uma boa seleção
  2. Um serviço incrível (9 tipos de gráficos do editor online)
  3. Конечно, mermaid.js
  4. E se você gosta de esquemas super detalhados e complexos — você certamente ficará impressionado com este projeto: go.drawthe.net

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster