阅读优秀项目的源代码是程序员自我提高的重要途经,因此好的工具能够帮助你事半功倍。就像 Lua 这样的开源项目,官方文档可能你花一天就看完了,但是源代码很多人一个月都看不明白,而 好的工具可以帮助你加速这个过程。
最早我直接用 VS 读代码,后来用 source insight 代替了 vs,再后来用的 vim + ctags/gtags ,其他乱七八糟的东西也都试用过,最近几年我只用 understand。
我是建议所有使用 source insight 的用户迁移 understand,因为 si 这货基本十多年没更新了(虽然最近出了个 4.0),而 si 有的功能 understand 基本全覆盖:
简单使用下的话,点击 “地球图标”进入浏览模式,然后鼠标直接点击代码区的符号(函数、变量名),下面预览窗口(Previewer)就会显示符号的相关代码,双击 Previewer 又可以在上面代码区打开对应代码。
同时左下角有符号详情面板,详细列举了符号的定义,引用,被调用,以及调用的东西,这些信息 si 也有,但是没有这么方便。
初次使用需要在下拉菜单 View 中,显示:Previewer, Project Browser 还有 Scope List 三项:
其中 Previewer 就是前面截屏中最下面的符号预览窗口,Project Browser 是左边的项目文件列表,Scope List 是右边的符号列表,这样 si 基本全覆盖了。
Understand 同时支持:C/C++, Python, Java, 汇编,VB,C#,Fortran,Ada,VHDL,Delphi/Pascal 等等十多种语言,比 si 丰富不少。
对比 Vim + gtags/ctags/cscope/grep:
最主要的就是 understand 真的是在分析源代码,是在理解源代码,而 gtags/ctags 之类的只是在按格式扫描文本文件,我举个例子,宏的条件编译,gtags/ctags 就无法识别:
一般而言符号定义只有一处,而有时候用 vim+ctags/gtags 搜索符号定义,经常会搜索出 7,8 个定义出来,因为 ctags/gtags 只会匹配字符串:
第一:ctags/gtags 无法处理宏,比如多个平台下都实现了同一个函数,并且用宏来进行条件编译,ctags/ gtags 就傻了,会搜索出很多无关结果来。
第二:对于同名但是参数不同的符号,understand 能够根据调用时候的参数类型,精准的匹配到对应的定义,而 ctags 这种时候基本也就挂了,只能给你全部列出来。
第三:ctags/gtags 数据库中的函数,比如 class1::update(),虽然它也会记录 class1,但是实际在 Vim 使用的时候,比如 x->update() 这样的语句,任何 ctags/gtags 的 vim 插件都没法分析出 x 是个什么类型,因此这样搜索定义的时候,ctags/gtags 会搜索出所有叫做 update 的函数。
上面三点导致用 vim+ctags/gtags/grep 经常无法准确的给我找出定义来,C 语言还稍微好一点,没有第二和第三个问题,C++ 的话,ctags/gtags 基本没法看。
很可惜,最新的 Source Insight 4.0 也无法理解代码里面的宏:
而 Understand 可以准确识别出有效的代码块:
有些人可能会说,si 难说识别出来了,只是没有标红显示,那么换张图,随便加两行代码:
上面这个对比只是冰山一角,原因就是 vim+ctags/gtags/grep 是基于字符串分析的,si 也没有好到哪里去,而 understand 是真的是基于语义的分析,他们我都用过好多年,差距是非常明显的。
预览窗口
这个功能类似 si,就是上面代码窗口点击了任意符号,最下面预览窗口就立马出现相关代码:
用这个预览窗口阅读代码效率是非常高的,通常瞥一眼符号定义的话,用它就够了,想详细看,双击预览窗口,就会在上面代码区打开源代码,vim 也有插件弄出这样一个预览窗口来,并且 vim 本身也有预览窗,甚至悬浮预览窗,然而由于 ctags/gtags/grep 没法准确求解定义,经常会给出 7-8 处结果来,弄得你预览非常低效,经常要切换过来切换过去。
Understand 是围绕代码阅读来设计的,所有 UI/UE,快捷键,鼠标操作方法,都是为了让读代码更方便而生的。过去用 Visual Studio 开发时,它也可以跳到定义处,但是这个跳转操作,实际体验比预览低效很多,大部分时候其实你只需要预览一下。
符号详情
就是第一张图左下角的那个信息窗口,浏览模式下点击任意符号就出现:
可以读读符号窗口里的信息有多详细,这个窗口已经足够秒杀任何 si 和 vim+ctags/gtags/grep 或者 Visual Studio 了,不但信息丰富程度秒杀他们,而且用起来真的方便,符号窗口上面那些蓝色的字体,鼠标单击就可以在下方的预览窗口预览,不需要打开新文件,或者切换文件。
对比 Visual Studio
虽然 vs 也有查找定义,查找引用,但大家发现没有,很多用 vs 的用户过去都会用 si 来阅读代码,举个简单例子,si 优势之一,代码窗口和预览窗口搭配十分方便,有时候一个源代码打开,我可能要对十多处符号查看定义,有预览窗口的话,鼠标点点点看下边就行了,vs 会给你打开一堆文件,把你原来的工作区都挤没了,或者有个 “Peek Definition" 的功能,会在你当前源代码那里插入一段目标代码,看完了还要你手工去关闭。
而 Understand 的:源代码窗口+预览窗口+符号信息窗口,三合一互相搭配的工作流,可以比 vs 和 si 都方便。同时还是那句老话,阅读代码不是简单搜索个定义和引用,而是 UI/UE + 数据,一体化解决方案,专业代码阅读软件,是围绕读代码设计的,最方便的快捷键,最好的 UI 位置,都给了 “读代码” 这件事情,还有各种特有的功能面板,启是普通 IDE 符号搜索功能可以代替。
过去用 vs 很多年的人,都会选择 si 读代码,而今天他们有了比 si 更好的选择。
对比 Sourcetrail
这货我试用过,真的很弱智,和 understand 比较起来就像三岁小孩比成年人的感觉,sourcetrail 也就是最近两年才出来的东西,是开源作者个人兴趣项目,而 understand 是商业团队持续迭代了 15 年以上的产品,能比么?
丰富的图表
因为 si 持续十多年不更新,而 understand 相当于一个继续迭代了十多年的 si,因此 si 有的图表,understand 只多不少,比如符号的 butterfly 图:
左边是 Slerp
这个函数的调用者,右边是它调用的东西,二者结合能让你对该符号在项目中的位置有一个值观了解。这个图 gtags 都没法生成,因为 gtags 虽然可以找到 callers,却无法找出 callees。
比如项目鸟瞰图:
这个项目鸟瞰图基本秒杀 si 和 vim+ctags/gtags 了,每个方块都可以点击,查看细节。
还有各种全局统计:
流程图:
以及其他:定义图,继承图,UML图,依赖图,Tree Map ,交叉引用图:
等等,应有尽有。还有很多其他功能,不一一例举了。。。
总的来讲,作为 source insight, vim+ctags/gtags/grep, understand 每样都用了三年以上的人来讲,用 understand 阅读代码是效率最高的,最方便的方式,基本能将你效率提升一倍以上。特别是阅读一些陌生的,复杂的源代码,understand 能够帮你更快速的理清楚各个模块的内在联系。
如果一个工具能够在未来数年内都让你受益,那么完全值得花一天时间试用评估一下,understand 同时支持 windows, linux, macos 三大平台,基本不会有任何门槛。
--
补充:Understand 是如何解析宏的,第一是 Understand 可以直接导入 Visual Studio 的 sln 文件,以及 CMake 的 cache 数据,里面都有一些基础的宏的定义,Understand 可以用这些基础宏对更高级的宏表达式求值。
另外一个是,对于一些没有工程文件,纯粹代码的裸项目而言,Understand 可以手动设置宏:
它支持预定义,导入导出,右下角的 "Undefined Macros" 按钮还能告诉你哪些宏没有定义,并不需要你定义所有宏,一般定义几个和平台相关的基础宏就够了,其他 Understand 能够根据他们进行宏表达式求值。
当然有条件的话,还是建议直接导入工程项目,这样更省事,也更准确些。
--
在我卸载 Source Insight 4.0 之前,最后在对比一次:
在搜索 obj->update 这个方法的时候,si 可以识别到 obj 的类型是 Bar,这很好,但是没法做参数匹配,找到正确的 update 函数原型,而 understand 却没问题:
可以看到 understand 找到了正确的函数原型。再来对比下 vim+ctags:
光标停在 21 行 obj->update(5) 的 update 处,g],好样的,vim 果然不负众望,帮我找到了 5 个 update 定义,根本不知道正确的是谁。
谁是谁非,高下立判。
--
收藏比点赞高 50%,什么情况?点个赞有心理阴影么?
--