In den letzten paar Jahren habe ich mich intensiver mit der Dokumentation beschäftigt. Einen erklärenden Text darüber zu schreiben, wie ein bestimmtes System funktioniert – das ist insgesamt recht einfach. Ein Diagramm zu zeichnen, das alle wichtigen Objekte und die Verbindungen zwischen diesen Objekten darstellt, ist auch ziemlich leicht.
Aber der schwierigste Punkt ist, diese Dokumentation aktuell zu halten. Wäre der Text nicht das Problem, aber die Diagramme… Da die gesamte Dokumentation online ist, also im html-Format, sind die Texte durch Bilder im gif/jpg/png-Format ergänzt, auf denen die Diagramme gezeigt werden. Diese Diagramme werden mit verschiedenen Programmen wie Visio oder Online-Diensten wie draw.io erstellt. Dann exportiert man das Diagramm in ein grafisches Format und fügt es in das html ein. Ganz einfach.
Was ist das Problem?
Die Diagramme sind normalerweise einfach. Genauer gesagt, nicht sehr komplex. Ja, die Anzahl der Objekte liegt bei zehn bis zwanzig, die Anzahl der Verbindungen ungefähr ebenso. Zusätzlich gibt es Beschriftungen, einige Bezeichnungen. Einfache Diagramme kann man auch verbal beschreiben, während zu komplexe, hm… (c) „nicht verstanden werden“. Es gibt viele Diagramme, die regelmäßig aktualisiert werden müssen, also ständig, da sie dem Fortschritt unserer Produkte folgen.
Kann man nicht den html-Dienst einbetten? Hast du das versucht?
Ja, natürlich. Mir gefallen zum Beispiel die Grafiken von gliffy.com. Aber für Änderungen muss man zu einem Drittanbieter gehen und dort Änderungen vornehmen. Es ist auch schwieriger, einem Kollegen die Korrekturen anzuvertrauen.
Was tun?
Kürzlich bin ich auf GitHub über einen Repository gestolpert, . Diagramme als Code. Das heißt, wir beschreiben das benötigte Diagramm in js. Dieses js schreiben wir direkt im selben html, wo auch der restliche Text der Dokumentation steht.
Übrigens schreibe ich die Dokumentation nicht ganz in html. Normalerweise besteht die Dokumentation aus einer Reihe von Dateien mit markdown-Text, der dann mit einer Engine in eine vollständige Dokumentationswebsite konvertiert wird, zum Beispiel wintersmith. Oder in einem Wiki-System.
Das ist sehr praktisch: Wir haben den Text geschrieben, dann öffnet sich das script-Tag und darin ist der js-Code für das Diagramm beschrieben.
Was ist wieder falsch?
Dieser Repository hat mir gefallen, aber das ist nicht das einzige Beispiel, bei dem ein Diagramm mit Hilfe von Code oder einer textlichen Darstellung gezeichnet wird. (Am Ende des Artikels finden sich Links zu Projekten und Artikeln, die ich zum Thema Diagramm als Code gefunden habe.)
Und ich bin nicht der einzige, der die Dokumentation bearbeitet. Manchmal leisten auch Kollegen ihren Beitrag – ein Wort korrigieren, eine Beschreibung ändern, neue Bilder einfügen.
Daher möchte ich das Diagramm in einem lesbaren, verständlichen Textformat sehen, das man nicht lange erlernen muss. Manchmal könnte man auch einfach Copy-Paste verwenden, um die Hinzufügung eines neuen Schemas zu beschleunigen.
Ein weiterer Kollege bemerkte, dass Code natürlich gut ist, aber wenn man eine Struktur verwendet, kann alles sehr strikt und ausdrucksvoll sein.
Deshalb habe ich versucht, das Schema als eine Reihe von mehreren kleinen Arrays darzustellen, die Knoten, Verbindungen, Gruppen von Knoten und auch die Position der Knoten beschreiben. Meiner bescheidenen Meinung nach ist das ziemlich praktisch, obwohl es natürlich Geschmackssache ist.
Wie sieht dieses Diagramm im Array aus?
- Jeder Knoten wird durch eine ID beschrieben, die den Knoten eindeutig identifiziert.
- Außerdem kann man dem Knoten ein Icon hinzufügen und eine Beschriftung hinzufügen.
- Zwischen zwei Knoten kann eine Verbindung angegeben werden.
- Für die Verbindung im Schema kann man Farbe und Beschriftung festlegen.
- Die Richtung der Verbindung wird als von der Quelle zum Ziel definiert. Quelle und Ziel werden durch die IDs der Knoten angegeben.
- Einen oder mehrere Knoten kann man zu einer Gruppe hinzufügen.
- Die Verbindung kann auch von einer Gruppe und zu einer Gruppe angegeben werden.
Mit diesen einfachen Regeln entsteht ein solches Schema. Einfach? Völlig.

Und es wird mit folgendem js-Code beschrieben. Wichtig hier ist das Objekt elements. Darin sind die nodes — Knoten, edges — Verbindungen angegeben.
const elements = {
nodes: [ // beschreibt die Knoten
{ 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: [ // gibt die Verbindungen an
{ source: 'client', target: 'server', label: 'request' },
{ source: 'server', target: 'db1', label: 'request' },
{ source: 'server', target: 'db2', label: 'request' },
],
};
Diagram('scheme1', elements);
Natürlich habe ich die Zeichnung des Schemas nicht selbst erfunden, sondern eine Bibliothek verwendet, — ein sehr leistungsstarkes Visualisierungstool, dessen Möglichkeiten ich in meiner Lösung nur teilweise nutze.
Natürlich ist das ein einfaches Beispiel. Kann es etwas komplizierter sein?
Ja, gerne. Um Positionen anzugeben, verwenden wir positions, um Gruppen anzugeben, geben wir eine Liste von Gruppen in groups an, und die Elemente selbst haben das Attribut group.

Und das ist der Code:
<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>
Solch ein Schema ist einerseits fast zwei Bildschirmseiten Code auf dem Laptop, andererseits ermöglicht die JSON-ähnliche Struktur, alle Daten analog und schnell zu füllen und man kann Copy-Paste verwenden.
Warum sind die Positionen getrennt von den Knoten ausgeführt?
So ist es bequemer. Zuerst geben wir die nodes an. Dann können wir ein oder zwei Gruppen angeben und sie den Knoten zuweisen. Danach definieren wir die Verbindungen. Und erst, wenn die Hauptobjekte und deren Verbindungen vorhanden sind, kümmern wir uns um die Anordnung dieser Objekte im Diagramm. Oder umgekehrt.
Geht es auch ohne positions?
Es ist auch ohne positions möglich. Aber es wird etwas chaotisch sein, in den Beispielen kann man eine solche Variante sehen. Dies liegt daran, dass es für cytoscape einen Algorithmus zur Anordnung der Knoten gibt, , der auch die Gruppen berücksichtigt. Das Angeben von positions macht das Diagramm kontrollierbarer, aber in der ersten Entwurfsphase des Diagramms kann man auch ohne positions arbeiten.
Außerdem können positions im Stil von Schach angegeben werden. Das heißt, ein Knoten befindet sich in a1, der andere in d5. Besonders hilfreich ist, dass cytoscape die Objekte auf dem Canvas beweglich erstellt, d.h. wir können sie verschieben, verschiedene Anordnungen ausprobieren und dann die uns gefallene Anordnung im Code fixieren.
Insgesamt ist es verständlich. Können wir es ausprobieren?
Natürlich, für die schnelle Erstellung von Diagrammen habe ich mir einen kleinen , der das Diagramm selbst aktualisiert und im Browser die letzte Version speichert (in localStorage).
Haben Sie es ausprobiert? Jetzt können Sie es auch auf Ihre Seite hinzufügen.
Dann noch einmal:
1. Binden Sie das Skript ein
<script src="https://unpkg.com/@antirek/network-diagram@0.1.4/dist/code-full.min.js"></script>
2. Fügen Sie diesen HTML-Code hinzu
<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. bearbeiten Sie den Code zu dem gewünschten Diagramm (ich denke, das ist einfacher, als eine Eule zu zeichnen 🙂
Noch detailliertere Informationen auf GitHub.
Was kommt dabei heraus?
Ich habe meine Ziele erreicht — die Inline-Einfügung von Diagrammen in die Dokumentation, das Format ist ausreichend einfach und verständlich. Für komplexe Diagramme eignet es sich nicht, aber für kleine Diagramme, die die Struktur von Verbindungen erklären, ist es durchaus geeignet. Man kann immer schnell Anpassungen vornehmen und im Laufe der Zeit etwas ändern. Ja, und die Kollegen können in der Dokumentation selbst etwas ändern, mindestens die Beschriftungen der Objekte ohne besondere Schulung ))
Was kann verbessert werden?
Hier gibt es natürlich viele Möglichkeiten. Weitere Symbole hinzufügen (alle vorhandenen sind inline im Skript hinzugefügt). Ein ausdrucksvolleres Symbolset auswählen. Die Möglichkeit zur Festlegung des Stils der Verbindungslinien hinzufügen. Ein Hintergrundbild einfügen.
Was denken Sie?
Ich habe bereits einige Ideen zur Umsetzung in den Issues, fügen Sie auch Ihre in die Kommentare hinzu.
Meine Lösung ist definitiv auf einen engen Spektrum von Aufgaben anwendbar, und möglicherweise finden Sie ein bequemeres Tool zum Zeichnen von Diagrammen, indem Sie sie einfach codieren – wie man so schön sagt: 'zeige mir dein Diagramm als Code'
- (9 Typen von Diagrammen Online-Editor)
- Und wenn Sie super detaillierte und komplexe Diagramme mögen, dann wird dieses Projekt Sie definitiv begeistern:
Quelle: habr.com
