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.

А чаму positions вынесены асобна ад вузлоў?

Так зручней. Спачатку мы паказваем nodes. Затым можам паказаць пару-тройку груп і паказаць іх у вузлах. Затым абазначаем сувязі. А ўжо затым, калі асноўныя аб'екты і сувязі паміж імі ёсць, бярэмся за размяшчэнне гэтых аб'ектаў на схеме. Ці наадварот.

А ці можна без positions?

Можна і без positions. Але гэта будзе крыху скамечана, у прыкладах можна паглядзець такі варыянт. Гэта абумоўлена тым, што для cytoscape ёсць алгарытм размяшчэння вузлоў. fcose, які таксама ўлічвае наяўнасць груп. Указанне positions робіць схему больш кантраляванай, але на стадыі першага накіда схемы можна і без 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

Дадаць каментар