Diagrama rețelei ca și cod

În ultimii câțiva ani, am început să mă ocup mai mult de documentație. Să scrii un text explicativ despre cum funcționează un anumit sistem – în general, este destul de simplu. Să desenezi o diagramă care să ilustreze toate obiectele cheie și legăturile dintre ele, de asemenea, este destul de ușor.

Dar cea mai problematică parte este să menții această documentație actualizată. Și ar fi simplu dacă ar fi doar text, dar diagramele... Deoarece toată documentația este online, adică în format html, imaginile gif/jpeg/png sunt atașate textului, în care sunt reprezentate diagramele. Diagramele sunt create în diverse programe, cum ar fi Visio sau servicii online precum draw.io. Apoi, exporți diagrama într-un format grafic și o atașezi la html. Totul e simplu.

Care este problema?

Diagrama este de obicei simplă. Adică, nu foarte complicată. Da, numărul de obiecte este de câteva zeci, iar numărul de legături este cam tot atâta. Plus etichete, diverse indicatoare. Diagramele simple pot fi descrise și în cuvinte, iar cele prea complicate, eh... (c) „nu se vor înțelege”. Există multe diagrame, modificările trebuie făcute periodic și constant, deoarece acestea evoluează împreună cu dezvoltarea produselor noastre.

Poate fi integrat un serviciu html. Ai încercat?

Da, desigur. De exemplu, îmi plac graficele de pe gliffy.com. Dar pentru modificări, trebuie să mergi în serviciul extern, acolo să corectezi. Și e mai greu să delegi sarcina unui coleg.

Ce să fac?

Recent, pe github, am dat peste un depozit recomandat github.com/RaoulMeyer/diagram-as-code. Diagrama ca și cod. Asta înseamnă că o descriem în js schema necesară. Acest js îl scriem chiar în același html unde se află și ceilalți texti ai documentației.

Ca o liniuță, eu scriu documentația nu chiar în html. De obicei, documentația este un set de fișiere cu text markdown, care este apoi convertit într-un site complet de documentație cu un motor, cum ar fi wintersmith. Sau un sistem wiki.

Se dovedește foarte convenabil: iată, am scris textul, apoi se deschide tag-ul script și în el este descris codul js al diagramei.

Ce nu este în regulă din nou?

Acest depozit mi-a plăcut, dar nu este singurul exemplu în care o diagramă este desenată cu ajutorul codului sau a unei reprezentări textuale. (La finalul articolului vor fi linkuri către proiecte și articole pe care le-am găsit pe tema diagrame ca și cod.)

Și eu nu sunt singur în editarea documentației. Uneori, colegii contribuie și ei — corectarea unor cuvinte, modificarea descrierilor, adăugarea de imagini noi. 

De aceea, mi-ar plăcea să văd diagrama într-un format text pe care să-l pot învăța ușor. Uneori, aș putea să fac pur și simplu copy-paste pentru a accelera adăugarea unei noi scheme. 

De asemenea, un alt coleg a observat că codul este, desigur, bun, dar dacă folosești o structură, totul poate fi foarte clar și expresiv.

Așadar, am încercat să prezint schema ca un set de mai multe array-uri mici, care descriu nodurile, conexiunile, grupurile de noduri, precum și amplasarea nodurilor. Din punctul meu de vedere, a ieșit destul de convenabil, deși, desigur, gusturile diferă...

Cum arată această diagramă în array?

  • Fiecare nod este descris printr-un identificator care îl definește în mod unic.
  • De asemenea, la nod se poate adăuga o pictogramă și o etichetă.
  • Între două noduri se poate specifica o legătură.
  • Pentru legătură în schemă se poate specifica culoarea și eticheta.
  • Direcția legăturii este definită ca de la sursă la destinație. Iar sursa și destinația sunt indicate prin identificatorii nodului.
  • Unul sau mai multe noduri pot fi adăugate într-un grup.
  • De asemenea, legătura poate fi specificată atât din grup, cât și către grup.

Folosind aceste reguli simple, obținem o astfel de schemă. Simplu? Cu siguranță.

Diagrama rețelei ca și cod

Iar aceasta este descrisă prin următorul cod js. Principalul aici este obiectul elements. În care sunt specificate nodes — noduri, edges — legături.
 

  const elements = {
    nodes: [       // descriem nodurile
      { id: 'client', type: 'smartphone', label: 'Aplicație mobilă'},
      { id: 'server', type: 'server', label: 'Server principal'},
      { id: 'db1', type: 'database', label: 'DB 1'},
      { id: 'db2', type: 'database', label: 'DB 2'},
    ],
    edges: [       // specificăm legăturile
      { source: 'client', target: 'server', label: 'cerere' },
      { source: 'server', target: 'db1', label: 'cerere' },
      { source: 'server', target: 'db2', label: 'cerere' },
    ],
  };
  Diagram('scheme1', elements);

Desigur, desenarea schemei nu am inventat-o eu, ci am folosit o bibliotecă cytoscape.js — un instrument de vizualizare foarte puternic. Din posibilitățile sale, în soluția mea folosesc doar o mică parte. 

E clar, acesta este un exemplu simplu. Poate fi ceva mai complex?

Da, desigur. Pentru specificarea pozițiilor — folosim positions, pentru specificarea grupurilor — indicăm lista grupurilor în groups, iar pentru elemente, atributul group.

Diagrama rețelei ca și cod

Iată codul:

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

Această schemă, pe de o parte, este aproape un set de coduri pe laptop, iar pe de altă parte, structura de tip JSON permite completarea rapidă a tuturor datelor prin analogie, ușor de utilizat și poate fi copiată.

Dar de ce pozițiile sunt separate de noduri?

Este mai convenabil. Mai întâi indicăm nodurile. Apoi putem specifica câteva grupuri și le putem include în noduri. Apoi definim legăturile. Și abia după ce avem obiectele de bază și legăturile dintre ele, ne ocupăm de aranjamentul acestor obiecte în schemă. Sau invers.

Poate fi fără poziții?

Se poate și fără poziții. Dar va fi un pic îngrămădit; în exemple se poate vedea un astfel de variant. Aceasta este determinată de faptul că pentru cytoscape există un algoritm de aranjare a nodurilor. fcose, care de asemenea ține cont de existența grupurilor. Specificarea pozițiilor face schemă mai controlabilă, dar în etapa preliminară a schiței putem să ne descurcăm și fără poziții.

De asemenea, pozițiile pot fi specificate în stilul războiului naval. Adică un nod se află în a1, iar altul în d5. Este deosebit de util, deoarece cytoscape formează obiectele pe canvas ca fiind mobile, adică putem să le mutăm, să vedem diferite aranjamente și apoi să salvăm în cod aranjamentul preferat al elementelor.

În general, este clar. Putem încerca?
 
Desigur, pentru a crea rapid scheme, mi-am făcut un mic editor, care actualizează automat schema și păstrează ultima variantă în browser (în localStorage).

Ați încercat? Acum puteți să-l adăugați pe pagina dumneavoastră.

Atunci, încă o dată:

1. Conectăm scriptul

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

2. Adăugăm în codul 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. corectăm codul până la schema dorită (cred că este mai simplu decât să desenăm o bufniță 🙂

Mai multe detalii pe pagina proiectului pe GitHub.

Ce înseamnă în final?

Mi-am atins scopurile — să fac adăugarea schemelor inline în documentație, formatul este suficient de simplu și clar. Nu este potrivit pentru super scheme, dar pentru scheme mai mici, care explică structura legăturilor — este foarte bun. Oricând se poate corecta rapid și se pot schimba lucruri în timp. Și colegii pot să modifice ei înșiși în doc, cel puțin semnăturile pentru obiecte fără o pregătire specială ))

Ce ar putea fi îmbunătățit?

Există, bineînțeles, o mulțime de opțiuni. Să facem adăugerea de pictograme suplimentare (toate cele existente sunt incluse inline în script). Să alegem un set mai expresiv de pictograme. Să facem posibilă specificarea stilului liniei de legătură. Să adăugăm o imagine de fundal.

Ce părere aveți?
 
Am deja câteva idei pentru implementare în probleme, adăugați și voi ale voastre în comentarii.

Soluția mea este cu siguranță aplicabilă într-un spectru îngust de sarcini, și este posibil să găsiți un instrument mai convenabil pentru crearea schemelor, codificându-le — așa cum se spune ‘arată-mi schema ta ca pe cod’

  1. O selecție bună
  2. Un serviciu excelent (9 tipuri de grafice editor online)
  3. Конечно, mermaid.js
  4. Și dacă vă plac schemele super detaliate și complexe — atunci acest proiect vă va impresiona cu siguranță: go.drawthe.net

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster