我正在维护使用python编写的旧代码库。特别是,有一段复杂的代码可以从一个模块调用其他功能,而从其他模块调用其他功能,依此类推。它不是OOP,而只是功能和模块。
每当我调用main函数时,我都试图跟踪流的开始和结束位置,但是我觉得我需要绘制该流,因为我在子调用中迷路了。
让我担心的是,每个函数都在其体内调用多个外部函数以完成其任务并将该值返回给调用者。
我怎么画这个?意味着哪种图表/图形适合于记录这种行为/代码?
因此,我认为绘制UML图和流程图都不有用。通话图,也许吗?
我正在维护使用python编写的旧代码库。特别是,有一段复杂的代码可以从一个模块调用其他功能,而从其他模块调用其他功能,依此类推。它不是OOP,而只是功能和模块。
每当我调用main函数时,我都试图跟踪流的开始和结束位置,但是我觉得我需要绘制该流,因为我在子调用中迷路了。
让我担心的是,每个函数都在其体内调用多个外部函数以完成其任务并将该值返回给调用者。
我怎么画这个?意味着哪种图表/图形适合于记录这种行为/代码?
因此,我认为绘制UML图和流程图都不有用。通话图,也许吗?
Answers:
我认为您在这里寻找的是序列图。这些使您可以可视化各种模块通过使用箭头相互调用的顺序。
构造一个很简单:
假设我们有以下代码要为其创建序列图:
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")
我们首先要绘制的是main
连接到方法的入口点()long_division
。请注意,这会在long_division中创建一个框,表示方法调用的范围。对于这个简单的示例,由于这是唯一的事情,因此该框将是序列图的整个高度。
现在,我们致电find_largest_fit
寻找适合我们工作号码的最大倍数,并将其返回给我们。我们在long_division
到find_largest_fit
另一条方框之间划一条线,以表示函数调用的范围。请注意返回乘数时框如何结束;这是功能范围的结尾!
重复几次以获得更大的数字,您的图表应如下所示:
您可以选择是使用传递的变量名来标记调用,还是仅在记录一种特定情况时才选择其值。您还可以通过调用自身的函数来显示递归。
另外,您可以在此处显示用户并提示他们,并轻松地将其输入到系统中。这是一个相当灵活的系统,我认为您会发现它非常有用!
我认为调用图将是最合适的可视化。如果您决定不手动执行此操作,则可以使用一个不错的小工具pyan
来对python文件进行静态分析,并可以通过graphviz点文件(可以呈现为图像)生成可视化的调用图。已经有几个分支,但是功能最全的分支似乎是https://github.com/davidfraser/pyan。
您只需要在运行命令时指定要处理的所有文件:
python ~/bin/pyan.py --dot a.py b.py c.py -n > pyan.dot; dot -Tpng -opyan.png pyan.dot
要么
python ~/bin/pyan.py --dot $(find . -name '*.py') -n > pyan.dot; dot -Tpng -opyan.png pyan.dot
您可以使用“ -n”使图形更整洁,从而删除显示函数定义位置的行。