Teken een aanroepgrafiek

Ik behoud een oude codebasis geschreven in python. In het bijzonder is er een complex stuk code dat vanuit een module andere functies aanroept van andere modules die andere functies aanroepen, enzovoort. Het is geen OOP, alleen functies en modules.
Ik heb geprobeerd bij te houden waar de stroom begint en eindigt wanneer ik de hoofdfunctie aanroep, maar ik heb het gevoel dat ik moet tekenen dit omdat ik verdwaal in de sub-oproepen.

Wat me zorgen baart is dat elke functie meerdere externe functies in hun lichaam aanroept om hun taak te voltooien en de waarde terug te sturen naar de beller.

Hoe kan ik dit tekenen? Wat betekent wat voor soort diagram / afbeelding geschikt is om dit soort gedrag / code te documenteren?

Dus ik denk niet dat het nuttig zou zijn om een UML-diagram te tekenen , noch een stroomschema. Een oproepgrafiek misschien?

Opmerkingen

  • doxygen – genereert oproep- / beller-grafieken, ik ' Ik weet niet zeker hoeveel ondersteuning het heeft voor python. Ik weet dat je er Python-code voor kunt documenteren.
  • Ik ' heb pycallgraph geprobeerd, maar het ' is gewoon ook ingewikkeld / te diep om het te gebruiken. Dit komt door de complexiteit van mijn code omdat het gewone python mengt met django en een externe aanroep naar API-url. Daarom wilde ik het met de hand tekenen, alleen rekening houdend met het relevante deel dat ik nodig heb. Het probleem is dat ik ' niet weet wat voor soort grafiek ik moet gebruiken om een volledig begrip van het systeem te krijgen.
  • Als dit alleen is om u te helpen het te begrijpen , teken gewoon wat er van nature komt. Je kunt het later altijd weer opruimen als het ' naar formele documentatie gaat.

Antwoord

Ik denk dat u hier “naar op zoek bent” een Sequentiediagram is. Hiermee kunt u de volgorde visualiseren waarin verschillende modules aanroepen elkaar door middel van pijlen.

Het construeren van een is eenvoudig:

  1. Teken je startklasse met een stippellijn eronder.
  2. Teken de volgende class / method in de call-trace met een stippellijn daaronder
  3. Verbind de lijnen met een pijl, verticaal gepositioneerd onder de laatste pijl die je hebt getekend
  4. Herhaal stap 2-3 voor alle calls in je trace

Voorbeeld

Laten we aannemen dat we de volgende code hebben waarvoor we een sequentiediagram willen maken:

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

Het eerste dat we” zullen tekenen is het toegangspunt (main) dat verbinding maakt met de methode long_division . Houd er rekening mee dat hierdoor een box wordt gemaakt in long_ divisie, waarmee het bereik van de methodeaanroep wordt aangegeven. Voor dit eenvoudige voorbeeld zal het vak de volledige hoogte van ons sequentiediagram zijn, omdat dit het enige is dat wordt uitgevoerd.

voer hier de beschrijving van de afbeelding in

Nu bellen we find_largest_fit om het grootste veelvoud te vinden dat binnen ons werknummer past , en geeft het ons terug. We trekken een lijn van long_division naar find_largest_fit met een ander vak om de omvang van de functieaanroep aan te duiden. Merk op hoe het vak eindigt wanneer de vermenigvuldiger wordt geretourneerd; dit is het einde van dat functiebereik!

voer hier een afbeeldingbeschrijving in

Herhaal een paar keer voor een groter getal en je diagram zou er ongeveer zo uit moeten zien:

voer in afbeelding beschrijving hier

Opmerkingen

U kunt kiezen of u de oproepen wilt labelen met de doorgegeven variabelenamen, of hun waarden als u alleen wilt documenteer een specifiek geval. Je kunt ook recursie laten zien met een functie die zichzelf aanroept.

Bovendien kun je gebruikers hier laten zien en ze vragen en hun invoer in het systeem gemakkelijk genoeg laten zien. Het “een redelijk flexibel systeem dat je volgens mij best wel nuttig zal vinden!

Reacties

  • Bedankt, ik ken het sequentiediagram, maar het voelt voor mij dat het meer geschikt is voor oop. In mijn geval is het een beetje rommeliger, wat betekent dat ik bijvoorbeeld ongeveer 20 functies / helpers heb verspreid over meerdere modules. Ho zou ik de module specificeren waartoe de functie behoort? Gezien het feit dat sommige functies ook hernoemd worden tijdens het importeren.
  • Ik zou zeggen dat het niet uitmaakt hoeveel modules je hebt – het bovenstaande voorbeeld is ook helemaal niet oop. Noem ze gewoon zodat u ze later kunt vinden, ModuleA / function1, ModuleB / Function2 enz. Voor 20 functies wordt het groter, maar zeker niet onmogelijk te begrijpen. Een ander idee dat je kunt doen is de regel voor een functie beëindigen na het laatste gebruik en een andere functieregel eronder plaatsen om horizontale ruimte in je diagram te besparen.

Antwoord

Ik denk dat een call-graph de meest geschikte visualisatie is.Als je besluit om het niet met de hand te doen, is er “een leuke kleine tool genaamd pyan die statische analyse uitvoert op een python-bestand en een gevisualiseerde aanroepgrafiek kan genereren door middel van een graphviz-punt bestand (dat kan worden weergegeven als afbeelding). Er zijn een aantal forks geweest, maar de meest complete lijkt https://github.com/davidfraser/pyan .

U hoeft alleen alle bestanden op te geven die u wilt verwerken wanneer u de opdracht uitvoert:

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

of

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

U kunt de grafiek schoner maken met de “-n” die de regels die aangeven waar een functie is gedefinieerd.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *