Network diagram as code / Schemi di rete come codice

Negli ultimi anni mi sono dedicato di più alla documentazione. Scrivere un testo esplicativo su come funziona un certo sistema è relativamente semplice. Disegnare uno schema che mostri tutti gli oggetti chiave e le relazioni tra essi è anche abbastanza facile.

Ma il problema principale è mantenere questa documentazione aggiornata. E va bene il testo, ma gli schemi… Poiché tutta la documentazione è online, cioè in formato HTML, le immagini gif/jpeg/png allegate mostrano effettivamente gli schemi. Gli schemi sono disegnati in vari programmi come Visio o servizi online come draw.io. Quindi esporti lo schema in un formato grafico e lo alleghi all'HTML. È tutto piuttosto semplice.

Qual è il problema?

Gli schemi sono generalmente semplici. Più precisamente, non molto complessi. Sì, il numero di oggetti è una decina o due, il numero di relazioni è all'incirca lo stesso. In aggiunta ci sono le etichette e alcune indicazioni. Gli schemi semplici possono essere descritti anche a parole, mentre quelli troppo complessi, ehm… (c) "non saranno compresi". Ci sono molti schemi e devono essere periodicamente aggiornati, cioè costantemente, poiché seguono lo sviluppo dei nostri prodotti.

Puoi integrare HTML nel servizio. Hai provato?

Sì, certo. A me, per esempio, piacciono i grafici di gliffy.com. Ma per le modifiche bisogna andare in un servizio esterno, lì apportare le correzioni. Ed è più difficile delegare un collega per fare le modifiche.

Cosa fare?

Di recente su GitHub mi è capitato tra le raccomandazioni un repository github.com/RaoulMeyer/diagram-as-code. Diagramma come codice. Cioè, descriviamo lo schema richiesto in js. Questo js lo scriviamo direttamente nell’HTML, dove c'è anche il resto del testo della documentazione.

A proposito, non scrivo la documentazione proprio in HTML. Di solito la documentazione consiste in un insieme di file con testo markdown, che poi viene convertito in un sito di documentazione completo utilizzando un motore, come wintersmith. Oppure un sistema wiki.

Diventa molto comodo: abbiamo scritto il testo, poi si apre il tag script e in esso è descritto il codice js dello schema.

Qual è di nuovo il problema?

Questo repository mi è piaciuto, ma non è l'unico esempio in cui un diagramma viene disegnato usando codice o una rappresentazione testuale. (Alla fine dell'articolo ci saranno link a progetti e articoli che ho trovato sull'argomento diagram as code.)

E non sono l'unico a modificare la documentazione. A volte i colleghi contribuiscono anch'essi — correggono parole, modificano descrizioni, inseriscono nuove immagini. 

Pertanto, sarebbe utile vedere il diagramma in un formato testuale leggibile e comprensibile, che non richieda una lunga formazione. E in alcuni casi, sarebbe possibile fare semplicemente copia e incolla per accelerare l'aggiunta di un nuovo schema. 

Inoltre, un altro collega ha notato che il codice è certamente utile, ma se si utilizza una struttura, tutto può diventare molto rigoroso ed espressivo.

Pertanto, ho cercato di rappresentare lo schema come un insieme di piccoli array che descrivono nodi, connessioni, gruppi di nodi e la posizione dei nodi. A mio modesto avviso, è abbastanza comodo, anche se, naturalmente, de gustibus.

Com'è questo diagramma in un array?

  • Ogni nodo è descritto da un identificatore che lo definisce univocamente.
  • È possibile aggiungere un'icona al nodo e aggiungere un'etichetta.
  • Tra due nodi è possibile specificare una connessione.
  • Per la connessione nello schema è possibile specificare un colore e un'etichetta.
  • La direzione della connessione è definita come dall'origine alla destinazione. E l'origine e la destinazione sono indicate dagli identificatori dei nodi.
  • Uno o più nodi possono essere aggiunti a un gruppo.
  • La connessione può essere specificata sia dal gruppo che verso il gruppo.

Utilizzando queste semplici regole, si ottiene questo schema. Facile? Assolutamente.

Network diagram as code / Schemi di rete come codice

E viene descritto dal seguente codice js. La cosa principale qui è l'oggetto elements. In cui sono indicati nodes - nodi, edges - connessioni.
 

  const elements = {
    nodes: [       // descriviamo i nodi
      { 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: [       // indichiamo le connessioni
      { source: 'client', target: 'server', label: 'request' },
      { source: 'server', target: 'db1', label: 'request' },
      { source: 'server', target: 'db2', label: 'request' },
    ],
  };
  Diagram('scheme1', elements);

Certo, l'implementazione del diagramma non è stata una mia invenzione, ma ho utilizzato una libreria cytoscape.js — uno strumento di visualizzazione molto potente. Di cui utilizzo solo una piccola parte delle funzionalità nella mia soluzione. 

È chiaro, questo è un esempio semplice. Possiamo renderlo più complesso?

Sì, per favore. Per specificare le posizioni, utilizziamo positions, per specificare i gruppi, indichiamo un elenco di gruppi in groups, e per gli elementi stessi, l'attributo group.

Network diagram as code / Schemi di rete come codice

Ecco il codice:

<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>

Questo schema da un lato è quasi un paio di schermi di codice su un laptop, dall'altro la struttura alla json consente di riempire rapidamente tutti i dati per analogia, e si può fare copia e incolla.

E perché le positions sono state separate dai nodi?

È più comodo. Prima indichiamo i nodi. Poi possiamo specificare un paio di gruppi e indicarli nei nodi. Successivamente definiamo le connessioni. E solo dopo, quando gli oggetti principali e le connessioni tra di essi sono definiti, ci dedichiamo alla disposizione di questi oggetti nello schema. O viceversa.

Si può fare senza positions?

Si può anche senza positions. Ma sarà un po' impacciato, negli esempi puoi vedere una tale variante. Questo è dovuto al fatto che per cytoscape esiste un algoritmo di disposizione dei nodi. fcose, che tiene anche conto della presenza di gruppi. Specificare positions rende lo schema più controllabile, ma nella fase della prima bozza dello schema si può fare anche senza positions.

Inoltre, le positions possono essere specificate nello stile del gioco della battaglia navale. Cioè, un nodo è posizionato in a1, e un altro in d5. È particolarmente utile che cytoscape formi gli oggetti su canvas in modo interattivo, cioè possiamo spostarli, vedere diverse opzioni di disposizione e poi fissare nel codice la disposizione preferita degli elementi.

In generale, chiaro. Possiamo provare?
 
Certo, per creare schemi velocemente ho realizzato un piccolo editor, che aggiorna automaticamente lo schema e memorizza l'ultima versione nel browser (in localStorage).

Hai provato? Ora puoi aggiungerlo anche alla tua pagina.

Allora, ricapitolando:

1. Colleghiamo lo script

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

2. Aggiungiamo al codice 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. modifichiamo il codice secondo lo schema desiderato (penso che sia più semplice che disegnare un gufo 🙂

Ancora più dettagli su pagina del progetto su GitHub.

Qual è il risultato finale?

Ho raggiunto i miei obiettivi: rendere l'aggiunta degli schemi inline nella documentazione, il formato è abbastanza semplice e comprensibile. Non è adatto per super schemi, ma per schemi piccoli che chiariscono la struttura delle connessioni è molto buono. Si può sempre modificare rapidamente e cambiare qualcosa nel tempo. Sì, e i colleghi possono modificare direttamente nella documentazione, almeno le etichette degli oggetti senza particolari addestramenti))

Cosa si può migliorare?

Ci sono davvero molte opzioni. Aggiungere icone aggiuntive (tutte quelle disponibili sono state aggiunte inline nello script). Scegliere un set di icone più espressivo. Creare la possibilità di specificare lo stile delle linee di connessione. Aggiungere un'immagine di sfondo.

E tu cosa ne pensi?
 
Ho già alcune idee per implementazioni in issues, aggiungi anche le tue nei commenti.

La mia soluzione è sicuramente applicabile in un ambito ristretto di problemi, e forse troverai uno strumento più comodo per disegnare diagrammi, semplicemente codificandoli — come si suol dire 'mostrami il tuo diagramma come codice'.

  1. Una buona selezione
  2. Servizio eccellente (9 tipi di grafici editor online)
  3. Конечно, mermaid.js
  4. E se ti piacciono gli schemi super dettagliati e complessi — questo progetto ti stupirà sicuramente: go.drawthe.net

Fonte: habr.com

Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS 🔥 Acquista hosting affidabile per siti web con protezione DDoS, server VPS VDS - ProHoster