Hlavní navigace

Knihovny Diagrams a go-diagrams určené pro tvorbu diagramů s architekturou systémů

27. 5. 2021
Doba čtení: 28 minut

Sdílet

 Autor: Pavel Tišnovský
Nejprve dokončíme popis knihovny Diagrams navržené pro tvorbu grafů definovaných v Pythonu. Ve druhé části článku se zaměříme na popis knihovny go-diagrams, což je obdoba Diagrams, ovšem určená pro Go.

Obsah

1. Knihovny Diagrams a go-diagrams určené pro tvorbu diagramů s architekturou systémů

2. Clustery v diagramech tvořených knihovnou Diagrams

3. Vytvoření clusteru v diagramu

4. Větší množství clusterů v diagramu

5. Hierarchické (vnořené) clustery

6. Další příklad hierarchických clusterů

7. Knihovna go-diagrams inspirovaná knihovnou Diagrams

8. Prázdný diagram vytvořený knihovnou go-diagrams

9. Diagram s dvojicí uzlů a jednou hranou

10. Propojení většího množství uzlů

11. Skupiny uzlů v diagramu

12. Pojmenování skupiny v diagramu

13. Propojení typu 1:N a N:1

14. Programové vytvoření skupiny s vazbami 1:N a N:1

15. Porovnání knihoven Diagrams a go-diagrams

16. Repositář s demonstračními příklady psanými v Pythonu

17. Repositář s demonstračními příklady psanými v jazyce Go

18. Odkazy na články s tématem programové tvorby grafů a diagramů

19. Odkazy na Internetu

1. Knihovny Diagrams a go-diagrams určené pro tvorbu diagramů s architekturou systémů

V dnešním článku nejdříve dokončíme popis možností knihovny nazvané Diagrams, jíž jsme se zabývali minule, a poté se seznámíme s další podobně koncipovanou knihovnou, tentokrát ovšem určenou pro programovací jazyk Go. Jedná se o knihovnu pojmenovanou go-diagrams. Tato knihovna je navržena takovým způsobem, aby byla s původní Pythonovskou knihovnou Diagrams do určité míry kompatibilní, což se týká především způsobu definice diagramů (ve skutečnosti je však použití varianty pro Go složitější, než v případě knihovny Diagrams pro Python, což si ostatně ukážeme na demonstračních příkladech).

2. Clustery v diagramech tvořených knihovnou Diagrams

Minule jsme si ukázali, jakým způsobem se s využitím knihovny Diagrams tvoří diagramy. Připomeňme si, že se nejprve vytvoří objekt typu Diagram (ideálně v rámci takzvaného kontextu, tedy bloku with), následně se zkonstruují různé typy uzlů a nakonec se tyto uzly propojí s využitím přetíženého operátoru >>. Taktéž je možné namísto jediného uzlu použít seznam či n-tici s uzly – poté se zobrazí propojení typu 1:N nebo N:1:

from diagrams import Diagram
from diagrams.onprem.queue import Kafka, ActiveMQ
from diagrams.programming.language import Go, Rust
from diagrams.aws.database import RDS
 
with Diagram("Clusters #1", show=True, direction="LR"):
    # definice uzlu
    consumer = Kafka("input stream")
 
    db = RDS("storage")
 
    # rozvetveni
    workersA = [Go("worker #1"),
                Go("worker #2"),
                Go("worker #3")]
 
    buffer = ActiveMQ("buffer")
 
    # rozvetveni
    workersB = [Rust("worker #1"),
                Rust("worker #2"),
                Rust("worker #3")]
 
    producer = Kafka("output stream")
 
    # propojeni uzlu grafu orientovanymi hranami
    consumer >> workersA >> buffer >> workersB >> producer
    db >> workersA

Výsledek dnešního prvního demonstračního příkladu vypadá následovně:

Obrázek 1: Diagram vytvořený prvním demonstračním příkladem.

Ve skutečnosti je však mnohdy vhodné některé uzly seskupit do takzvaného clusteru. Jak se tato operace provede si ukážeme v navazujících kapitolách.

3. Vytvoření clusteru v diagramu

Cluster neboli seskupení uzlů, se ve skutečnosti provede velmi jednoduše. Postačuje pouze vytvořit uzly (resp. přesněji řečeno ty uzly, které se mají sdružit) v rámci kontextu, tedy uvnitř bloku with v němž je zkonstruován objekt typu Cluster. V následující ukázce skriptu se vytvoří dva uzly sdružené do clusteru:

    with Cluster("jméno clusteru"):
        # definice uzlu v clusteru
        uzel1 =  Kafka("input stream")
 
        uzel2 = RDS("storage")

Samozřejmě je však možné pracovat i se seznamem uzlů, tedy následovně:

    with Cluster("jméno clusteru"):
        # definice uzlu v clusteru
        uzel1 =  Kafka("input stream")
 
        # rozvetveni
        uzly = [Go("worker #1"),
                Go("worker #2"),
                Go("worker #3")]
 
        uzel2 = RDS("storage")

Podívejme se nyní na nepatrně upravený předchozí demonstrační příklad, do něhož byl přidán cluster:

from diagrams import Diagram
from diagrams import Cluster
from diagrams.onprem.queue import Kafka, ActiveMQ
from diagrams.programming.language import Go, Rust
from diagrams.aws.database import RDS
 
with Diagram("Clusters #2", show=True, direction="LR"):
    # definice clusteru
    with Cluster("Input processor"):
        # definice uzlu v clusteru
        consumer = Kafka("input stream")
 
        # rozvetveni
        workersA = [Go("worker #1"),
                    Go("worker #2"),
                    Go("worker #3")]
 
        db = RDS("storage")
 
    # definice uzlu mimo cluster
    buffer = ActiveMQ("buffer")
 
    # rozvetveni
    workersB = [Rust("worker #1"),
                Rust("worker #2"),
                Rust("worker #3")]
 
    producer = Kafka("output stream")
 
    # propojeni uzlu grafu orientovanymi hranami
    consumer >> workersA >> buffer >> workersB >> producer
    db >> workersA

Výsledek by měl nyní vypadat následovně:

Obrázek 2: Diagram vytvořený druhým demonstračním příkladem.

4. Větší množství clusterů v diagramu

Nic nám samozřejmě nebrání vytvořit v diagramu větší množství clusterů. Jedinou podmínkou je, že se tyto clustery nebudou překrývat (i to je však možné zařídit některými triky). V dalším demonstračním příkladu je ukázána definice diagramu s několika uzly rozdělenými mezi dvojici clusterů. Oba clustery (resp. uzly v clusteru) jsou propojeny přes buffer/frontu představovanou uzlem ActiveMQ (což je jeden ze známých message brokerů):

from diagrams import Diagram
from diagrams import Cluster
from diagrams.onprem.queue import Kafka, ActiveMQ
from diagrams.programming.language import Go, Rust
from diagrams.aws.database import RDS
 
with Diagram("Clusters #3", show=True, direction="LR"):
    # definice clusteru
    with Cluster("Input processor"):
        # definice uzlu v clusteru
        consumer = Kafka("input stream")
 
        # rozvetveni
        workersA = [Go("worker #1"),
                    Go("worker #2"),
                    Go("worker #3")]
 
        db = RDS("storage")
 
    # definice uzlu mimo cluster
    buffer = ActiveMQ("buffer")
 
    with Cluster("Output processor"):
        # rozvetveni
        workersB = [Rust("worker #1"),
                    Rust("worker #2"),
                    Rust("worker #3")]
 
        producer = Kafka("output stream")
 
    # propojeni uzlu grafu orientovanymi hranami
    consumer >> workersA >> buffer >> workersB >> producer
    db >> workersA

Výsledek bude v tomto případě následující:

Obrázek 3: Diagram vytvořený třetím demonstračním příkladem.

5. Hierarchické (vnořené) clustery

Cluster může kromě uzlů obsahovat i další clustery, takže diagram může zobrazovat i poměrně složitou hierarchii navrhovaného systému. V Pythonu se vnořené clustery definují vnořenými bloky with:

with Cluster("Input processor"):
    # definice uzlu v clusteru
    uzel1 = Kafka("input stream")
 
    # definice clusteru uvnitř cluster
    with Cluster("Worker group A"):
        # definice uzlu v podclusteru
        uzel2 = Kafka("input stream")

Prakticky může vypadat definice diagramu s hierarchií clusterů následovně:

from diagrams import Diagram
from diagrams import Cluster
from diagrams.onprem.queue import Kafka, ActiveMQ
from diagrams.programming.language import Go, Rust
from diagrams.aws.database import RDS
 
with Diagram("Clusters #4", show=True, direction="LR"):
    # definice clusteru
    with Cluster("Input processor"):
        # definice uzlu v clusteru
        consumer = Kafka("input stream")
 
        # definice clusteru uvnitr cluster
        with Cluster("Worker group A"):
            # rozvetveni
            workersA = [Go("worker #1"),
                        Go("worker #2"),
                        Go("worker #3")]
 
        db = RDS("storage")
 
    # definice uzlu mimo cluster
    buffer = ActiveMQ("buffer")
 
    with Cluster("Output processor"):
        # definice clusteru uvnitr cluster
        with Cluster("Worker group B"):
            # rozvetveni
            workersB = [Rust("worker #1"),
                        Rust("worker #2"),
                        Rust("worker #3")]
 
        producer = Kafka("output stream")
 
    # propojeni uzlu grafu orientovanymi hranami
    consumer >> workersA >> buffer >> workersB >> producer
    db >> workersA

Výsledný diagram:

Obrázek 4: Diagram vytvořený čtvrtým demonstračním příkladem.

6. Další příklad hierarchických clusterů

Poslední demonstrační příklad, který je založen na knihovně Diagrams, ukazuje způsob vytvoření diagramu s trojím zanořením clusterů, tedy situaci, kdy jeden cluster obsahuje další clustery a i ty obsahují další clustery z uzly. Maximální úroveň zanoření není prakticky omezena:

from diagrams import Diagram
from diagrams import Cluster
from diagrams.onprem.queue import Kafka, ActiveMQ
from diagrams.programming.language import Go, Rust
from diagrams.aws.database import RDS
 
with Diagram("Clusters #5", show=True, direction="LR"):
    with Cluster("Out wonderful pipeline"):
        # definice clusteru
        with Cluster("Input processor"):
            # definice uzlu v clusteru
            consumer = Kafka("input stream")
 
            # definice clusteru uvnitr cluster
            with Cluster("Worker group A"):
                # rozvetveni
                workersA = [Go("worker #1"),
                            Go("worker #2"),
                            Go("worker #3")]
 
            db = RDS("storage")
 
        # definice uzlu mimo cluster
        buffer = ActiveMQ("buffer")
 
        with Cluster("Output processor"):
            # definice clusteru uvnitr cluster
            with Cluster("Worker group B"):
                # rozvetveni
                workersB = [Rust("worker #1"),
                            Rust("worker #2"),
                            Rust("worker #3")]
 
            producer = Kafka("output stream")
 
    # propojeni uzlu grafu orientovanymi hranami
    consumer >> workersA >> buffer >> workersB >> producer
    db >> workersA

Obrázek 5: Diagram vytvořený pátým demonstračním příkladem.

7. Knihovna go-diagrams inspirovaná knihovnou Diagrams

Ve druhé části dnešního článku se seznámíme se základy používání knihovny nazvané go-diagrams. Jedná se o poměrně přiléhavý název, protože tato knihovna je skutečně určena pro použití v programovacím jazyku Go a současně byl její návrh do určité míry inspirován výše popsanou knihovnou Diagrams. Nicméně – jak ostatně uvidíme v navazujících kapitolách, v nichž budou ukázány demonstrační příklady – se skutečně jedná pouze o inspiraci, protože vytváření diagramů je v go-diagrams přece jen poněkud odlišné. Je to do značné míry způsobeno rozdílnostmi mezi Pythonem a Go: v prvním případě se jedná o dynamicky typovaný programovací jazyk se sémantikou pro definici kontextů s využitím bloku with, ve druhém případě o jazyk staticky typovaný, navíc nepodporující ani blok with ani žádnou další podobně koncipovanou jazykovou konstrukci (Go nemá ani koncept nepovinných pojmenovaných parametrů, což je opět jeden z rozdílů, na který narazíme).

Další rozdíl spočívá v tom, že zatímco knihovna Diagrams dokázala diagramy vykreslovat automaticky (dokonce i s náhledem), je tomu v případě go-diagrams jinak, protože po překladu a spuštění kódu se vytvoří soubor s koncovkou .dot, který je nutné následně dále zpracovat nástrojem GraphViz, o němž jsme se v tomto miniseriálu již několikrát zmínili. Teprve GraphViz dokáže z definice grafu (tentokrát popsaného pomocí DSL) vytvořit rastrový obrázek, vektorovou kresbu, dokument v PDF atd.

8. Prázdný diagram vytvořený knihovnou go-diagrams

Knihovna go-diagrams se instaluje s využitím základních prostředků nabízených ekosystémem programovacího jazyka Go. Pro stažení, překlad a instalaci knihovny je nutné použít tento příkaz:

$ go get github.com/blushft/go-diagrams

Pro otestování, zda je knihovna go-diagrams nainstalována a zda je volatelná, použijeme následující demonstrační příklad, který představuje definici prázdného (nicméně korektního) diagramu. Povšimněte si použití konstruktoru pro vytvoření diagramu a taktéž explicitního požadavku na jeho vykreslení (což ovšem neznamená vykreslení obrázku, ale vygenerování souboru .dot):

package main
 
import (
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
)
 
func main() {
        // inicializace objektu představujícího diagram
        diagram, err := diagram.New(diagram.Label("Diagram #1"), diagram.Filename("diagram1"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // vykreslení diagramu
        err = diagram.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}

Příklad přeložíme (na pozadí) a spustíme:

$ go run diagrams1.go
Poznámka: zdrojový kód tohoto příkladu je dostupný na adrese https://github.com/tisnik/go-root/blob/master/article74/di­agram1.go.

Po spuštění by se měl v aktuálním (pracovním) adresáři objevit nový podadresář, který obsahuje jak definici diagramu v jazyku DOT, tak i datové soubory s ikonami jednotlivých uzlů. Tyto datové soubory uvidíme u následujících demonstračních příkladů. Podívejme se na obsah zmíněného souboru s definicí diagramu v jazyku DOT:

digraph root {
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=13;
        label="Diagram #1";
        nodesep=0.6;
        pad=2;
        rankdir=LR;
        ranksep=0.75;
        splines=ortho;
}

Vykreslení obrázku zajistí příkaz:

$ dot -Tpng diagram1.dot > diagram.png
Poznámka: samozřejmě je možné zvolit i jiný formát výstupu, zejména SVG a PDF.

Obrázek 6: Výsledek získaný předchozím příkazem.

9. Diagram s dvojicí uzlů a jednou hranou

První demonstrační příklad založený na knihovně go-diagrams zajisté nebyl příliš oslnivý, protože dokázal vykreslit pouze prázdný diagram. Ukažme si tedy poněkud složitější diagram (vlastně první diagram, který má skutečně reálný význam) s dvojicí uzlů propojených hranou. Podobně jako v knihovně Diagrams je i zde zapotřebí nejdříve zkonstruovat oba uzly a následně je propojit – ovšem nikoli přetíženým operátorem >>, ale metodou Connect. Zdrojový kód tohoto příkladu naleznete na adrese https://github.com/tisnik/go-root/blob/master/article74/di­agram2.go:

package main
 
import (
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
        "github.com/blushft/go-diagrams/nodes/apps"
)
 
func main() {
        // inicializace objektu představujícího diagram
        diagram, err := diagram.New(diagram.Label("Diagram #2"), diagram.Filename("diagram2"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // deklarace uzlů v diagramu
        inet := apps.Network.Internet().Label("Internet")
        proxy := apps.Network.Caddy().Label("3scale")
 
        // propojení uzlů v diagramu
        diagram.Connect(inet, proxy)
 
        // vykreslení diagramu
        err = diagram.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}
Poznámka: prozatím používáme uzly definované v balíčku github.com/blushft/go-diagrams/nodes/apps, ovšem těchto balíčků existuje více – podobně jako v případě knihovny Diagrams.

Vygenerovaný soubor s definicí grafu v doménově specifickém jazyce DOT:

digraph root {
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=13;
        label="Diagram #2";
        nodesep=0.6;
        pad=2;
        rankdir=LR;
        ranksep=0.75;
        splines=ortho;
        wuyslsjy->munjokhx [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        munjokhx [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/apps/network/caddy.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
        wuyslsjy [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/apps/network/internet.png", imagescale=true, label=Internet, labelloc=b, shape=none, style=rounded, width=1.4 ];
}

Diagram po vykreslení příkazem dot:

Obrázek 7: Výsledek získaný příkazem dot.

10. Propojení většího množství uzlů

Ve třetím demonstračním příkladu založeném na knihovně go-diagrams je definován diagram s trojicí uzlů, které jsou načteny ze dvou různých balíčků (viz sekce import). Tento diagram budeme dále rozvíjet v navazujících kapitolách:

package main
 
import (
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
        "github.com/blushft/go-diagrams/nodes/apps"
        "github.com/blushft/go-diagrams/nodes/gcp"
)
 
func main() {
        // inicializace objektu představujícího diagram
        diagram, err := diagram.New(diagram.Label("Diagram #3"), diagram.Filename("diagram3"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // deklarace uzlů v diagramu
        inet := apps.Network.Internet().Label("Internet")
        proxy := apps.Network.Caddy().Label("3scale")
        router := gcp.Network.Router().Label("Router")
 
        // propojení uzlů v diagramu
        diagram.Connect(inet, proxy)
        diagram.Connect(proxy, router)
 
        // vykreslení diagramu
        err = diagram.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}
Poznámka: zdrojový kód tohoto příkladu je dostupný na adrese https://github.com/tisnik/go-root/blob/master/article74/di­agram3.go.

Vygenerovaný soubor s definicí grafu v doménově specifickém jazyce DOT:

digraph root {
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=13;
        label="Diagram #3";
        nodesep=0.6;
        pad=2;
        rankdir=LR;
        ranksep=0.75;
        splines=ortho;
        loggiusv->vwecchtf [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        dkxkvtkt->loggiusv [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        dkxkvtkt [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/apps/network/internet.png", imagescale=true, label=Internet, labelloc=b, shape=none, style=rounded, width=1.4 ];
        loggiusv [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/apps/network/caddy.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
        vwecchtf [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/gcp/network/router.png", imagescale=true, label=Router, labelloc=b, shape=none, style=rounded, width=1.4 ];
}

Diagram po vykreslení příkazem dot:

Obrázek 8: Výsledek získaný příkazem dot.

11. Skupiny uzlů v diagramu

Čtvrtý demonstrační příklad je již odlišný od příkladů předchozích, protože zde vybrané uzly sdružujeme do skupin, což je vlastně obdoba clusterů z knihovny Diagrams. Na skupinu se můžeme dívat jako na kontejner pro uzly, které se do skupiny přidávají metodou Add. Skupina je pojmenována, ovšem toto jméno není ve výsledném diagramu zobrazeno:

package main
 
import (
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
        "github.com/blushft/go-diagrams/nodes/apps"
        "github.com/blushft/go-diagrams/nodes/gcp"
)
 
func main() {
        // inicializace objektu představujícího diagram
        diagram4, err := diagram.New(diagram.Label("Diagram #4"), diagram.Filename("diagram4"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // deklarace uzlů v diagramu
        inet := apps.Network.Internet().Label("Internet")
        proxy := apps.Network.Caddy().Label("3scale")
        router := gcp.Network.Router().Label("Router")
 
        diagram4.Group(diagram.NewGroup("Wild west").Add(inet).Add(proxy))
 
        // propojení uzlů v diagramu
        diagram4.Connect(inet, proxy)
        diagram4.Connect(proxy, router)
 
        // vykreslení diagramu
        err = diagram4.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}

Vygenerovaný soubor s definicí grafu v doménově specifickém jazyce DOT:

digraph root {
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=13;
        label="Diagram #4";
        nodesep=0.6;
        pad=2;
        rankdir=LR;
        ranksep=0.75;
        splines=ortho;
        winxwgsu->qbhrmyaa [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        qbhrmyaa->rkhrhwbq [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        subgraph "cluster_Wild west" {
                bgcolor="#E5F5FD";
                fontcolor="#2D3436";
                fontname="Sans-Serif";
                fontsize=12;
                labeljust=l;
                pencolor="#AEB6BE";
                shape=box;
                style=rounded;
                qbhrmyaa [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=2.1999999999999997, image="assets/apps/network/caddy.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
                winxwgsu [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=2.1999999999999997, image="assets/apps/network/internet.png", imagescale=true, label=Internet, labelloc=b, shape=none, style=rounded, width=1.4 ];
        };
        rkhrhwbq [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/gcp/network/router.png", imagescale=true, label=Router, labelloc=b, shape=none, style=rounded, width=1.4 ];
}

Diagram po vykreslení příkazem dot:

Obrázek 9: Diagram po vykreslení příkazem dot.

12. Pojmenování skupiny v diagramu

Dostáváme se k příkladu pátému, který se od příkladu předchozího liší pouze v jediné maličkosti – v přidání štítku (label) do skupiny. Štítek bude zobrazen i ve výsledném diagramu:

diagram5.Group(diagram.NewGroup("Wild west").Label("Wild west").Add(inet).Add(proxy))

Úplný zdrojový kód tohoto příkladu:

package main
 
import (
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
        "github.com/blushft/go-diagrams/nodes/apps"
        "github.com/blushft/go-diagrams/nodes/gcp"
)
 
func main() {
        // inicializace objektu představujícího diagram
        diagram5, err := diagram.New(diagram.Label("Diagram #5"), diagram.Filename("diagram5"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // deklarace uzlů v diagramu
        inet := apps.Network.Internet().Label("Internet")
        proxy := apps.Network.Caddy().Label("3scale")
        router := gcp.Network.Router().Label("Router")
 
        diagram5.Group(diagram.NewGroup("Wild west").Label("Wild west").Add(inet).Add(proxy))
 
        // propojení uzlů v diagramu
        diagram5.Connect(inet, proxy)
        diagram5.Connect(proxy, router)
 
        // vykreslení diagramu
        err = diagram5.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}

Opět si ukažme, jak vypadá soubor vygenerovaný v doménově specifickém jazyku DOT:

digraph root {
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=13;
        label="Diagram #5";
        nodesep=0.6;
        pad=2;
        rankdir=LR;
        ranksep=0.75;
        splines=ortho;
        pmpohiec->tymwuwkk [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        tymwuwkk->juurwdxb [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        subgraph "cluster_Wild west" {
                bgcolor="#E5F5FD";
                fontcolor="#2D3436";
                fontname="Sans-Serif";
                fontsize=12;
                label="Wild west";
                labeljust=l;
                pencolor="#AEB6BE";
                shape=box;
                style=rounded;
                pmpohiec [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=2.1999999999999997, image="assets/apps/network/internet.png", imagescale=true, label=Internet, labelloc=b, shape=none, style=rounded, width=1.4 ];
                tymwuwkk [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=2.1999999999999997, image="assets/apps/network/caddy.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
        };
        juurwdxb [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/gcp/network/router.png", imagescale=true, label=Router, labelloc=b, shape=none, style=rounded, width=1.4 ];
}

Výsledný diagram po vykreslení příkazem dot:

Obrázek 10: Výsledný diagram po vykreslení příkazem dot.

13. Propojení typu 1:N a N:1

V knihovně Diagrams se spojení typu 1:N a N:1 řešilo takovým způsobem, že se uzly uložily do seznamu nebo do n-tice. V případě go-diagrams není řešení tak přímočaré. Jeden z možných způsobů zobrazení spojení 1:N a N:1 spočívá v tom, že všechna tato spojení explicitně zapíšeme do zdrojového kódu s definicí diagramu. Uzly mohou, ale nutně nemusí, být uloženy ve skupině:

diagram6.Connect(inet, proxy1)
diagram6.Connect(inet, proxy2)
diagram6.Connect(inet, proxy3)
 
diagram6.Connect(proxy1, router)
diagram6.Connect(proxy2, router)
diagram6.Connect(proxy3, router)

Celý zdrojový kód tohoto příkladu vypadá následovně:

package main
 
import (
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
        "github.com/blushft/go-diagrams/nodes/apps"
        "github.com/blushft/go-diagrams/nodes/gcp"
        "github.com/blushft/go-diagrams/nodes/generic"
)
 
func main() {
        // inicializace objektu představujícího diagram
        diagram6, err := diagram.New(diagram.Label("Diagram #6"), diagram.Filename("diagram6"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // deklarace uzlů v diagramu
        inet := apps.Network.Internet().Label("Internet")
        proxy1 := generic.Network.Firewall().Label("3scale")
        proxy2 := generic.Network.Firewall().Label("3scale")
        proxy3 := generic.Network.Firewall().Label("3scale")
        router := gcp.Network.Router().Label("Router")
 
        diagram6.Connect(inet, proxy1)
        diagram6.Connect(inet, proxy2)
        diagram6.Connect(inet, proxy3)
 
        diagram6.Connect(proxy1, router)
        diagram6.Connect(proxy2, router)
        diagram6.Connect(proxy3, router)
 
        // vykreslení diagramu
        err = diagram6.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}

Vygenerovaný soubor s popisem diagramu v doménově specifickém jazyce DOT:

digraph root {
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=13;
        label="Diagram #6";
        nodesep=0.6;
        pad=2;
        rankdir=LR;
        ranksep=0.75;
        splines=ortho;
        ddncgkdg->yetpkgzs [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        ddncgkdg->xnbxgnsh [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        ddncgkdg->jubmcseh [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        yetpkgzs->jhvutahu [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        xnbxgnsh->jhvutahu [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        jubmcseh->jhvutahu [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
        ddncgkdg [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/apps/network/internet.png", imagescale=true, label=Internet, labelloc=b, shape=none, style=rounded, width=1.4 ];
        jhvutahu [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/gcp/network/router.png", imagescale=true, label=Router, labelloc=b, shape=none, style=rounded, width=1.4 ];
        jubmcseh [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/generic/network/firewall.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
        xnbxgnsh [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/generic/network/firewall.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
        yetpkgzs [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/generic/network/firewall.png", imagescale=true, label="3scale", labelloc=b, shape=none, style=rounded, width=1.4 ];
}

Výsledný diagram po vykreslení příkazem dot:

Obrázek 11: Výsledný diagram po vykreslení příkazem dot.

14. Programové vytvoření skupiny s vazbami 1:N a N:1

V dnešním posledním demonstračním příkladu je ukázáno, jak je možné vylepšit nutnost přidání několika podobných uzlů do skupiny, typicky se zajištěním napojení typu 1:N a N:1. Nejprve uzly vytvoříme a uložíme je do pole, popř. do řezu (slice):

proxies := make([]*diagram.Node, ProxiesCount)
 
for i := 0; i < ProxiesCount; i++ {
        label := fmt.Sprintf("Proxy #%d", i+1)
        proxies[i] = generic.Network.Firewall().Label(label)
}

Následně vytvoříme skupinu a všechny uzly z pole/řezu do ní přidáme. Navíc metodami pojmenovanými ConnectAllFrom a ConnectAllTo zajistíme propojení všech těchto uzlů s uzlem předcházejícím (vazba 1:N) i uzlem následujícím (vazba N:1):

diagram7.Group(diagram.NewGroup("Proxies").
        Add(proxies...).
        ConnectAllFrom(inet.ID()).
        ConnectAllTo(router.ID()),
)

Úplný zdrojový kód dnešního posledního příkladu vypadá takto:

package main
 
import (
        "fmt"
        "log"
 
        "github.com/blushft/go-diagrams/diagram"
        "github.com/blushft/go-diagrams/nodes/apps"
        "github.com/blushft/go-diagrams/nodes/gcp"
        "github.com/blushft/go-diagrams/nodes/generic"
)
 
const ProxiesCount = 3
 
func main() {
        // inicializace objektu představujícího diagram
        diagram7, err := diagram.New(diagram.Label("Diagram #7"), diagram.Filename("diagram7"))
 
        // kontrola konstrukce objektu
        if err != nil {
                log.Fatal(err)
        }
 
        // deklarace uzlů v diagramu
        inet := apps.Network.Internet().Label("Internet")
 
        proxies := make([]*diagram.Node, ProxiesCount)
 
for i := 0; i < ProxiesCount; i++ {
                label := fmt.Sprintf("Proxy #%d", i+1)
                proxies[i] = generic.Network.Firewall().Label(label)
        }
        router := gcp.Network.Router().Label("Router")
 
        diagram7.Add(inet)
        diagram7.Add(router)
 
        diagram7.Group(diagram.NewGroup("Proxies").
                Add(proxies...).
                ConnectAllFrom(inet.ID()).
                ConnectAllTo(router.ID()),
        )
 
        // vykreslení diagramu
        err = diagram7.Render()
 
        // kontrola, zda bylo vykreslení provedeno bez chyby
        if err != nil {
                log.Fatal(err)
        }
}

Soubor DOT vygenerovaný tímto příkladem:

digraph root {
    fontcolor="#2D3436";
    fontname="Sans-Serif";
    fontsize=13;
    label="Diagram #7";
    nodesep=0.6;
    pad=2;
    rankdir=LR;
    ranksep=0.75;
    splines=ortho;
    zlvpebgu->kjxceadk [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
    ixelswwc->kjxceadk [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
    dpjzrxvm->bxkejjqb [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
    dpjzrxvm->zlvpebgu [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
    dpjzrxvm->ixelswwc [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
    bxkejjqb->kjxceadk [ color="#7B8894", dir=forward, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13 ];
    subgraph cluster_Proxies {
        bgcolor="#E5F5FD";
        fontcolor="#2D3436";
        fontname="Sans-Serif";
        fontsize=12;
        labeljust=l;
        pencolor="#AEB6BE";
        shape=box;
        style=rounded;
        bxkejjqb [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/generic/network/firewall.png", imagescale=true, label="Proxy #1", labelloc=b, shape=none, style=rounded, width=1.4 ];
        ixelswwc [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/generic/network/firewall.png", imagescale=true, label="Proxy #3", labelloc=b, shape=none, style=rounded, width=1.4 ];
        zlvpebgu [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/generic/network/firewall.png", imagescale=true, label="Proxy #2", labelloc=b, shape=none, style=rounded, width=1.4 ];
    };
    dpjzrxvm [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/apps/network/internet.png", imagescale=true, label=Internet, labelloc=b, shape=none, style=rounded, width=1.4 ];
    kjxceadk [ fixedsize=true, fontcolor="#2D3436", fontname="Sans-Serif", fontsize=13, height=1.7999999999999998, image="assets/gcp/network/router.png", imagescale=true, label=Router, labelloc=b, shape=none, style=rounded, width=1.4 ];
}

A konečně toto je podoba výsledného diagramu:

Obrázek 12: Výsledný diagram po vykreslení příkazem dot.

15. Porovnání knihoven Diagrams a go-diagrams

Knihovny Diagrams a go-diagrams jsou sice založeny na podobné filozofii zápisu definice diagramů, ovšem již z předchozích příkladů bylo patrné, jak se obě knihovny od sebe odlišují. Diagrams je – alespoň podle mého názoru – mnohem jednodušeji použitelná a nabízí větší flexibilitu. Výhodou go-diagrams je, alespoň teoreticky, větší typová bezpečnost při deklaraci grafů, ovšem v praxi se ukazuje, že typové kontroly nejsou v tomto případě dokonalé a na chybu se přijde až při volání nástroje dot. Osobně jsem si pro reálné použití vybral Diagrams.

16. Repositář s demonstračními příklady psanými v Pythonu

Zdrojové kódy všech minule i dnes popsaných demonstračních příkladů určených pro Python 3 byly uloženy do Git repositáře dostupného na adrese https://github.com/tisnik/most-popular-python-libs. V případě, že nebudete chtít klonovat celý repositář (ten je ovšem stále velmi malý, dnes má velikost zhruba několik desítek kilobajtů), můžete namísto toho použít odkazy na jednotlivé příklady, které naleznete v následující tabulce:

MIF21_Dolejsova

# Demonstrační příklad Stručný popis příkladu Cesta
1 flowchart1.py jednoduchý vývojový diagram s dvojicí uzlů (počátek a konec zpracování) https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/flow­chart1.py
2 flowchart2.py vývojový diagram s uzly typu Action a InputOutput https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/flow­chart2.py
3 flowchart3.py diagram s nastavenou orientací Top-Bottom https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/flow­chart3.py
4 flowchart4.py přímé zobrazení diagramu po spuštění skriptu https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/flow­chart4.py
       
5 onprem1.py jednoduchá pipeline tvořená Kafkou, workerem naprogramovaným v Go a message brokerem RabbitMQ https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem1.py
6 onprem2.py diagram s větvením a spojením – větší množství workerů https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem2.py
7 onprem2aws.py totožný diagram, ovšem používající odlišné ikony (z AWS) https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/on­prem2aws.py
8 onprem3.py změna orientace předchozího diagramu (shora dolů) https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem3.py
9 onprem3B.py změna orientace předchozího diagramu (zdola nahoru) https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem3B.py
10 onprem4.py složitější pipeline s větším množstvím větvení https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem4.py
11 onprem5.py dvojice zdrojů dat https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem5.py
12 onprem6.py zdroj a cíl dat je tvořen jediným uzlem https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem6.py
13 onprem7.py zjednodušení předchozího diagramu https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem7.py
14 onprem8.py více zdrojů a cílů dat, větší množství workerů https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/onprem8.py
       
15 dx.py složitější diagram s clustery https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/dx.py
       
16 clusters1.py diagram bez clusterů https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/clusters1.py
17 clusters2.py diagram s jedním clusterem https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/clusters2.py
18 clusters3.py diagram se dvěma clustery https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/clusters3.py
19 clusters4.py diagram s hierarchickými clustery https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/clusters4.py
20 clusters5.py diagram s hierarchickými clustery https://github.com/tisnik/most-popular-python-libs/blob/master/diagrams/clusters5.py

17. Repositář s demonstračními příklady psanými v jazyce Go

Budu se částečně opakovat: zdrojové kódy všech dnes použitých demonstračních příkladů vytvořených v jazyce Go byly uloženy do nového Git repositáře, který je dostupný na adrese https://github.com/tisnik/go-root (stále na GitHubu :-). V případě, že nebudete chtít klonovat celý repositář (ten je ovšem – alespoň prozatím – velmi malý, dnes má přibližně stovku kilobajtů), můžete namísto toho použít odkazy na jednotlivé demonstrační příklady, které naleznete v následující tabulce:

# Příklad/soubor Stručný popis Cesta
1 diagram1.go prázdný diagram vytvořený knihovnou go-diagrams https://github.com/tisnik/go-root/blob/master/article74/di­agram1.go
2 diagram2.go diagram s dvojicí uzlů a jednou hranou https://github.com/tisnik/go-root/blob/master/article74/di­agram2.go
3 diagram3.go propojení většího množství uzlů https://github.com/tisnik/go-root/blob/master/article74/di­agram3.go
4 diagram4.go skupiny uzlů v diagramu https://github.com/tisnik/go-root/blob/master/article74/di­agram4.go
5 diagram5.go pojmenování skupiny v diagramu https://github.com/tisnik/go-root/blob/master/article74/di­agram5.go
6 diagram6.go propojení typu 1:N a N:1 https://github.com/tisnik/go-root/blob/master/article74/di­agram6.go
7 diagram7.go programové vytvoření skupiny s vazbami 1:N a N:1 https://github.com/tisnik/go-root/blob/master/article74/di­agram7.go

18. Odkazy na články s tématem programové tvorby grafů a diagramů

V této kapitole jsou uvedeny odkazy na předchozí články, v nichž jsme se zabývali tvorbou různých typů grafů a diagramů – a to v naprosté většině případů s využitím nějakého doménově specifického jazyka neboli DSL (Domain Specific Language), popř. nějakého univerzálního programovacího jazyka:

  1. Nástroje pro tvorbu UML diagramů
    https://www.root.cz/clanky/nastroje-pro-tvorbu-uml-diagramu/
  2. Nástroje pro tvorbu UML diagramů z příkazové řádky
    https://www.root.cz/clanky/nastroje-pro-tvorbu-uml-diagramu-z-prikazove-radky/
  3. Nástroje pro tvorbu UML diagramů z příkazové řádky (II)
    https://www.root.cz/clanky/nastroje-pro-tvorbu-uml-diagramu-z-prikazove-radky-ii/
  4. Nástroje pro tvorbu grafů a diagramů z příkazové řádky
    https://www.root.cz/clanky/nastroje-pro-tvorbu-grafu-a-diagramu-z-prikazove-radky/
  5. Sledování správy paměti v Pythonu s využitím nástroje objgraph
    https://www.root.cz/clanky/sledovani-spravy-pameti-v-pythonu-s-vyuzitim-nastroje-objgraph/
  6. Programová tvorba diagramů v jazyku Clojure s využitím knihovny Rhizome
    https://www.root.cz/clanky/programova-tvorba-diagramu-v-jazyku-clojure-s-vyuzitim-knihovny-rhizome/
  7. Tvorba sekvenčních diagramů v Pythonu s využitím knihovny Napkin
    https://www.root.cz/clanky/tvorba-sekvencnich-diagramu-v-pythonu-s-vyuzitim-knihovny-napkin/
  8. Tvorba vývojových diagramů přímo ze zdrojových kódů Pythonu
    https://www.root.cz/clanky/tvorba-vyvojovych-diagramu-primo-ze-zdrojovych-kodu-pythonu/
  9. Tvorba diagramů s architekturou systémů s využitím knihovny Diagrams
    https://www.root.cz/clanky/tvorba-diagramu-s-architekturou-systemu-s-vyuzitim-knihovny-diagrams/

19. Odkazy na Internetu

  1. Flowchart (Wikipedia)
    https://en.wikipedia.org/wi­ki/Flowchart
  2. DRAKON
    https://en.wikipedia.org/wiki/DRAKON
  3. Modeling language
    https://en.wikipedia.org/wi­ki/Modeling_language
  4. Napkin na GitHubu
    https://github.com/pinetr2e/napkin
  5. Napkin 0.6.8 na PyPi
    https://pypi.org/project/napkin/
  6. PlantUML (home page)
    http://plantuml.sourceforge.net/
  7. PlantUML (download page)
    http://sourceforge.net/pro­jects/plantuml/files/plan­tuml.jar/download
  8. PlantUML (Language Reference Guide)
    http://plantuml.sourcefor­ge.net/PlantUML_Language_Re­ference_Guide.pdf
  9. Rhizome
    https://github.com/ztellman/rhizome
  10. Swagger to UML
    https://github.com/nlohman­n/swagger_to_uml
  11. pydiagrams
    https://github.com/billin­gtonm/pydiagrams
  12. graphviz(3) – Linux man page
    https://linux.die.net/man/3/graphviz
  13. dot(1) – Linux man page
    https://linux.die.net/man/1/dot
  14. neato(1) – Linux man page
    https://linux.die.net/man/1/neato
  15. twopi(1) – Linux man page
    https://linux.die.net/man/1/twopi
  16. circo(1) – Linux man page
    https://linux.die.net/man/1/circo
  17. fdp(1) – Linux man page
    https://linux.die.net/man/1/fdp
  18. sfdp(1) – Linux man page
    https://linux.die.net/man/1/sfdp
  19. Plain-text diagrams take shape in Asciidoctor!
    http://asciidoctor.org/new­s/2014/02/18/plain-text-diagrams-in-asciidoctor/
  20. Graphviz – Graph Visualization Software
    http://www.graphviz.org/
  21. graphviz (Manual Page)
    http://www.root.cz/man/7/graphviz/
  22. dot (Manual page)
    http://www.root.cz/man/1/dot/
  23. dot (Manual v PDF)
    https://graphviz.org/pdf/dot.1.pdf
  24. Ditaa home page
    http://ditaa.sourceforge.net/
  25. Ditaa introduction
    http://ditaa.sourceforge.net/#intro
  26. Ditaa usage
    http://ditaa.sourceforge.net/#usage
  27. Node, Edge and Graph Attributes
    http://www.graphviz.org/doc/in­fo/attrs.html
  28. Graphviz (Wikipedia)
    http://en.wikipedia.org/wiki/Graphviz
  29. Unified Modeling Language
    https://en.wikipedia.org/wi­ki/Unified_Modeling_Langu­age
  30. UML basics: The sequence diagram
    http://www.ibm.com/develo­perworks/rational/library/3101­.html
  31. UML 2 State Machine Diagrams: An Agile Introduction
    http://www.agilemodeling.com/ar­tifacts/stateMachineDiagram­.htm
  32. Sequence diagram (Wikipedia)
    https://en.wikipedia.org/wi­ki/Sequence_diagram
  33. UML 2 Sequence Diagrams: An Agile Introduction
    http://www.agilemodeling.com/ar­tifacts/sequenceDiagram.htm
  34. A Quick Introduction to UML Sequence Diagrams
    http://www.tracemodeler.com/ar­ticles/a_quick_introducti­on_to_uml_sequence_diagram­s/
  35. UML Sequence Diagrams
    https://www.uml-diagrams.org/sequence-diagrams.html
  36. Web Sequence Diagrams
    https://www.websequencediagrams.com/
  37. Drawing sequence diagrams “napkin style”
    https://modeling-languages.com/drawing-sequence-diagrams-napkin-style/
  38. Curated list of UML tools – 2020 edition
    https://modeling-languages.com/uml-tools/#textual
  39. Flowchart diagrams vs. UML activity diagrams
    https://stackoverflow.com/qu­estions/7081215/flowchart-diagrams-vs-uml-activity-diagrams
  40. Kopenograms – Graphical Language for Structured Algorithms
    https://kopenogram.org/As­sets/Kopenograms_Graphical_Lan­guage_for_Structured_Algo­rithms.pdf
  41. Kopenograms and Their Implementation in BlueJ
    https://link.springer.com/chap­ter/10.1007%2F978–3–319–46535–7_8
  42. The simplest way to describe your flows
    https://code2flow.com/
  43. Allan Mogensen and his Legacy
    http://www.worksimp.com/articles/allan-mogensen.htm
  44. Diagrams: Diagram as Code
    https://diagrams.mingrammer.com/
  45. Diagrams: Guides
    https://diagrams.mingrammer­.com/docs/guides/diagram
  46. Diagrams: Nodes
    https://diagrams.mingrammer­.com/docs/nodes/onprem
  47. go-diagrams
    https://github.com/blushft/go-diagrams
  48. GoJS
    https://gojs.net/latest/index.html
  49. Code visualization: How to turn complex code into diagrams
    https://www.lucidchart.com/blog/vi­sualize-code-documentation
  50. Create dependency diagrams from your code
    https://docs.microsoft.com/en-us/visualstudio/modeling/create-layer-diagrams-from-your-code?view=vs-2019
  51. Software Architecture Diagrams as Code
    https://shekhargulati.com/2020/04/21/sof­tware-architecture-diagrams-as-code/
  52. Processing spreadsheet data in Go
    https://appliedgo.net/spreadsheet/
  53. Stránka projektu plotly
    https://plot.ly/
  54. Plotly JavaScript Open Source Graphing Library
    https://plot.ly/javascript/
  55. Domain coloring
    https://en.wikipedia.org/wi­ki/Domain_coloring
  56. The Gonum Numerical Computing Package
    https://www.gonum.org/pos­t/introtogonum/
  57. Gomacro na GitHubu
    https://github.com/cosmos72/gomacro
  58. gophernotes – Use Go in Jupyter notebooks and nteract
    https://github.com/gopher­data/gophernotes
  59. gonum
    https://github.com/gonum
  60. go-gota/gota – DataFrames and data wrangling in Go (Golang)
    https://porter.io/github.com/go-gota/gota
  61. A repository for plotting and visualizing data
    https://github.com/gonum/plot
  62. Gonum Numerical Packages
    https://www.gonum.org/
  63. Getting started with Go modules
    https://medium.com/@fonse­ka.live/getting-started-with-go-modules-b3dac652066d
  64. Create projects independent of $GOPATH using Go Modules
    https://medium.com/mindorks/create-projects-independent-of-gopath-using-go-modules-802260cdfb51o
  65. Anatomy of Modules in Go
    https://medium.com/rungo/anatomy-of-modules-in-go-c8274d215c16
  66. Modules
    https://github.com/golang/go/wi­ki/Modules
  67. Go Modules Tutorial
    https://tutorialedge.net/golang/go-modules-tutorial/
  68. Module support
    https://golang.org/cmd/go/#hdr-Module_support
  69. Go vs. Python
    https://www.peterbe.com/plog/govspy
  70. PackageManagementTools
    https://github.com/golang/go/wi­ki/PackageManagementTools

Autor článku

Pavel Tišnovský vystudoval VUT FIT a v současné době pracuje ve společnosti Red Hat, kde vyvíjí nástroje pro OpenShift.io.