Netværksdiagram som kode / Network diagram as code

I de seneste par år er jeg begyndt at fokusere mere på dokumentation. At skrive en forklarende tekst om, hvordan et bestemt system fungerer, er generelt ret enkelt. At lave et diagram, der viser alle nøgleobjekter og forbindelserne mellem disse objekter, er også ganske let.

Men den største udfordring er at holde denne dokumentation opdateret. Og det er ikke kun teksten; diagrammerne... Da al dokumentation er online, altså i html-format, følger billederne i gif/jpg/png, som faktisk viser diagrammerne. Diagrammerne laves i forskellige programmer som Visio eller online-tjenester som draw.io. Derefter eksporterer du diagrammet til et grafisk format og tilføjer det til html. Alt er simpelt.

Hvad er problemet?

Diagrammerne er normalt enkle. Mere præcist, ikke meget komplekse. Ja, antallet af objekter er ti til tolv, og antallet af forbindelser er omtrent det samme. Plus, der er beskrivelser og nogle betegnelser. Enkle diagrammer kan også beskrives med ord, men alt for komplekse, hmmm... (s) "forstår ikke-s". Der er mange diagrammer, og ændringer i dem skal forekomme jævnligt, som sagt, konstant, da de følger udviklingen af vores produkter.

Kan man ikke integrere html fra tjenesterne? Har du prøvet?

Ja, selvfølgelig. Jeg kan for eksempel godt lide diagrammerne fra gliffy.com. Men for at lave ændringer skal man gå til en ekstern tjeneste og redigere der. Det er også sværere at delegere opgaver til en kollega.

Hvad skal man gøre?

For nylig kom jeg over et repository på GitHub, som blev anbefalet til mig. github.com/RaoulMeyer/diagram-as-code. Diagram som kode. Det vil sige, at vi beskriver den nødvendige skematik i js. Denne js skriver vi direkte i samme html, som den øvrige dokumentationstekst.

For at sige det på en anden måde, så skriver jeg ikke dokumentation helt i html. Normalt er dokumentation en samling af filer med markdown-tekst, som derefter konverteres til et fuldt dokumentationswebsted ved hjælp af en motor, som f.eks. wintersmith. Eller et wiki-system.

Det er meget praktisk: Vi skriver teksten, så åbner vi et script-tag, og der beskrives js-koden for diagrammet.

Hvad er der nu galt?

Dette repository kunne jeg godt lide, men det er ikke det eneste eksempel, hvor et diagram laves med hjælp af kode eller tekstrepræsentation. (I slutningen af artiklen vil der være links til projekter og artikler, som jeg har fundet om emnet diagram som kode.)

Og jeg er ikke den eneste, der redigerer dokumentationen. Nogle gange bidrager kolleger også med deres kommentar — at rette et ord, ændre en beskrivelse, indsætte nye billeder. 

Derfor vil jeg gerne have diagrammet i et læsbart og forståeligt tekstformat, som man ikke skal bruge lang tid på at lære. Nogle steder ville det endda være muligt blot at copy-paste for at fremskynde tilføjelsen af nye skemaer. 

En anden kollega bemærkede, at kode selvfølgelig er godt, men hvis man bruger strukturen, kan alt være meget stramt og udtryksfuldt.

Derfor har jeg forsøgt at fremstille skemaet som en samling af flere små arrays, der beskriver noder, forbindelser, grupper af noder samt placeringen af noder. Det virker, efter min beskedne mening, ret praktisk, skønt man selvfølgelig har forskellige smag.

Hvordan ser dette diagram ud i et array?

  • Hver node beskrives med en identifikator, der entydigt definerer noden.
  • Man kan også tilføje et ikon til noden samt en beskrivelse.
  • Mellem to noder kan man angive en forbindelse.
  • For forbindelsen i skemaet kan man angive farve og beskrivelse.
  • Retningen af forbindelsen defineres som fra kilde til mål. Kilde og mål angives med nodernes identifikatorer.
  • En eller flere noder kan tilføjes til en gruppe.
  • Forbindelsen kan også angives fra en gruppe til en gruppe.

Ved at følge disse enkle regler får man sådan et skema. Simpelt? Absolut.

Netværksdiagram som kode / Network diagram as code

Og det beskrives med følgende js-kode. Hovedpointen her er objektet elements. Hvor der er angivet noder — noder, kanter — forbindelser.
 

  const elements = {
    nodes: [       // beskrivelse af noder
      { id: 'client', type: 'smartphone', label: 'Mobil App'},
      { id: 'server', type: 'server', label: 'Hovedserver'},
      { id: 'db1', type: 'database', label: 'DB 1'},
      { id: 'db2', type: 'database', label: 'DB 2'},
    ],
    edges: [       // angivelse af forbindelser
      { source: 'client', target: 'server', label: 'anmodning' },
      { source: 'server', target: 'db1', label: 'anmodning' },
      { source: 'server', target: 'db2', label: 'anmodning' },
    ],
  };
  Diagram('scheme1', elements);

Naturligvis har jeg ikke selv opfundet tegningen af skemaet, men har brugt et bibliotek cytoscape.js — et meget kraftfuldt visualiseringsværktøj. Jeg bruger kun en del af dets muligheder i min løsning. 

Det er tydeligt, at dette er et simpelt eksempel. Kan vi gøre det mere komplekst?

Ja, selvfølgelig. For at angive positioner bruger vi positions, for at angive grupper angiver vi en liste over grupper i groups, og for selve elementerne har vi attributten group.

Netværksdiagram som kode / Network diagram as code

Og her er koden:

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

Dette skema er på den ene side næsten to skærme kode på en laptop, men på den anden side gør strukturen a la json det muligt at udfylde alle data efter samme mønster, hurtigt og muligt at copy-paste.

Og hvorfor er positions adskilt fra noderne?

Det er lettere. Først angiver vi nodes. Så kan vi angive et par grupper og inkludere dem i noderne. Derefter definerer vi forbindelserne. Og først når de grundlæggende objekter og forbindelser mellem dem er på plads, begynder vi at placere disse objekter på skemaet. Eller omvendt.

Kan vi gøre det uden positions?

Det kan vi godt gøre uden positions. Men det vil være lidt rodet; i eksemplerne kan man se en sådan variant. Dette skyldes, at der for cytoscape er en algoritme til placering af noder. fcose, som også tager hensyn til grupper. Angivelsen af positions gør skemaet mere kontrolleret, men i første udkast til skemaet kan man godt undvære positions.

Positions kan også angives i stil med Skak. Det vil sige, at en node placeres i a1, og en anden i d5. Det hjælper især, at cytoscape laver objekterne på canvas som flytbare, så vi kan flytte dem, se forskellige placeringsmuligheder og derefter fastgøre det ønskede arrangement i koden.

Overordnet set, klart. Kan vi prøve?
 
Selvfølgelig, for hurtigt at lave skemaer har jeg lavet en lille en, redaktør, som automatisk opdaterer skemaet og gemmer den seneste version i browseren (i localStorage).

Har du prøvet? Nu kan du også tilføje det til din egen side.

Så, endnu en gang:

1. Vi tilslutter scriptet

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

2. Vi tilføjer til HTML-koden

<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. vi retter koden til det ønskede skema (jeg tror, det er lettere end at tegne en ugle 🙂

Uddybende på på projektets side på GitHub.

Hvad ender vi med?

Mine mål er nået — at gøre det muligt at tilføje skemaer inline i dokumentationen, formatet er ret enkelt og forståeligt. Det er ikke egnet til superkomplekse skemaer, men til små skemaer, der forklarer strukturen af forbindelser — er det rigtig godt. Man kan altid hurtigt rette lidt og ændre noget over tid. Desuden kan kolleger selv rette noget i dokumentationen, som minimum ændre beskrivelserne til objekterne uden særlig training.))

Hvad kan forbedres?

Der er selvfølgelig mange muligheder. Tilføje ekstra ikoner (alle eksisterende er tilføjet inline i scriptet). Vælge et mere udtryksfuldt sæt ikoner. Gøre det muligt at angive stil for forbindelseslinjer. Tilføje et baggrundsbillede.

Hvad tænker du?
 
Jeg har allerede flere implementeringsideer i issues, du kan også tilføje dine i kommentarerne.

Min løsning er bestemt anvendelig inden for et smalt spektrum af opgaver, og du vil måske finde et mere bekvemt værktøj til at tegne diagrammer ved simpelthen at kode dem — som man siger 'vis mig dit diagram som kode'

  1. Godt udvalg
  2. Fantastisk service (9 typer diagrammer online-redaktør)
  3. Конечно, mermaid.js
  4. Og hvis du elsker super detaljerede og komplekse diagrammer — så vil dette projekt bestemt imponere dig: go.drawthe.net

Kilde: habr.com

Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere 🔥 Køb pålidelig webhosting med DDoS-beskyttelse, VPS VDS-servere | ProHoster