Rita en samtalsgraf

Jag håller en gammal kodbas skriven i python. Speciellt finns det en komplex kod som från en modul kallar andra funktioner från andra moduler som anropar andra funktioner och så vidare. Det är inte OOP, bara funktioner och moduler.
Jag har försökt hålla reda på var flödet börjar och slutar när som helst jag ringer till huvudfunktionen men jag känner att jag behöver rita detta för att jag går vilse i underanropen.

Det som berör mig är att varje funktion ringer till flera externa funktioner i kroppen för att slutföra sin uppgift och returnera värdet till den som ringer.

Hur kan jag rita det här? Vilken typ av diagram / grafik skulle vara lämpligt för att dokumentera denna typ av beteende / kod?

Så jag tror inte att det skulle vara användbart att rita ett UML-diagram , varken ett flödesschema. Ett samtalsdiagram, kanske?

Kommentarer

  • doxygen – genererar samtals- / samtalsdiagram, jag ' jag är inte säker på hur mycket stöd det har för python. Jag vet att du kan dokumentera pythonkod för det.
  • Jag ' har försökt pycallgraph men det ' är bara för komplicerat / för djupt för att använda det. Detta beror på komplexiteten i min kod eftersom den blandar vanlig python med django och externt samtal till API-url. Det var därför jag ville rita den för hand bara med hänsyn till den relevanta delen jag behöver. Problemet är att jag inte ' inte vet vilken typ av diagram som ska användas för att få en fullständig förståelse för systemet
  • Om detta bara är för att hjälpa dig att förstå det , rita bara vad som kommer naturligt. Du kan alltid städa upp det senare om det ' går in i formell dokumentation.

Svar

Jag tror att det du söker här är ett Sekvensdiagram . Dessa låter dig visualisera den ordning som olika moduler kallar varandra med hjälp av pilar.

Att konstruera en är enkel:

  1. Rita din startklass med en prickad linje under den.
  2. Rita nästa klass / metod i samtalsspåret med en prickad linje nedanför den
  3. Anslut linjerna med en pil, vertikalt placerad under den sista pilen du ritade
  4. Upprepa steg 2-3 för alla samtal i ditt spår

Exempel

Låt oss anta att vi har följande kod vi vill skapa ett sekvensdiagram för:

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

Det första vi ritar är ingångspunkten (main) som ansluter till metoden long_division Observera att detta skapar en ruta i long_ division, vilket anger omfattningen av metodanropet. För detta enkla exempel kommer rutan att vara hela höjden på vårt sekvensdiagram på grund av att detta är det enda som körs.

ange bildbeskrivning här

Nu ringer vi find_largest_fit för att hitta den största multipeln som passar inom vårt arbetsnummer och returnerar det till oss. Vi drar en linje från long_division till find_largest_fit med en annan ruta för att ange omfattningen för funktionsanropet. Observera hur rutan slutar när multiplikatorn returneras; detta är slutet på detta funktionsomfång!

ange bildbeskrivning här

Upprepa några gånger för ett större nummer och ditt diagram ska se ut så här:

enter bildbeskrivning här

Anteckningar

Du kan välja om du vill märka samtalen med variabelnamnen passerade eller deras värden om du bara vill dokumentera ett specifikt fall. Du kan också visa rekursion med en funktion som anropar sig själv.

Dessutom kan du visa användare här och uppmana dem och visa deras inmatning i systemet tillräckligt enkelt. Det är ett ganska flexibelt system som jag tror att du kommer att hitta ganska användbart!

Kommentarer

  • Tack, jag vet sekvensdiagrammet, men det känns för mig att det är mer lämpligt för oop. I mitt fall är saker lite mer röriga, vilket betyder att jag till exempel har ett 20-tal funktioner / hjälpare fördelade på flera moduler. Ho skulle jag specificera den modul som funktionen tillhör? Med tanke på att vissa funktioner också byts namn vid import ..
  • Jag skulle säga att det spelar ingen roll hur många moduler du har – det ovanstående exemplet är inte heller öppet. Namnge dem bara så att du kan hitta dem senare, ModuleA / function1, ModuleB / Function2 etc. För 20 funktioner kommer det att bli större, men definitivt inte omöjligt att förstå. En annan tro att du kan göra är att avsluta raden för en funktion efter dess senaste användning och lägga en annan funktionsrad under den för att spara horisontellt utrymme i diagrammet.

Svar

Jag tror att en samtalsgraf skulle vara den mest lämpliga visualiseringen.Om du bestämmer dig för att inte göra det för hand finns det ett trevligt litet verktyg som heter pyan som gör statisk analys på en pythonfil och kan generera en visualiserad samtalsgraf med hjälp av en graphviz-punkt fil (som kan återges till en bild). Det har funnits ett par gafflar, men den mest kompletta ser ut att vara https://github.com/davidfraser/pyan .

Du behöver bara ange alla filer du vill bearbeta när du kör kommandot:

python ~/bin/pyan.py --dot a.py b.py c.py -n > pyan.dot; dot -Tpng -opyan.png pyan.dot

eller

python ~/bin/pyan.py --dot $(find . -name "*.py") -n > pyan.dot; dot -Tpng -opyan.png pyan.dot

Du kan göra grafen renare med ”-n” som tar bort rader som visar var en funktion definierades.

Lämna ett svar

Din e-postadress kommer inte publiceras. Obligatoriska fält är märkta *