Network diagram as code / Схема мережі як код

В останні кілька років почав більше займатися документацією. Написати текст, що пояснює, про те, як працює та чи інша система — загалом, це досить просто. Намалювати схему, де будуть відображені всі ключові об'єкти, зв'язку між цими об'єктами, теж цілком легко.

Але найпроблемніший момент — підтримувати цю документацію в актуальному стані. І добре б текст, але схеми ... Т.к. вся документація онлайн, тобто. у форматі html, то до тексту додаються картинки gif/jpeg/png, у яких власне зображені схеми. А схеми малюються в різних програмах типу Visio чи онлайн-сервісах а-ля draw.io. Потім експортуєш схему до графічного формату і додаєш до html. Все просто.

У чому проблема?

Схеми зазвичай прості. Точніше, не дуже складні. Так, кількість об'єктів десяток-два, кількість зв'язків приблизно стільки ж. Плюс підписи, якісь позначення. Прості схеми і на словах описати можна, а надто складні, кх-м… (с) «не зрозуміють». Схем багато, зміни у них треба вносити періодично-епізодично, тобто. завжди, т.к. вони йдуть за розробкою наших продуктів.

Можна ж вбудовувати HTML сервісу. Пробував?

Так звичайно. Мені, наприклад, подобається графіка gliffy.com. Але для змін треба йти до стороннього сервісу, там правити. І складніше делегувати поправки зробити колезі.

Що робити?

Нещодавно на гітхабі мені попався у рекомендаціях репозиторій github.com/RaoulMeyer/diagram-as-code. Діаграма як код. Тобто. ми описуємо на js необхідну нам схему. Цей js ми пишемо у тому ж html, де й інший текст документації.

До речі, але я пишу документацію не зовсім у html. Зазвичай документація - це набір файлів з markdown-текстом, який потім конвертується в повноцінний сайт документації якимсь двигуном, наприклад wintersmith. Або wiki-система.

Виходить дуже зручно: ми написали текст, потім відкривається тег script і в ньому описаний js код схеми.

Що знову не так?

Цей репозиторій мені сподобався, але це не єдиний приклад, коли діаграму малюють за допомогою коду або текстового представлення. (Наприкінці статті будуть посилання проектів та статей, які нагуглили на тему diagram as code.)

І я ж не один правлю документацію. Іноді свій внесок вносять і колеги - слово поправити, опис змінити, нові картинки вставити. 

Тому хотілося б діаграму бачити в зрозумілому текстовому форматі, якому б не довелося довго навчатися. А подекуди навіть просто copy-paste зробити для прискорення додавання нової схеми. 

А ще один колега помітив, що код це, звичайно, добре, але якщо використати структуру, все може бути дуже суворо та виразно.

Тому я спробував представити схему як набір кількох невеликих масивів, які описують вузли, зв'язки, групи вузлів та розташування вузлів. Вийшло на мій скромний погляд досить зручно, хоча, звичайно, на смак і колір.

Як це діаграма у масиві?

  • Кожен вузол описується ідентифікатором, що однозначно визначає вузол.
  • Також до сайту можна додати іконку, додати напис.
  • Між двома вузлами можна вказати зв'язок.
  • Для зв'язку на схемі можна встановити колір, напис.
  • Напрямок зв'язку визначається як від джерела до мети. А джерело та мета вказуються ідентифікаторами вузла.
  • Один і більше вузлів можна додати до групи.
  • Зв'язок також можна вказати і від групи, і групи.

Користуючись цими простими правилами виходить така схема. Просто? Цілком.

Network diagram as code / Схема мережі як код

А описується вона наступним js-кодом. Основне тут – це об'єкт elements. У якому зазначені nodes – вузли, edges – зв'язки.
 

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

Звичайно, малювання схеми я придумав не сам, а скористався бібліотекою cytoscape.js - Дуже потужний інструмент візуалізації. Частку можливостей якої у своєму рішенні використовую лише. 

Зрозуміло, це найпростіший приклад. Чи можна складніше?

Так будь ласка. Для вказівки позицій ми використовуємо positions, для вказівки груп вказуємо список груп у groups, а у самих елементів атрибут group.

Network diagram as 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>

Така схема з одного боку - це майже пара екранів коду на ноуті, з іншого - структура а-ля json дозволяє заповнювати всі дані за аналогією, швидко і можна copy-paste.

А чому позиції винесені окремо від вузлів?

Так зручніше. Спочатку ми вказуємо nodes. Потім можемо вказати пару-трійку груп та вказати їх у вузлах. Потім позначаємо зв'язки. А вже потім, коли основні об'єкти та зв'язки між ними є, беремося за розташування цих об'єктів на схемі. Або навпаки.

А чи можна без positions?

Можна і без позицій. Але це буде трохи зім'ятий, у прикладах можна подивитися такий варіант. Це зумовлено тим, що для cytoscape є алгоритм розташування вузлів fcose, що також враховує наявність груп. Вказівка ​​positions робить схему більш контрольованою, але на стадії першого начерку схеми можна і без positions.

Також позиції можна вказувати у стилі Морського бою. Тобто. один вузол розташовується в a1, а інший в d5. Особливо допомагає, що cytoscape формує об'єкти на canvas рухомими, тобто. ми можемо їх спонукати, подивитися різні варіанти розташування, а потім зафіксувати в коді розташування елементів, що сподобалося.

Загалом, зрозуміло. Можна спробувати?
 
Звичайно, для швидкого створення схем зробив собі невеликий редактор, Що сам оновлює схему і в браузері зберігає останній варіант (в localStorage).

Спробували? Можна тепер і до себе на сторінку додати.

Тоді ще раз:

1. Підключаємо скрипт

<script src="https://unpkg.com/@antirek/[email protected]/dist/code-full.min.js"></script>

2. Додаємо в 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. правимо код до потрібної нам схеми (думаю, це простіше, ніж намалювати сову 🙂

Ще докладніше на сторінці проекту на гітхабі.

Що в підсумку?

Своїх цілей я досяг - зробити додавання схем inline до документації, формат досить простий і зрозумілий. Для суперсхем не підійде, а для невеликих схем, що пояснюють структуру зв'язків, — навіть нічого. Завжди можна швидко підправити і щось з часом змінити. Так, і колеги можуть у доку самі щось підправити, як мінімум підписи до об'єктів без особливого навчання))

Що можна покращити?

Тут варіантів, звісно, ​​маса. Зробити додавання додаткових іконок (всі наявні додані inline у ​​скрипт). Підібрати більш виразний набір іконок. Зробити можливість вказівки стилю лінії зв'язків. Додати зображення фону.

А що ви думаєте?
 
У мене вже є кілька ідей на реалізацію в issues, ви також додайте свої коментарі.

Моє рішення безперечно застосовується у вузькому спектрі завдань, і можливо ви знайдете більш зручний інструмент для малювання діаграм, просто закодувавши їх — як кажуть 'show me your diagram as code'

  1. Хороша добірка
  2. Шикарний сервіс (9 типів графіків онлайн-редактор)
  3. Звісно, ​​mermaid.js
  4. І якщо вам будь-які супер детальні та складні схеми — то вас виразно захопить цей проект: go.drawthe.net

Джерело: habr.com

Додати коментар або відгук