Zachovávám starou kódovou základnu napsanou v pythonu. Zejména existuje komplexní část kódu, která z modulu volá další funkce z jiných modulů, které volají jiné funkce atd. Nejedná se o OOP, pouze o funkce a moduly.
Snažil jsem se sledovat, kde tok začíná a končí, kdykoli zavolám hlavní funkci, ale mám pocit, že musím kreslit to proto, že se ztrácím v dílčích hovorech.
Co se mě týká, je, že každá funkce volá více externích funkcí v rámci svého těla, aby dokončila svůj úkol a vrátila hodnotu volajícímu.
Jak to mohu nakreslit? Znamená to, jaký druh grafu / grafiky by bylo vhodné dokumentovat tento druh chování / kódu?
Takže si nemyslím, že by bylo užitečné nakreslit diagram UML , ani vývojový diagram. Možná graf volání?
Komentáře
- doxygen – vygeneruje grafy volajícího / volajícího, I ' nejsem si jistý, jak velkou podporu má pro python. Vím, že pro to můžete zdokumentovat kód v pythonu.
- Zkoušel jsem pycallgraph, ale ' i, ale ' to prostě taky komplikované / příliš hluboké na to, aby to bylo možné použít. Je to kvůli složitosti mého kódu, protože se v něm mísí prostý python s django a externí volání na adresu URL API. Proto jsem to chtěl nakreslit ručně pouze s přihlédnutím k příslušné části, kterou potřebuji. Problém je v tom, že ' nevím, jaký druh grafu použít, abych systému plně porozuměl
- Pokud vám to má pomoci pochopit , stačí nakreslit, co přijde přirozeně. Kdykoli to můžete uklidit, pokud ' jde do formální dokumentace.
Odpovědět
Myslím, že to, co zde hledáte, je Sekvenční diagram . Ty vám umožní vizualizovat pořadí, v jakém různé moduly volají přicházejí do styku pomocí šipek.
Vytvoření jedné je jednoduché:
- Nakreslete svou výchozí třídu tečkovanou čarou pod ní.
- Nakreslete další třída / metoda v trasování volání s tečkovanou čarou pod tím
- Spojte linky šipkou, svisle umístěnou pod poslední nakreslenou šipkou
- Opakujte kroky 2-3 pro všechna volání ve vaší stopě
Příklad
Předpokládejme, že máme následující kód, pro který chceme vytvořit sekvenční diagram:
def long_division(quotient, divisor): solution = "" remainder = quotient working = "" while len(remainder) > 0: working += remainder[0] remainder = remainder[1:] multiplier = find_largest_fit(working, divisor) solution += multiplier working = calculate_remainder(working, multiplier, divisor) print solution def calculate_remainder(working, multiplier, divisor): cur_len = len(working) int_rem = int(working) - (int(multiplier) * int (divisor)) return "%*d" % (cur_len, int_rem) def find_largest_fit(quotient, divisor): if int(divisor) == 0: return "0" i = 0 while i <= 10: if (int(divisor) * i) > int(quotient): return str(i - 1) else: i += 1 if __name__ == "__main__": long_division("645", "5")
První věc, kterou nakreslíme, je vstupní bod (main
) připojující se k metodě long_division
. Všimněte si, že tím vytvoříte pole v long_ rozdělení, označující rozsah volání metody. V tomto jednoduchém příkladu bude rámeček celá výška našeho sekvenčního diagramu, protože jde o jedinou věc, kterou lze spustit.
Nyní voláme find_largest_fit
, abychom našli největší násobek, který se vejde do našeho pracovního čísla a vrátí nám jej. Nakreslíme čáru od long_division
do find_largest_fit
s dalším polem, které označuje rozsah volání funkce. Všimněte si, jak pole končí, když je multiplikátor vrácen; toto je konec rozsahu této funkce!
Několikrát opakujte pro větší počet a váš graf by měl vypadat asi takto:
Poznámky
Můžete si vybrat, zda chcete označit volání předanými názvy proměnných, nebo jejich hodnotami, pokud chcete pouze zdokumentovat jeden konkrétní případ. Můžete také ukázat rekurzi s funkcí, která se sama volá.
Dále zde můžete ukázat uživatelům a vyzvat je a dostatečně snadno ukázat jejich vstup do systému. Je to docela flexibilní systém, o kterém si myslím, že vás bude považovat za docela užitečný!
Komentáře
- Díky, znám sekvenční diagram, ale má pocit, že je to vhodnější pro oop. V mém případě jsou věci trochu špinavější, což znamená, že například mám kolem 20 funkcí / pomocníků rozložených kolem více modulů. Ho bych specifikovat modul, který funkce patří? Vzhledem k tomu, že některé funkce jsou během importu také přejmenovány.
- Řekl bych, že nezáleží na tom, kolik modulů máte – výše uvedený příklad vůbec není. Stačí je pojmenovat, abyste je mohli najít později, ModuleA / function1, ModuleB / Function2 atd. Pro 20 funkcí to bude větší, ale rozhodně není nemožné to pochopit. Další věc, kterou můžete udělat, je ukončit řádek funkce po jejím posledním použití a umístit pod ni další řádek funkcí, aby se ve vašem diagramu ušetřil horizontální prostor.
Odpovědět
Myslím, že graf volání by byl nejvhodnější vizualizací.Pokud se rozhodnete to nedělat ručně, existuje pěkný malý nástroj s názvem pyan
, který provádí statickou analýzu souboru pythonu a může vygenerovat vizualizovaný graf volání pomocí tečky graphviz soubor (který lze vykreslit na obrázek). Vyskytlo se několik vidlic, ale nejvíce plně vybavený se zdá být https://github.com/davidfraser/pyan .
Při spuštění příkazu stačí zadat všechny soubory, které chcete zpracovat:
python ~/bin/pyan.py --dot a.py b.py c.py -n > pyan.dot; dot -Tpng -opyan.png pyan.dot
nebo
python ~/bin/pyan.py --dot $(find . -name "*.py") -n > pyan.dot; dot -Tpng -opyan.png pyan.dot
Graf můžete vyčistit pomocí znaku „-n“, který odstraní řádky ukazující, kde byla funkce definována.