如何在 MATLAB 中可视化项目结构?
我拥有数千行 Matlab 代码,其中一些超过 900 行函数,还有一些充满 function_name.m
文件的目录。很难弄清楚所有事情正在做什么(或与之相关)或找出依赖关系。您建议如何可视化函数结构,例如从哪个函数调用什么函数以及以什么顺序调用?
I've come into ownership of several thousand lines of Matlab code, some as >900 line functions and a few directories full of function_name.m
files. It's hard to figure out what everything is doing (or relating to) or figure out the dependencies. What would you suggest to visualize the functions structure, such as what functions are called from which, and in what sequence?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
移植到 NumPy。
(笑话。)
通常在 Matlab 中,您有一些文件编写为函数,还有一些文件编写为脚本。脚本执行的操作包括加载要处理的数据、将其提供给函数并绘制图表。
为了组织事情,我将从顶层脚本开始,找出哪些函数负责加载、绘图、处理等。将脚本保存在顶层目录中,并尝试根据目的将函数分离到子目录中。功能。将函数的依赖项放入同一子目录中。尝试使目录中的代码不依赖于父目录(或表兄弟目录)中的任何内容。
每当您弄清楚函数的作用及其参数是什么时,请编写文档注释。
这假设编写代码的人是合理的。如果没有,Matlab 可以轻松地将所有内容放入一个目录中,并使所有内容都依赖于摇摇欲坠的代码塔中的其他所有内容,因此您最终可能会进行大量重构。
Port to NumPy.
(Joke.)
Usually in Matlab you have some files written as functions, and some as scripts. Scripts do things like load the data you want to process, and feed it to the functions, and graph it.
To organize things I would start at the top level script and find out which functions do the loading, graphing, processing, etc. Keep the scripts in a top level directory and try to separate the functions out into subdirectories, according to the purpose of the function. Put dependencies of a function into the same subdirectory. Try to make it so that no code in a directory depends on anything in a parent directory (or cousin directory).
Whenever you figure out what a function does and what its arguments are, write a doc comment.
This assumes the person who wrote the code was reasonable. If not, Matlab makes it easy to plunk everything down into one directory and have everything depend on everything else in a rickety tower of code, so you may end up doing a lot of refactoring.
我在 The MathWorks 担任各种角色时不得不多次处理这个问题。这就是我对大段 MATLAB 代码所做的事情:
全选,Ctrl-J 换行注释
如果我感觉纸质版 - 打印所有文件,并获得一组荧光笔 - 手动跟随,突出显示长期变量和重要的函数调用。
~~~ AND / OR ~~~
5 如果我感觉幸运的话,开始在调试器中运行代码,单步执行
一次一行(进入用户编写的子函数)
此时,我可以浏览并遵循控制结构的典型流程。我可能不太清楚每件事的作用,但我对正在发生的事情有一个很好的了解。
通常,我的目标是找到错误、解决它并继续前进。您的目标可能完全不同。这是我用来快速理解多年来我收到的数百段不同 MATLAB 代码的方法。
I have had to deal with this problem many times in my various roles at The MathWorks. This is what I do for the big pieces of MATLAB code:
Select all, Ctrl-J to wrap comments
If I am feeling paper-based- Print all the files out, and get a set of highlighters- follow manually, highlighting long term variables and important function calls.
~~~ AND / OR ~~~
5 If I am feeling lucky, start running the code in the debugger, stepping through
one line at a time (stepping into subfunctions that were user written)
At this point, I can go through and follow a typical flow through the control structure. I may not have a great idea what everything does, but I have a decent idea of what is going on.
Normally, my goal is to find a bug, solve it and move on. Your goals might be completely different. This is the method that I have used to quickly comprehend hundereds of different pieces of MATLAB code that I have been sent over the years.
您的代码是否带有合适的帮助文本?在这种情况下, m2html 将是一个很大的帮助,因为它允许您创建链接的 html 帮助以便于浏览。
此外,它还允许您制作依赖关系图,这可以帮助您更多地了解如何组织代码。
Does your code come with decent help text? In that case, m2html is going to be a great help, since it allows you to create linked html help for easy browsing.
Furthermore, it allows you to make dependency graphs, which help you understand a bit more how you may want to organize the code.
Richard Johnson 的 MATLAB 编程风格指南 是一个很好的资源。
MATLAB Programming Style Guidelines by Richard Johnson is a good resource.
关于 Matlab 编码约定的一些建议:
使用 addpath 避免文件混乱并协助函数分类
分解功能脚本的section_或设置条件运行,这也可以帮助插入/输出模块和重用或代码引用。
使用配置文件打开和关闭选项
为了区分,可以考虑为代码修改设置一个新节点,例如。设置一棵树来区分版本。
为输入/输出、图像、中间结果等使用单独的文件夹。
使用时间戳来跟踪您的版本
p>
与其他人共享您的代码,如果他们发现难以维护、使用或修改,请重新考虑如何改进您的构建。
some suggestions on Matlab coding convention:
use addpath to avert file cluttering and assist in functions taxnomony
break up section_ for functional scripts or set for conditional runs, this can also help in plug-in/ out modules and re-use or code referencing.
use a config file to turn on and off the options
for differentiation, consider setting a new node for code modifications, eg. set a tree to differentiate the versions.
use a separate folder for inputs/ outputs, images, intermediate results, etc.
use timestamp to trace your versions
share your codes with someone else, if they find it difficult to maintain, use or modify, rethink on how to refine your builds.
我同意大多数关于 Matlab 不太支持现代软件源代码结构的评论,但我不认为通过一点规则强加一些你自己的结构是太困难的。
将源文件组织到目录层次结构中,就像组织用其他编程语言编写的任何程序的源文件一样。您无需遵循层次结构,如果您愿意,可以选择自己的结构。使用 setpath 命令(或者无论它叫什么名字)告诉 Matlab 在工作时到哪里查找 m 文件。
熟悉 Matlab 分析器工具,它可以为您提供调用图(不是非常图形化,更像 gprof 的调用图),这对破译意大利面条代码有一些帮助。
当然,我们所有的 m 文件都在存储库中,我们从存储库中提供它们。我们在一个网络驱动器上保留一个私有工具箱,所有用户都可以直接调用该工具箱中的“已发布”代码。
I agree with most of the comments about Matlab not being terribly supportive of modern software source code structuring but I don't believe it's too difficult to impose some of your own structure with a little discipline.
Organise your source files into a hierarchy of directories, as you would the source files for any program written in another programming language. You don't need to stick to a hierarchy, choose your own structure if you wish. Use the setpath command (or whatever the heck it is called) to tell Matlab where to look for your m files when you are working.
Acquaint yourself with the Matlab profiler tool which can give you call graphs (not terribly graphically, more like gprof's call graphs) which is some help in deciphering spaghetti code.
Of course, all our m files are in the repository and we serve them out of that. We keep a private toolbox on one of our networked drives and all users can call the 'released' code in that toolbox directly.
备份一切都是正确的。创建原始源代码树的原始 tarball,然后将其全部放入源代码管理中,以便您可以跟踪和回滚更改。
看一下 Matlab 的 depfun() 和 depdir(),它们检测静态依赖关系。它可以帮助您了解 Matlab 函数之间的依赖关系。通过对所有文件使用“depfun -toponly”并进行一些字符串修改,您可以构建直接依赖项列表并将其放入 GraphViz 文件中,以生成代码库调用连接的大有向图。图中的簇可能是划分代码的好地方。 (编辑:请参阅 Jonas 的解决方案;看起来 m2html 为您做到了这一点。)
如果您有很大的自由度来重写代码,请考虑将一些代码重写为对象,使用带有类方法和私有函数的无状态实用程序类作为将相关的功能打包在一起,并提供一些封装。我曾经使用过以这种方式组织的大型 Matlab 代码库,并且它工作得很好。在经典的 Matlab 中,类是执行某种包的唯一方法。我相信 Matlab 的新 OO 系统也有命名空间支持。
如果不想将代码转换为OO,可以将相关函数组织在子目录中。这至少有助于组织它以供源代码浏览。
所有函数都应该有一些 Matlab 标准帮助文本格式的 doco,包括 H1 行。如果他们不这样做,请将您在那里学到的内容发表评论。然后使用“contentsrpt”工具自动生成类或目录的目录文件。
祝你好运。
Back everything up is right. Create a pristine tarball of the original source tree, and then throw it all in source control so you can track and roll back your changes.
Have a look at Matlab's depfun() and depdir(), which detect static dependencies. It could help you see dependencies between Matlab functions. With "depfun -toponly" on all the files and a little string munging, you could build a list of immediate dependencies and throw that in a GraphViz file to produce a big directed graph of your codebase's call connections. Clusters in the graph could be a good place to divide the code around. (EDIT: See Jonas's solution; looks like m2html does this for you.)
If you have a lot of latitude to rewrite the code, consider rewriting some of the code as objects, using stateless utility classes with class methods and private functions as ways of packaging related functions together and providing some encapsulation. I've worked with largish Matlab codebases organized this way, and it works all right. In classic Matlab, classes are your only way of doing some sort of packages. I believe Matlab's newer OO system has namespace support, too.
If you don't want to convert the code to OO, you can organize related functions in subdirectories. That helps to organize it for source code browsing at least.
All the functions should have some doco in Matlab's standard helptext format, including an H1 line. If they don't, stick the comments on what you learn there. Then use the "contentsrpt" tool to automatically generate table of contents files for the classes or directories.
Good luck.