Dessinez un graphe dappel

Je « m entretiens une ancienne base de code écrite en python. En particulier, il y a un morceau de code complexe qui à partir dun module appelle dautres fonctions à partir dautres modules qui appellent dautres fonctions et ainsi de suite. Ce nest pas la POO, juste des fonctions et des modules.
Jai essayé de garder une trace du début et de la fin du flux à chaque fois que jappelle la fonction principale mais je sens que jai besoin de dessiner ceci parce que je me perds dans les sous-appels.

Ce qui me préoccupe, cest que chaque fonction appelle plusieurs fonctions externes dans son corps pour terminer leur tâche et renvoyer la valeur à lappelant.

Comment puis-je dessiner ceci? Signification quel type de graphique / graphique serait approprié pour documenter ce type de comportement / code?

Donc, je ne pense pas quil serait utile de dessiner un diagramme UML , ni un organigramme. Un graphique dappel, peut-être?

Commentaires

  • doxygen – générera des graphiques dappel / appelant, I ' Je ne sais pas combien de support il a pour python. Je sais que vous pouvez documenter le code python pour cela.
  • Jai ' essayé pycallgraph mais il ' est tout simplement aussi compliqué / trop profond pour lutiliser. Cela est dû à la complexité de mon code car il mélange du python simple avec django et un appel externe à lURL de lAPI. Cest pourquoi jai voulu le dessiner à la main en ne tenant compte que de la partie pertinente dont jai besoin. Le problème est que je ne ' que je ne sais pas quel type de graphique utiliser pour avoir une compréhension complète du système
  • Si cest juste pour vous aider à le comprendre , dessinez tout ce qui vient naturellement. Vous pouvez toujours le ranger plus tard si ' va dans la documentation formelle.

Réponse

Je pense que ce que vous « cherchez ici est un Diagramme de séquence . Ceux-ci vous permettent de visualiser lordre dans lequel les différents modules appellent les uns des autres via lutilisation de flèches.

En construire une est simple:

  1. Dessinez votre classe de départ avec une ligne pointillée en dessous.
  2. Dessinez la suivante classe / méthode dans le suivi des appels avec une ligne pointillée en dessous
  3. Reliez les lignes avec une flèche, positionnée verticalement sous la dernière flèche que vous avez dessinée
  4. Répétez les étapes 2 et 3 pour tous les appels dans votre trace

Exemple

Supposons que nous ayons le code suivant pour lequel nous voulons créer un diagramme de séquence:

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

La première chose que nous » allons dessiner est le point dentrée (main) se connectant à la méthode long_division . Notez que cela crée une boîte dans long_ division, indiquant la portée de lappel de méthode. Pour cet exemple simple, la boîte correspondra à la hauteur entière de notre diagramme de séquence car cest la seule chose exécutée.

entrez la description de limage ici

Nous appelons maintenant find_largest_fit pour trouver le plus grand multiple qui correspond à notre numéro de travail , et nous le renvoie. Nous dessinons une ligne de long_division à find_largest_fit avec une autre case pour indiquer la portée de lappel de fonction. Notez comment la boîte se termine lorsque le multiplicateur est retourné; cest la fin de la portée des fonctions!

entrez la description de limage ici

Répétez plusieurs fois pour un nombre plus grand et votre graphique devrait ressembler à ceci:

entrez description de limage ici

Remarques

Vous pouvez choisir si vous souhaitez étiqueter les appels avec les noms de variables passés, ou leurs valeurs si vous le souhaitez uniquement documenter un cas spécifique. Vous pouvez également afficher la récursivité avec une fonction qui s’appelle elle-même.

De plus, vous pouvez afficher les utilisateurs ici, les inviter et afficher leur entrée dans le système assez facilement. Cest un système assez flexible que je pense que vous trouverez plutôt utile!

Commentaires

  • Merci, je connais le diagramme de séquence, mais il me semble quil est plus approprié pour oop. Dans mon cas, les choses sont un peu plus compliquées, ce qui signifie que, par exemple, jai environ 20 fonctions / assistants répartis sur plusieurs modules. Comment spécifier le module auquel appartient la fonction? Considérant que certaines fonctions sont également renommées lors des importations ..
  • Je dirais que peu importe le nombre de modules que vous avez – lexemple ci-dessus nest pas du tout non plus. Nommez-les simplement pour pouvoir les retrouver plus tard, ModuleA / function1, ModuleB / Function2 etc. Pour 20 fonctions, ce sera plus grand, mais certainement pas impossible à comprendre. Une autre chose que vous pouvez faire est de terminer la ligne dune fonction après sa dernière utilisation et de mettre une autre ligne de fonctions en dessous pour économiser de lespace horizontal dans votre diagramme.

Réponse

Je pense quun graphe dappel serait la visualisation la plus appropriée.Si vous décidez de ne pas le faire à la main, il existe « un joli petit outil appelé pyan qui effectue une analyse statique sur un fichier python et peut générer un graphe dappel visualisé au moyen dun point graphviz fichier (qui peut être rendu à une image). Il y a eu quelques fourches, mais la plus complète semble être https://github.com/davidfraser/pyan .

Il vous suffit de spécifier tous les fichiers que vous souhaitez traiter lorsque vous exécutez la commande:

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

ou

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

Vous pouvez rendre le graphique plus propre avec le « -n » qui supprime le lignes indiquant où une fonction a été définie.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *