Hlavní navigace

Tvorba vývojových diagramů přímo ze zdrojových kódů Pythonu

20. 5. 2021
Doba čtení: 22 minut

Sdílet

 Autor: Pavel Tišnovský
Ve třetí části miniseriálu o knihovnách pro tvorbu různých grafů a diagramů si představíme knihovnu nazvanou pyflowchart. Už název této knihovny poměrně dobře popisuje její funkci – jedná se totiž o nástroj pro tvorbu vývojových diagramů.

Obsah

1. Tvorba vývojových diagramů přímo ze zdrojových kódů Pythonu

2. Vývojové diagramy – flowcharts

3. Vznik a další rozvoj vývojových diagramů

4. Vývojové diagramy v současnosti

5. Interaktivní a programová tvorba vývojových diagramů

6. Nástroj pyflowchart

7. Vytvoření jednoduchého vývojového diagramu

8. Vstupy a výstupy

9. Rozvětvení ve vývojovém diagramu

10. Složitější rozvětvení

11. Rekurze ve vývojovém diagramu

12. Programové smyčky ve vývojových diagramech

13. Složitější příklad s vnořenými smyčkami a podmínkou

14. Alternativy k vývojovým diagramům

15. Kopenogramy

16. DRAKON-charts

17. „Puzzle“ používané v projektu Scratch a podobných nástrojích

18. Repositář s demonstračními příklady

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

20. Odkazy na Internetu

1. Tvorba vývojových diagramů přímo ze zdrojových kódů Pythonu

V předminulé části miniseriálu o knihovnách určených pro tvorbu grafů a diagramů jsme se seznámili s knihovnou nazvanou Rhizome. Připomeňme si, že tato knihovna je primárně určena pro použití v programovacím jazyku Clojure a umožňuje vytvářet orientované i neorientované grafy, a to přímo na základě jejich deklarace formou mapy (asociativního pole), tedy s využitím základní datové struktury jazyka Clojure. Interně je tato knihovna postavena na nástroji Graphviz, který zajišťuje samotné vykreslení grafu (a to konkrétně s využitím utility nazvané dot). Jedná se tedy o jeden z příkladů grafů, resp. diagramů, pro jejichž definici je použit obecný (v tomto kontextu možná lépe řečeno univerzální) programovací jazyk a nikoli doménově specifický jazyk (DSL), a to se všemi přednostmi a zápory, které toto řešení přináší.

Obrázek 1: Graf vykreslený s využitím nástroje Rhizome.

Minule byl naproti tomu popsán nástroj pojmenovaný Napkin. Ten byl určen pro tvorbu a vykreslení takzvaných sekvenčních diagramů, což je jeden z typů diagramů definovaných v rámci jazyka UML (Unified Modeling Language). Tento nástroj je určen pro použití v jazyku Python a pro vykreslení diagramů používá známou a poměrně často využívanou utilitu PlantUML, která může být volána buď lokálně (pokud je nainstalována), nebo lze využít API veřejného serveru, na je němž PlantUML nabízen formou služby. Opět platí – namísto doménově specifického jazyka jsou v tomto případě sekvenční diagramy definovány přímo v Pythonu s využitím některých vlastností tohoto jazyka. Zejména se jedná o použití dekorátorů a taktéž o blokové kontexty představované programovým blokem with.

Obrázek 2: Diagram s přidanými poznámkami vytvořený nástrojem Napkin.

2. Vývojové diagramy – flowcharts

V dnešním článku se zaměříme na další typ diagramů; konkrétně se jedná o vývojové diagramy neboli flowcharts. Tento typ diagramů, který je všeobecně známý a poměrně snadno pochopitelný i nevývojáři, se používá pro popis toku (flow) operací ve znázorněném algoritmu. Algoritmus je rozdělen na jednotlivé kroky, popř. operace, přičemž se na základě typu operace používá odlišný tvar uzlu, který tuto operaci ve vývojovém diagramu reprezentuje. Některé aplikace určené pro tvorbu vývojových diagramů navíc dokážou typ operace rozlišit i barvou pozadí uzlu, což dále přispívá k přehlednosti reprezentace. Uzly jsou propojeny šipkami, které naznačují tok (flow) programu (jedná se tedy o formu orientovaného grafu). V případě, že se šipky kříží, nepoužívá se (alespoň většinou) žádný specifický tvar, který křížení naznačuje (některé aplikace ovšem v tomto případě nakreslí „mostky“ tak, jak je tomu zvykem v UML).

Otcové vývojových diagramů.

Poznámka: to, jaké operace jsou ve vývojovém diagramu popsány, záleží na konkrétním použití. Na jedné straně může být operace velmi nízkoúrovňová („přičti k proměnné i jedničku“), ovšem taktéž se může jednat o interně složitou operaci („vyskladni zboží“). Lze se setkat, i když to není příliš časté, i s hierarchickými vývojovými diagramy, kdy jsou jednotlivé podprogramy (pro ty existuje speciální typ uzlu) rozepsány do větších podrobností v dalším (pod)diagramu.

Obrázek 3: Typický vývojový diagram s barevně zvýrazněnými uzly.
Autor: Booyabazooka

3. Vznik a další rozvoj vývojových diagramů

Vývojové diagramy byly velmi populární především v minulosti, konkrétně v padesátých letech minulého století, kdy se programy vytvářely buď v takzvaném autokódu nebo v assembleru (za jejich vznik vděčíme Franku Gilbrethovi). Tyto vývojářské prostředky jsou sice vhodné pro zápis implementací algoritmů, ovšem nikoli už pro jejich návrh, popř. pro prezentaci. A právě z tohoto důvodu se algoritmy na začátku vývoje nejdříve popsaly vývojovým diagramem a teprve poté byly skutečně implementovány. Přitom popis složitých programů mohl zabrat několik desítek a mnohdy i stovek stran s vývojovými diagramy (resp. jejich částmi propojenými s využitím spojovacích „koleček“). Takto použité vývojové diagramy byly mnohdy strukturovány hierarchicky – nejdříve byla aplikace popsána na nejvyšším stupni abstrakce a poté byly rozpracovány jednotlivé části aplikace popsané formou procedur (resp. přesněji řečeno podprogramů) – to ostatně dobře korespondovalo i se způsobem implementace v konkrétním programovacím jazyce (snad s výjimkou jednoduchých BASICů nepodporujících procedury).

Poznámka: Frank Gilbreth ve skutečnosti pracoval s nepatrně odlišnými diagramy známými pod jménem flow process charts, viz též https://en.wikipedia.org/wi­ki/Flow_process_chart. Tyto diagramy byly později upraveny pro potřeby informatiky.
flow-rule

Obrázek 4: Základní pomůcky programátorů před vznikem a rozšířením vyšších programovacích jazyků – šablona pro tvorbu vývojových diagramů a tabulka kódů znaků.

Poznámka: vývojové diagramy se používaly i později, sloužily například i při výuce algoritmizace, a to předtím, než byly vyvinuty, resp. v našem prostředí než začaly být dostupné vysokoúrovňové programovací jazyky. Nicméně stále se jednalo popis algoritmu v naprosté většině případů zcela oddělený od jeho implementace, tj. mezi vývojovým diagramem a (ekvivalentním) zdrojovým kódem nebyly vytvořeny automatické vazby zajištěné například nějakým překladačem či transformátorem kódu.

4. Vývojové diagramy v současnosti

Ve skutečnosti se s vývojovými diagramy se setkáme i v současnosti, kdy se mohou používat pro popis chování složitějších aplikací, popř. naopak dobře izolovaných algoritmů („školním“ příkladem jsou vývojové diagramy popisující algoritmy pro vyhledávání prvků v poli, popř. pro seřazení prvků v poli). Takto pojaté vývojové diagramy už nemusí sloužit (a mnohdy ani neslouží) jako „předpis“, kterého se musí programátoři držet při přepisu algoritmu do konkrétního programovacího jazyka (což bylo používáno v padesátých a šedesátých letech minulého století; v ČSSR i později). Spíše se tyto vývojové diagramy používají pro lepší pochopení algoritmu, který je abstrahován od skutečné implementace (a ta je mnohdy „zaneřáděna“ nízkoúrovňovými operacemi – zpracováním výjimek, typovými deklaracemi, deklaracemi proměnných, nízkoúrovňovými programovými smyčkami atd. – jen malé množství jazyků dokáže dobře oddělit různé úrovně abstrakce).

Poznámka: zajímavé je, že se vývojové diagramy nestaly součástí standardu UML. I v UML sice nalezneme podobně koncipované diagramy, například diagram aktivit a stavový diagram, popř. diagram interakcí,ovšem ty nejsou plnohodnotnou náhradou vývojových diagramů. Podobně v UML nenajdeme plnohodnotnou náhradu za DFD apod.

Obrázek 5: Diagram aktivit (UML) vykreslený nástrojem PlantUML.

5. Interaktivní a programová tvorba vývojových diagramů

Vývojové diagramy lze vytvářet v různých grafických editorech, a to jak editorech realizovaných formou desktopové aplikace (Flowgorithm), tak i v editorech, které jsou dostupné formou webové aplikace (Flowchart Maker, https://app.diagrams.net/ atd.). Existují i specifikace doménově specifických jazyků, které jsou určeny pro popis vývojových diagramů v textové podobě. Nicméně existuje ještě jeden elegantní způsob výroby vývojového diagramu. Ten je založen – což může zpočátku vypadat poněkud paradoxně – na zápisu algoritmu v Pythonu, z něhož se posléze diagram vygeneruje. Musíme si ovšem uvědomit, že Python je skutečně vysokoúrovňovým jazykem, který je pro popis algoritmů na libovolné (zvolené) úrovni abstrakce takřka ideální – až na absenci některých programových konstrukcí popsatelných vývojovým diagramem (zejména chybí programová smyčka typu repeat-until, tedy smyčka s testem prováděným za koncem těla smyčky).

Obrázek 6: Ukázkový vývojový diagram otevřený v online nástroji https://app.diagrams.net.

6. Nástroj pyflowchart

Nástroj pyflowchart, jímž se budeme zabývat v navazujících kapitolách, dokáže vytvořit vývojové diagramy ze zdrojových kódů Pythonu. Instalace tohoto nástroje je, podobně jako v případě minule popsaného Napkinu, snadná a přímočará:

$ pip3 install --user pyflowchart
 
Collecting pyflowchart
  Downloading https://files.pythonhosted.org/packages/64/b6/65bb0ca47e55bfa09f1246e2cc0994f6e682c2e13344211f2b2ead57e147/pyflowchart-0.1.3-py3-none-any.whl
Requirement already satisfied: astunparse in ./.local/lib/python3.6/site-packages (from pyflowchart)
Requirement already satisfied: chardet in /usr/lib/python3.6/site-packages (from pyflowchart)
Requirement already satisfied: six<2.0,>=1.6.1 in ./.local/lib/python3.6/site-packages (from astunparse->pyflowchart)
Requirement already satisfied: wheel<1.0,>=0.23.0 in ./.local/lib/python3.6/site-packages (from astunparse->pyflowchart)
Installing collected packages: pyflowchart
Successfully installed pyflowchart-0.1.3

Otestujeme, zda se pyflowchart nainstaloval korektně a zda je dostupný:

$ python3 -m pyflowchart -h
 
usage: __main__.py [-h] [-f FIELD] [-i] [--no-simplify] code_file
 
Python code to flowchart.
 
positional arguments:
  code_file
 
optional arguments:
  -h, --help            show this help message and exit
  -f FIELD, --field FIELD
                        field to draw flowchart. (e.g. Class.method)
  -i, --inner           parse the body of field
  --no-simplify         do not simplify the one-line-body If/Loop

7. Vytvoření jednoduchého vývojového diagramu

V praktické části článku si nejprve ukážeme vytvoření jednoduchého vývojového diagramu. Ten bude založen na následujícím skriptu, který pravděpodobně nepotřebuje podrobnější rozbor:

import math
 
r = float(input("Polomer= "))
obvod = 2*math.pi*r
print("Obvod=", obvod)

Z tohoto skriptu vytvoříme definiční soubor s vývojovým diagramem (psaným v DSL) takto:

$ python3 -m pyflowchart kruh.py > kruh.flow

Výsledný soubor pojmenovaný „kruh.flow“ bude mít tento obsah:

op140390441087272=>operation: import math
op140390441087328=>operation: r = float(input('Polomer= '))
op140390441087440=>operation: obvod = ((2 * math.pi) * r)
sub140390441087944=>subroutine: print('Obvod=', obvod)
 
op140390441087272->op140390441087328
op140390441087328->op140390441087440
op140390441087440->sub140390441087944
Poznámka: nejedná se o příliš čitelný soubor, ale to jen kvůli tomu, že nástroj pyflowchart generuje jména jednotlivých uzlů v diagramu automaticky. To lze napravit běžným grepem (pokud je zapotřebí sdílet i tento soubor).

V dalším kroku již můžeme vytvořit grafickou podobu vývojového diagramu. K tomuto účelu lze použít buď lokálně nainstalovanou utilitu flowchart.js (přes Node atd.), nebo lze obsah souboru přenést na stránku http://flowchart.js.org/ a nechat si graf vygenerovat přímo na této stránce. Podle toho, jaký styl diagramu zvolíte může výsledek vypadat takto:

Obrázek 7: Vývojový diagram algoritmu pro výpočet obsahu kruhu.

Či takto:

Obrázek 8: Alternativní podoba vývojového diagramu algoritmu pro výpočet obsahu kruhu..

8. Vstupy a výstupy

Nástroj pyflowchart nedokáže (prozatím?) rozlišit ty příkazy, které představují vstupní a výstupní operace. Tento nedostatek lze nahradit ruční úpravou vygenerovaného souboru kruh.flow vytvořeného v rámci předchozí kapitoly. Uzel představující vstup nebo výstup je v popisu vývojového diagramu reprezentován klíčovým slovem inputoutput, takže úprava může vypadat následovně:

op140347960709304=>operation: import math
op140347960709360=>inputoutput: r = float(input('Polomer= '))
op140347960709472=>operation: obvod = ((2 * math.pi) * r)
sub140347960709976=>inputoutput: print('Obvod=', obvod)
 
op140347960709304->op140347960709360
op140347960709360->op140347960709472
op140347960709472->sub140347960709976

Grafickou podobu diagramu si můžeme opět nechat vygenerovat, nyní s tímto výsledkem:

Obrázek 9: Vývojový diagram algoritmu pro výpočet obsahu kruhu se vstupy a výstupy.

Alternativní podoba výstupu:

Obrázek 10: Alternativní podoba vývojového diagramu algoritmu pro výpočet obsahu kruhu..

9. Rozvětvení ve vývojovém diagramu

Jeden z důvodů vzniku vývojových diagramů byla potřeba vyjádřit rozvětvení toku v algoritmu. To je operace, která je pochopitelně nástrojem pyflowchart podporována. Vyzkoušíme si ji na jednoduchém rozvětvení:

x = int(input("x="))
if x > 0:
    print("Kladne")
else:
    print("Nulove nebo zaporne")

Transformací výše uvedeného kódu do DSL vznikne tento popis vývojového diagramu:

op139761666391960=>operation: x = input('x=')
cond139761665941856=>condition: if (x > 0)
sub139761665942248=>subroutine: print('Kladne')
sub139761665942360=>subroutine: print('Nulove nebo zaporne')
 
op139761666391960->cond139761665941856
cond139761665941856(yes)->sub139761665942248
cond139761665941856(no)->sub139761665942360

Po jeho zobrazení je patrné, že je rozvětvení skutečně zakresleno korektně (a dokonce i relativně přehledným způsobem):

Obrázek 11: Rozvětvení ve vývojovém diagramu.

10. Složitější rozvětvení

Ve většině algoritmů se pochopitelně provádí složitější rozvětvení realizované například následovně (jedná se o poněkud umělý příklad, který by šel řešit i kratším kódem):

x = int(input("x="))
if x > 0:
    print("Kladne")
else:
    if x < 0:
        print("Zaporne")
    else:
        print("Nulove")

Výsledek transformace tohoto programového kódu do DSL určeného pro popis vývojových diagramů:

op140193708249720=>operation: x = int(input('x='))
cond140193708249776=>condition: if (x > 0)
sub140193708250504=>subroutine: print('Kladne')
cond140193708693040=>condition: if (x < 0)
sub140193708693208=>subroutine: print('Zaporne')
sub140193708250672=>subroutine: print('Nulove')
 
op140193708249720->cond140193708249776
cond140193708249776(yes)->sub140193708250504
cond140193708249776(no)->cond140193708693040
cond140193708693040(yes)->sub140193708693208
cond140193708693040(no)->sub140193708250672

Obrázek 12: Složitější rozvětvení ve vývojovém diagramu.

11. Rekurze ve vývojovém diagramu

Specifikace rekurzivního výpočtu je relativně snadná, protože pro rekurzi se používá volání nějaké funkce, které je nástrojem pyflowchart korektně rozpoznáno. Tuto funkcionalitu si otestujeme na výpočtu faktoriálu rekurzivní metodou (tedy tou nejméně efektivní); navíc jsou do skriptu přidány testy na neočekávané hodnoty, což výsledný vývojový diagram poněkud zesložiťuje:

"""Výpočet faktoriálu."""
 
def factorial(n):
    if n is None:
        return None
    if n < 0:
        return None
    if n == 0:
        return 1
 
    r = factorial(n-1)
 
    if r is None:
        return None
    return n * r

Výsledek transformace programového kódu do DSL:

op140142231253904=>operation: 'Výpočet faktoriálu.'
st140142231254128=>start: start factorial
io140142231253960=>inputoutput: input: n
cond140142231254464=>condition: if (n is None)
io140142231254576=>inputoutput: output:  None
e140142231254968=>end: end function return
cond140142231255024=>condition: if (n < 0)
io140142231254688=>inputoutput: output:  None
e140142231254744=>end: end function return
cond140142231255472=>condition: if (n == 0)
io140142231255136=>inputoutput: output:  1
e140142231255808=>end: end function return
op140142231255080=>operation: r = factorial((n - 1))
cond140142231255864=>condition: if (r is None)
io140142231255192=>inputoutput: output:  None
e140142231255640=>end: end function return
io140142231256256=>inputoutput: output:  (n * r)
e140142231256480=>end: end function return
 
op140142231253904->st140142231254128
st140142231254128->io140142231253960
io140142231253960->cond140142231254464
cond140142231254464(yes)->io140142231254576
io140142231254576->e140142231254968
cond140142231254464(no)->cond140142231255024
cond140142231255024(yes)->io140142231254688
io140142231254688->e140142231254744
cond140142231255024(no)->cond140142231255472
cond140142231255472(yes)->io140142231255136
io140142231255136->e140142231255808
cond140142231255472(no)->op140142231255080
op140142231255080->cond140142231255864
cond140142231255864(yes)->io140142231255192
io140142231255192->e140142231255640
cond140142231255864(no)->io140142231256256
io140142231256256->e140142231256480

Výsledný vývojový diagram bude v tomto případě vypadat následovně:

Obrázek 13: Rekurze ve vývojovém diagramu.

12. Programové smyčky ve vývojových diagramech

Kromě rozvětvení a rekurze je nutné umět ve vývojovém diagramu naznačit programovou smyčku. I to je pochopitelně možné, i když níže uvedené řešení nepodporuje nové tvary uzlů pro programové smyčky (ty byly přidány až po vzniku a rozšíření strukturovaného programování). Základním typem smyčky je smyčka typu while. Tu si otestujeme na algoritmu pro výpočet největšího společného dělitele (GCD):

x = int(input("x= "))
y = int(input("y= "))
 
while x != y:
    if x > y:
        x = x - y
    if x < y:
        y = y - x
 
print("gcd=", x)

Takto zapsaná programová smyčka se do vývojového diagramu převede následujícím způsobem:

op140393552635328=>operation: x = int(input('x= '))
op140393553074048=>operation: y = int(input('y= '))
cond140393553074608=>condition: while (x != y)
cond140393552635776=>operation: x = (x - y) if  (x > y)
cond140393552636448=>operation: y = (y - x) if  (x < y)
sub140393553073992=>subroutine: print('gcd=', x)
 
op140393552635328->op140393553074048
op140393553074048->cond140393553074608
cond140393553074608(yes)->cond140393552635776
cond140393552635776->cond140393552636448
cond140393552636448->cond140393553074608
cond140393553074608(no)->sub140393553073992

A výsledný diagram bude vykreslen tímto způsobem:

Obrázek 14: Programová smyčka ve vývojovém diagramu.

13. Složitější příklad s vnořenými smyčkami a podmínkou

Ukažme si nyní poněkud složitější algoritmus, v němž jsou použity vnořené smyčky a navíc je ve vnitřní smyčce ještě zapsána podmínka. Jedná se o „školní“ implementaci řadícího algoritmu bubble sort (resp. o jednu z jeho mnoha variant):

import random
 
size = 40
 
a = [random.randrange(0, 20) for i in range(size)]
print(a)
 
for i in range(size-1, 0, -1):
    print(i)
    for j in range(0, i):
        if a[j] > a[j+1]:
            a[j], a[j+1] = a[j+1], a[j]
 
print("Sorted")
print(a)
Poznámka: povšimněte si způsobu vytvoření seznamu s využitím techniky známé pod jménem list comprehension.

Popis vývojového diagramu v DSL:

op140323499932864=>operation: import random
op140323499932920=>operation: size = 40
op140323499933312=>operation: a = [random.randrange(0, 20) for i in range(size)]
sub140323499933200=>subroutine: print(a)
cond140323499933648=>condition: for i in range((size - 1), 0, (- 1))
sub140323499918392=>subroutine: print(i)
cond140323499918168=>condition: for j in range(0, i)
cond140323499919680=>operation: (a[j], a[(j + 1)]) = (a[(j + 1)], a[j]) if  (a[j] > a[(j + 1)])
sub140323499933424=>subroutine: print('Sorted')
sub140323499933032=>subroutine: print(a)
 
op140323499932864->op140323499932920
op140323499932920->op140323499933312
op140323499933312->sub140323499933200
sub140323499933200->cond140323499933648
cond140323499933648(yes)->sub140323499918392
sub140323499918392->cond140323499918168
cond140323499918168(yes)->cond140323499919680
cond140323499919680->cond140323499918168
cond140323499918168(no)->cond140323499933648
cond140323499933648(no)->sub140323499933424
sub140323499933424->sub140323499933032

Výsledek je zajímavý tím, že se v něm podmínka nerozepsala na rozhodovací uzel, a to kvůli větší přehlednosti:

Obrázek 15: Vnořené programové smyčky ve vývojovém diagramu; první varianta.

V případě, že vám toto chování nevyhovuje, lze použít přepínač –no-simplify:

$ python3 -m pyflowchart --no-simplify bubble_sort.py > bubble_sort2.flow

Nyní bude výsledný diagram vypadat takto:

Obrázek 16: Vnořené programové smyčky ve vývojovém diagramu; druhá varianta.

Poznámka: zde se již začínají ukazovat omezení na straně renderovací/vykreslovací části.

14. Alternativy k vývojovým diagramům

Na závěr dnešního článku je vhodné se zmínit i o některých alternativách k vývojovým diagramům. Jak jsme si již řekli v úvodních kapitolách, slouží vývojové diagramy k popisu algoritmů či jejich částí a s využitím nástroje pyflowchart je zajištěna jednosměrná vazba Python → vývojový diagram. Ovšem ve skutečnosti se nejedná o plnohodnotnou oboustrannou vazbu, kdy by se například změna ve vývojovém diagramu automaticky promítla v Pythonovském kódu (ovšem i takové nástroje existují – například Flowgorithm). Navíc je kreslení a zejména případná editace vývojového diagramu relativně složitá a vyžaduje velké množství času.

A konečně – vývojové diagramy jsou dosti náročné na zabranou plochu papíru či obrazovky, a to kvůli tomu, že jednotlivé bloky je nutné mnohdy poměrně složitě spojovat (mezi jednotlivými šipkami je vhodné ponechat relativně velké mezery, jinak nebude diagram přehledný) a do jisté míry i kvůli tomu, že podmínky (a kvůli nim se mnohdy vývojové diagramy používají primárně) jsou reprezentovány kosočtverci, které zabírají velkou plochu, ale současně nenabízí dostatek místa pro zápis podmínky.

Existují ovšem i další způsoby grafického vyjádření nějakého algoritmu. Některé z alternativ jsou spíše staršího data, jiné jsou naopak poměrně moderní a jsou navrženy takovým způsobem, aby byla zajištěna interakce uživatele se vznikajícím algoritmem.

15. Kopenogramy

Alespoň ve stručnosti se musíme zmínit o takzvaných kopenogramech. Jedná se o alternativu ke klasickým vývojovým diagramům; zajímavé přitom je, že první verze kopenogramů vznikla v Československu a jejími autory jsou Jiří Kofránek, Rudolf Pecinovský a Petr Novák. Ostatně ze jmen autorů je odvozen i název kopenogram: KOfránek PEcinovský NOvák grams (dnes se ovšem tento název vysvětluje jako zkratka z „Keep Our Program in Embedded Noted Oblongs for Graphical Representation of Algorithmic Modules“). Kopenogramy existovaly v několika variantách; pravděpodobně poslední (nejbarevnější) varianta je popsána v článku Kopenograms – Graphical Language for Structured Algorithms. Od vývojových diagramů se kopenogramy odlišují v mnoha ohledech, především rozdílnou reprezentací podmínek a smyček – vyjádření těchto částí algoritmu je stručnější, i když čtení může být (zejména zpočátku) složitější.

Obrázek 17: Příklad kopenogramu se smyčkou, v níž je použit příkaz break.
Převzato z článku Kopenograms – Graphical Language for Structured Algorithms

16. DRAKON-charts

Další rozšíření vývojových diagramů bylo použito ve velmi zajímavém projektu – při programování sovětského raketoplánu Buran. Jednalo se o jazyk pojmenovaný DRAKON, který lze použít jak pro modelování, tak i pro vlastní vývoj. Jméno tohoto jazyka znamená v azbuce „Дружелюбный Русский Алгоритмический [язык], Который Обеспечивает Наглядность“, neboli velmi volně přeloženo „(uživatelsky) přátelský ruský algoritmický jazyk, s vysokou názorností (přehledností)“. V DRAKONu lze vyjádřit rozeskoky, programové smyčky s testem na začátku i na konci atd. Na následujícím obrázku je patrné, že se jedná o vylepšenou alternativu ke klasickým vývojovým diagramům

Obrázek 18: Algoritmus vyjádřený v diagramu typu DRAKON.
Autor: Mitkin
Originál: https://en.wikipedia.org/wi­ki/File:A*_in_DRAKON.png

17. „Puzzle“ používané v projektu Scratch a podobných nástrojích

Asi nejdále byla původní myšlenka vývojových diagramů dotažena v projektu Scratch a podobných nástrojích, které se tímto projektem nechaly následně inspirovat. Ve Scratchi se program skládá z přikazových bloků, které se spojují systémem známým z puzzle – s využitím „výčnělků“ na okrajích lze tedy jednoznačně určit, které bloky jdou spojit a které nikoli. Běžný příkazový blok je vizuálně představován obdélníkem s několika výčnělky připomínajícími puzzle. Programové smyčky a podmínky jsou vyobrazeny jako složitější tvary umožňující vkládání dalších bloků dovnitř svého těla. Pomocí těchto výčnělků se bloky spojují dohromady tak, aby tvořily sekvenci či dokonce strukturovaný program. V případě, že je zapotřebí sekvenci příkazů změnit, je možné bloky od sebe rozdělit, popř. vybraný blok smazat (přes menu zobrazené po stisku pravého tlačítka myši), zkopírovat (opět přes pravé tlačítko myši) či přesunout. Výsledný vizuální návrh algoritmu bývá (co se týká plochy) menší, než je tomu u vývojového diagramu, na druhou stranu však není dobře možné některé části zvýraznit o oddělit od částí ostatních.

scratch

Obrázek 19: Ukázka využití nekonečné programové smyčky použité při popisu chování spritu, který se má po každém nárazu na stěnu nakreslenou červenou barvou otočit zpět směrem ke středu „ohrady“.

scratch2

Obrázek 20: Ukázka použití počítané programové smyčky ve Scratchi.

Nástrojem Scratch a od něj odvozených projektů jsme se na Rootu poměrně podrobně zabývali v následujících článcích:

  1. Scratch: plnohodnotný programovací jazyk nebo jen dětské puzzle?
    https://www.root.cz/clanky/scratch-plnohodnotny-programovaci-jazyk-nebo-jen-detske-puzzle/
  2. Scratch: plnohodnotný programovací jazyk nebo jen dětské puzzle? (2. část)
    https://www.root.cz/clanky/scratch-plnohodnotny-programovaci-jazyk-nebo-jen-detske-puzzle-2-cast/
  3. Scratch – plnohodnotný programovací jazyk nebo jen dětské puzzle? (3. část: Scratch a BYOB)
    https://www.root.cz/clanky/scratch-plnohodnotny-programovaci-jazyk-nebo-jen-detske-puzzle-3-cast-scratch-a-byob/
  4. Scratch – plnohodnotný programovací jazyk nebo jen dětské puzzle? (4. část: pokročilá práce s BYOB)
    https://www.root.cz/clanky/scratch-plnohodnotny-programovaci-jazyk-nebo-jen-detske-puzzle-4-cast-pokrocila-prace-s-byob/
  5. Scratch – plnohodnotný programovací jazyk nebo jen dětské puzzle? (5. část: projekt Panther)
    https://www.root.cz/clanky/scratch-plnohodnotny-programovaci-jazyk-nebo-jen-detske-puzzle-5-cast-projekt-panther/
  6. Snap! – důstojný nástupce programovacího jazyka Scratch
    https://www.root.cz/clanky/snap-dustojny-nastupce-programovaciho-jazyka-scratch/
scratch3

Obrázek 21: Použití programové smyčky typu repeat-until pro počítání od nuly do devíti.

scratch4

Obrázek 22: Příklad použití příkazového bloku if-then-else.

Linux tip

18. Repositář s demonstračními příklady

Zdrojové kódy všech 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:

# Demonstrační příklad Stručný popis příkladu Cesta
1 kruh.py výpočet obvodu kruhu https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchart/kruh.py
2 kruh.flow převod algoritmu do DSL pro popis vývojových diagramů https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchart/kruh.flow
       
3 cislo1.py jednoduché rozvětvení https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchart/cislo1.py
4 cislo1.flow převod algoritmu do DSL pro popis vývojových diagramů https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/cislo1.flow
       
5 cislo2.py složitější rozvětvení https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchart/cislo2.py
6 cislo2.flow převod algoritmu do DSL pro popis vývojových diagramů https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/cislo2.flow
       
7 factorial.py rekurze https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/factorial.py
8 factorial.flow převod algoritmu do DSL pro popis vývojových diagramů https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/factorial.flow
       
9 gcd.py programová smyčka https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchart/gcd.py
10 gcd.flow převod algoritmu do DSL pro popis vývojových diagramů https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchart/gcd.flow
       
11 bubble_sort.py vnořené smyčky a podmínka https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/bubble_sort.py
12 bubble_sort.flow převod algoritmu do DSL pro popis vývojových diagramů https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/bubble_sort.flow
13 bubble_sort2.flow převod algoritmu do DSL pro popis vývojových diagramů, alternativní varianta https://github.com/tisnik/most-popular-python-libs/blob/master/pyflowchar­t/bubble_sort2.flow

19. 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/

20. 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/

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.