In den letzten Jahren habe ich mich intensiver mit der Dokumentation beschäftigt. Einen erklärenden Text darüber zu schreiben, wie ein System funktioniert, ist grundsätzlich recht einfach. Auch ein Diagramm zu erstellen, das alle wichtigen Objekte und deren Verbindungen darstellt, ist nicht allzu schwer.
Das größte Problem besteht jedoch darin, diese Dokumentation aktuell zu halten. Und wenn es nur um den Text ginge, wäre es ja noch in Ordnung. Aber bei den Diagrammen wird es komplizierter… Da die gesamte Dokumentation online, also im HTML-Format vorliegt, fügt man zu den Texten Bilder im GIF/JPEG/PNG-Format hinzu, auf denen die Diagramme dargestellt sind. Diese werden in verschiedenen Programmen wie Visio oder Online-Diensten wie draw.io erstellt. Anschließend exportiert man das Diagramm in ein Grafikformat und hängt es an das HTML-Dokument. Ganz einfach.
Was ist das Problem?
Die Diagramme sind in der Regel einfach. Genauer gesagt, sind sie nicht allzu komplex. Ja, die Anzahl der Objekte beträgt ein oder zwei Dutzend, die Anzahl der Verbindungen etwa ebenso. Dazu kommen Beschriftungen und andere Notationen. Einfache Diagramme lassen sich auch verbal erklären, aber komplexere sind (hüstel)… "werden nicht verstanden." Es gibt viele Diagramme, und Änderungen müssen regelmäßig – sprich ständig – vorgenommen werden, da sie mit der Entwicklung unserer Produkte Schritt halten.
Man kann HTML-Dienste einbetten. Hast du das schon ausprobiert?
Ja, natürlich. Mir gefallen zum Beispiel die Diagramme von gliffy.com. Für Änderungen muss man jedoch zu einem externen Dienst gehen und dort bearbeiten. Es ist auch schwieriger, Anpassungen an einen Kollegen zu delegieren.
Was tun?
Vor kurzem bin ich auf GitHub über ein empfohlenes Repository gestolpert, . Diagramm als Code. Das bedeutet, wir beschreiben das benötigte Schema in JS. Dieses JS schreiben wir direkt im selben HTML, wo auch der Rest des Dokumentationstextes steht.
Übrigens, ich schreibe die Dokumentation nicht ganz in HTML. Normalerweise ist die Dokumentation eine Sammlung von Dateien mit Markdown-Text, der dann mit einem Tool wie wintersmith in eine vollständige Dokumentationswebsite umgewandelt wird. Oder es wird ein Wiki-System verwendet.
Das ist sehr praktisch: Wir haben den Text geschrieben, dann öffnet sich das Script-Tag und darin ist der JS-Code für das Schema beschrieben.
Was ist jetzt wieder falsch?
Dieses Repository hat mir gefallen, aber es ist nicht das einzige Beispiel, bei dem Diagramme mit Code oder einem textuellen Format erstellt werden. (Am Ende des Artikels werden Links zu Projekten und Artikeln bereitgestellt, die ich zum Thema Diagramm als Code gefunden habe.)
Und ich bin nicht der Einzige, der die Dokumentation verwaltet. Manchmal tragen auch Kollegen ihren Teil bei – sei es durch das Korrigieren von Worten, das Ändern von Beschreibungen oder das Einfügen neuer Bilder.
Deshalb würde ich mir wünschen, die Diagramme in einem leicht lesbaren Textformat zu sehen, das nicht lange erlernt werden muss. Manchmal wäre es sogar einfach, Inhalte per Copy-Paste einzufügen, um die Aufnahme neuer Schemata zu beschleunigen.
Ein weiterer Kollege bemerkte, dass der Code zwar gut ist, aber mit einer strukturierten Herangehensweise alles sehr klar und aussagekräftig sein kann.
Daher habe ich versucht, das Schema als eine Sammlung mehrerer kleiner Arrays darzustellen, die Knoten, Verbindungen, Gruppen von Knoten sowie deren Anordnung beschreiben. Meiner bescheidenen Meinung nach ist dies ziemlich praktisch, obwohl, wie man sagt, über Geschmack lässt sich streiten...
Wie funktioniert dieses Diagramm in einem Array?
- Jeder Knoten wird durch eine ID beschrieben, die den Knoten eindeutig identifiziert.
- Zusätzlich kann man dem Knoten ein Icon und eine Beschriftung hinzufügen.
- Zwischen zwei Knoten kann eine Verbindung definiert werden.
- Für die Verbindung im Diagramm kann eine Farbe und eine Beschriftung festgelegt werden.
- Die Richtung der Verbindung wird von der Quelle zum Ziel bestimmt. Quelle und Ziel werden durch die IDs der Knoten angegeben.
- Einen oder mehrere Knoten können zur Gruppe hinzugefügt werden.
- Verbindungen können sowohl von der Gruppe als auch zur Gruppe angegeben werden.
Mit diesen einfachen Regeln entsteht folgendes Schema. Einfach? Ganz klar.

Und es wird im folgenden js-Code beschrieben. Das Wesentliche hier ist das Objekt elements, in dem nodes — Knoten und edges — Verbindungen angegeben sind.
const elements = {
nodes: [ // beschreiben wir die Knoten
{ id: 'client', type: 'smartphone', label: 'Mobile App'},
{ id: 'server', type: 'server', label: 'Hauptserver'},
{ id: 'db1', type: 'database', label: 'DB 1'},
{ id: 'db2', type: 'database', label: 'DB 2'},
],
edges: [ // wir geben die Verbindungen an
{ source: 'client', target: 'server', label: 'Anfrage' },
{ source: 'server', target: 'db1', label: 'Anfrage' },
{ source: 'server', target: 'db2', label: 'Anfrage' },
],
};
Diagram('scheme1', elements);
Natürlich habe ich die Zeichnung des Schemas nicht selbst erfunden, sondern eine Bibliothek verwendet. — ein sehr leistungsfähiges Visualisierungstool, dessen Möglichkeiten ich nur teilweise in meiner Lösung nutze.
Klar, das ist ein einfaches Beispiel. Kann es auch komplizierter sein?
Ja, bitte. Zur Angabe der Positionen verwenden wir positions, für die Angabe der Gruppen listen wir die Gruppen in groups auf, und die Elemente selbst haben das Attribut group.

Hier 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>
Dieses Schema ist einerseits fast ein Paar von Code-Bildschirmen auf einem Laptop, während die json-artige Struktur es ermöglicht, die Daten analog auszufüllen, schnell und einfach copy-paste.
Warum sind die positions separat von den Knoten aufgeführt?
Das ist so bequemer. Zuerst geben wir die Knoten an. Dann können wir ein oder zwei Gruppen angeben und diese in den Knoten einfügen. Dann definieren wir die Verbindungen. Und erst wenn die Hauptobjekte und ihre Verbindungen festgelegt sind, kümmern wir uns um die Anordnung dieser Objekte im Schema. Oder umgekehrt.
Kann man ohne positions arbeiten?
Ja, man kann auch ohne positions arbeiten. Aber es wird ein wenig unübersichtlich sein, in den Beispielen kann man eine solche Variante sehen. Das liegt daran, dass es für Cytoscape einen Algorithmus zur Anordnung der Knoten gibt. , der auch die Gruppen berücksichtigt. Die Angabe von positions macht das Schema kontrollierbarer, aber in der ersten Entwurfsphase kann man auch ohne positions arbeiten.
Positions können auch im Stil von Schiffe versenken angegeben werden. Das heißt, ein Knoten wird in a1 platziert und ein anderer in d5. Besonders hilfreich ist, dass Cytoscape die Objekte auf der Zeichenfläche beweglich macht, sodass wir sie verschieben und verschiedene Anordnungen ansehen können, bevor wir die bevorzugte Anordnung im Code festlegen.
Insgesamt ist es klar. Können wir es ausprobieren?
Natürlich, ich habe mir einen kleinen , erstellt, der das Diagramm automatisch aktualisiert und die letzte Version im Browser (im localStorage) speichert.
Haben Sie es ausprobiert? Jetzt kann es auch auf Ihrer Seite hinzugefügt werden.
Dann noch einmal:
1. Wir fügen das Skript hinzu
<script src="https://unpkg.com/@antirek/network-diagram@0.1.4/dist/code-full.min.js"></script>
2. Fügen Sie den HTML-Code ein
<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. passen Sie den Code an unser gewünschtes Schema an (ich denke, das ist einfacher, als eine Eule zu zeichnen 🙂
Noch detailliertere Informationen finden Sie auf GitHub.
Was ist das Ergebnis?
Ich habe meine Ziele erreicht — die Inline-Hinzufügung von Diagrammen in die Dokumentation zu ermöglichen, das Format ist recht einfach und verständlich. Für sehr komplexe Diagramme ist es vielleicht nicht geeignet, aber für kleine Diagramme, die die Struktur der Beziehungen erklären — ist es durchaus geeignet. Man kann es immer schnell anpassen und im Laufe der Zeit etwas ändern. Ja, und die Kollegen können selbst in der Dokumentation etwas anpassen, mindestens die Beschriftungen der Objekte, ohne besondere Schulung. ))
Was kann verbessert werden?
Es gibt natürlich viele Möglichkeiten. Zusätzliche Icons hinzufügen (alle vorhandenen sind inline im Skript hinzugefügt). Einen aussagekräftigeren Satz von Icons auswählen. Die Möglichkeit hinzufügen, den Stil der Verbindungslinien anzugeben. Ein Hintergrundbild hinzufügen.
Was denken Sie darüber?
Ich habe bereits einige Ideen für die Umsetzung in Issues, fügen Sie auch Ihre Ideen in die Kommentare hinzu.
Meine Lösung ist definitiv auf ein enges Spektrum von Aufgaben anwendbar. Möglicherweise finden Sie ein besseres Tool zum Zeichnen von Diagrammen, indem Sie diese einfach im Code darstellen – wie man so schön sagt: 'Zeigen Sie mir Ihr Diagramm als Code'.
- (9 Diagrammtypen im Online-Editor)
- Und wenn Sie super detaillierte und komplexe Diagramme mögen, dann wird Sie dieses Projekt definitiv begeistern:
Quelle: habr.com
