【方法】阅读源码

11 篇文章 1 订阅


以下内容来自网络。

经验总结

先别看代码,先看书或者国外牛人博客,尝试从设计者的角度审视代码,也就是从全局到模块再到主要类的方式去梳理。如果一上来就扎入代码,会很快迷失在茫茫代码中。

不要直接看代码。先看文档,特别是关于整个东西的整体架构、整体设计的部分,了解它的结构和运作方式。然后看API文档,了解它的主要接口都在干什么。最后再看具体实现

先看代码的整体结构,实现类,接口类,模型类,工具类区别开来。花10分钟时间把每个文件大概看下。之后跟着程序跑一次,从入口走,进入库的核心实现类后观察他实例化了哪些类,这些类分别都做了些什么…最后一层层慢慢地把源码拆开阅读,很快就能理解。一定要有耐心,有的源码比较难懂,往往看了几遍后还没有头绪,相信多读继续,每次肯定有新收获。

读代码和写代码一样,你得先明确目标。漫无目的的读代码是不会有结果的,就如你自己都不知道写什么功能的情况下,能写什么代码?既然明确你想了解的具体功能,接下去就简单了,你只要找到这个功能的切入点,按代码顺序读下来就可以了,读代码的速度取决于你对整体代码的熟悉程度,刚上手肯定会慢一点整个过程中最关键的是找切入点,我看了很多新手程序员根本找不到他想看的功能该如何看起,那就需要一些技巧了,找一些不会变的关键api来作为索引的关键字,比如网络相关的肯定有recv,文件相关的也就是fread这样的一系列函数。

读懂开源项目首先你一定是这个开源项目的重度用户,你熟悉这个项目的个性和脾气。比如说你用一个开源框架,你知道这个框架喜欢你怎么配置,什么时候会出问题。然后某次你调试代码的时候突然发现一些不合情理的异常,于是你一步一步跟踪终于找到是在调用框架方法A的时候出现的问题。这是你自然而然的挖掘到这个项目的源代码去,终于发现原来这个项目有n层调用,每一层都检查些什么、又做些什么,等等。这种情况经历多了,你对这个项目就越来越熟悉,甚至如果你发现了缺陷还可以贡献一下。最后再说一遍,最看不顺眼整天一上来就牛逼哄哄让人看个Linux内核之类的,tmd绝对没安好心。另外,关于代码注释,不好意思,我还没见过任何一个开源项目有完整注释的,5%都没有。

看得慢,看不懂,要嘛是看少了,要嘛是水平不够。没捷径,多看,努力提升理论水平。熟读唐诗三百首,多看猪跑。对于没多少经验的新手,建议从两个角度读,全局或者局部。了解全局的时候,关注执行流程、层次、调用之类的,对细节不求甚解,看不懂的,底层的,跳过就是。读细节的时候,就只读系统内自己关注的某个点,甚至某个具体的方法或者函数,一行一行慢慢啃。

题主,我个人感觉读开源分两种情况:1. 工作中需要解决一类问题2. 为了学习如果为了解决一类问题,这个时候你的目的是很明确的,直接在源码中找寻相关的部分读就好。我当时为了解决连接不提供JMXURL的MBeanServer问题时,去看OpenJDK的源码,其源码东西很多,但这一块因为目的明确,可以直接到其Attach机制实现的部分去了解,顺带着看JConsole的实现,就解决了问题。而如果是为了学习,就需要慢慢来读,开源项目一般都不小,不能急着想一气读完。那样和读课文一样看过之后,也是吸收不到东西的。而借助其文档,了解整个项目的大概,架构,组件等一系列内容,再分别去看,效果可能会好一些。甚至读的过程中,某一些点感觉很不错,自己马上上手mock一个,兴趣可能会大增吧。 比如你在读Tomcat源码,则先了解其各个容器,组件划分等。之后各个组件间的关联,可以跑起来跟一下就会有个大概印象。另外,也可以从开源项目的testcase入手,都是按功能点写的。至于题主提到的类有多个继承这一类的,可以在看的时候一边看一边画个类图,也方便后续的使用。如果给别人讲,甚至可以直接拿类图开始说。

根据我的经验,把握粒度很重要,每行每行读是不现实的,这样容易造成只见树木不见森林,但是又不能读的太粗糙,否则错过很多精华部分,以c代码为例,我一般是先以文件为单位,看看每个文件大致是干嘛的,然后再以函数为单位,这时不关心函数的具体实现细节,而是将注意力放在函数接口上,大致理解下函数的意图,控制流的流动等,然后觉得哪个函数比较重要,在看看其实现。。。如果一上来就一行一行的啃就图样图森破了,上述过程完成之后,如果还有余力,最好亲手实现一下,正所谓知者行之始,行者知之成,知行合一,如果能自己写一个,就说明真的掌握了。。。

应该先打开它的trace或debug日志,跑起来,然后跟踪日志,可以最快的熟悉代码

自动生成代码图的工具

单步调试,可以看到程序流程

先去掌握了设计模式,再去看优秀的开源代码

1、导入代码至开发环境,运行起来
2、样例代码做为入口,逐步断点调试
3、把工程、包名、类在word中按层次整理,分析写出用途和主要技术点
4、画程序流程图或者时序图
5、尝试代码扩展、以及打包构建

读代码切勿一开始就钻进一些细节。就像工作中接触一个新项目,新人也是从解bug 开始。带着目标问题去读,效果更好。要掌握一个整体架构,不妨自己动手画出一张完整的类图,对于理解代码架构非常有帮助。一些主要的业务逻辑,继续画些流程图顺序图,就一目了然了。最后才是语法方面的问题。我认为好的代码一定也是阅读起来超爽的…

先搞清楚代码的业务流程,什么设计模式都是看懂代码以后的事了

直接开始调试,先大致搞清楚程序跑得流程;然后不好调试的部分,比如网络,添加log,通过读日志分析程序行为。
最后,挑感兴趣的部分,直接读代码。

开源项目的代码结构文件布局应该都不错,在了解项目的主题功能后,我都是先看文件夹结构,猜测每个文件夹下的文件可能是干嘛的,文件名字应该都挺达意。我只说vs,它好像可以画出所有类的引用关系图,然后挑选继承关系在最上层的开始阅读。如果项目功能模块分的比较开,那更好了,一个模块一个模块的读。阅读中最怕数据model了,变量都是啥意思,怎么用,能干嘛,真是烦死了。

阅读源代码的第一个工具,就是你手中的code base。把它编译出来,运行它,加log,试着修改一些数据和代码,看看有什么变化。第二个重要的工具就是debugger,而debugger最重要的功能是获取call stack。在你感兴趣的use case里pause一下,在你不知道有什么用的函数里加个断点,显示出来的call stack都能让你对系统有更清晰的认识。一个软件系统就是一个小宇宙。别期待有什么高明的文档。要把自己当成探求自然真理的物理学家。
必须找好切入点。你要解决什么问题。是要fix bug;还是要把这个系统和其它模块集成;还是要增加新功能。物理学家没有上来就研究整个宇宙的,必须选好分支。
如果你有一个猜想,但是又和你的目标关联不太大,那就坚持这个猜想,直到出现明显反例。物理学有很多这样的例子,和数学不同,为了旁支猜想投入过多研究是不明智的。
如果有明显证据证明你的某个旁支猜想大错特错,你就要放弃主要目标,暂时把解决旁支猜想作为主要目标。比如,你本来以为某个结构是LRU的cache,结果发现怎么做都不对,那就先放弃原来的目标,专门研究这个结构的用途。
对于旁支猜想的不断切换,要做好自己的task stack保留。在旁支猜想解决之后,要根据结论尽快回到上次中断的任务。

第一,找准入口出口,不要直接跳进去看,任何代码都有触发点,无论是http request,还是服务器自动启动,还是main函数,还是其他的,先从入口开始。第二,手边一支笔一张纸,除非你是Jeff,否则你不会记得那么多跳转的。一个跳转就写下来函数/方法名和参数,读完一遍,就有了一个sequence diagram雏形第三,私有方法掠过,只要记住输入输出即可,无需看具体实现

1.先搞清程序的流程和整体框架。模糊的地方可以尝试进行修改看效果,有debug工具的话最好。2.定位。找到需要了解的具体功能实现模块。工具方法也可如上。3.分析。对需要的具体的代码进行详细分析。搞清变量的意义和关联关系,搞清实现的逻辑和算法。好的代码,此处最需要注释。

一般阅读非自己写的代码都是关注某一部分代码块,比如某一条流程线。如果这份代码让你看的眼花缭乱,条件允许的话最有效地方法就是进行debug调试。一步一步的跟进调试会让你很流畅的根据代码的执行步骤了解代码的逻辑。如果无法debug调试的话,我会从最浅层的代码层入手,理清思路,先不去关注深层的逻辑或者函数,需要使用到得时候在去仔细查看。

如果是C++的话,VS可以生成UML的类关系图,由UML图去看关系比较清楚,即使不用VS,也有很多软件可以从代码生成UML图,看面向对象的代码,搞清楚有多少类,每个类的接口是什么,继承关系,依赖关系,VS的类图可以通过双击直接跳转到目标代码,分析起来也会很方便。看项目的源代码主要的难点是整理清楚整体的逻辑关系,具体实现可以先不去看,配合UML用笔把把整体依赖关系在之上画写清楚,哪些类是做什么的也要写一写,如果只看不记,就像走马观花,今天可能有点感觉了,明天就会忘记,因为很多代码依赖关系错综复杂,笔记配合UML是最好的入门方法了。多问自己几个为什么,它为什么要这么封装,为什么要分离,为什么要用模板?然后阅读的过程中去一一解开这些问题,代码就渐渐懂了。当然,有些时候实现可以有多种方式,也不用太转牛角尖,非要思维和作者达成一致,只要合理即可。

单元测试
在这个页面上搜索了一下,发现提到单元测试的人很少,所以我觉得很有必要强调一下。
思路
我觉得得从开发者的角度去阅读程序源代码,从一开始就不要抱着学习的心态。去改进它。

作者:豆包
链接:https://www.zhihu.com/question/19625320/answer/105942481
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

  1. 首先你得找本入门资料,最好是中文的,这样可以了解基本术语,知道变量的意思是啥,这样阅读代码里注释时方便快速理解。 2. 有一个好的调试工具,Libgdx 可以导入Eclipse或者Android Studio,因此我一直用Eclipse看代码,方便快速定位方法和变量。3. 每个源代码里基本都有demo 和 WIKI,将demo运行起来,结合WIKI 不断的修改里面的方法和变量,这样就清楚的知道每个API的作用。这绝对是帮你快速入门、了解API作用的不二法门。4. 了解API之后自己写简单的demo,加速自己对框架的理解和记忆。 5.现在我们要深入源码,根据步骤 3 进入每一个源文件,先阅读注释,然后看每个API实现方法。(其实要不自己写框架,只需要理解API具体做什么就可以了) 了解框架所用的数据结构,最好再去看具体的实现步骤,这个真是太难了^^ 6. 根据步骤自己写一个教程/笔记,这个过程是一个查漏补缺的过程,也方便你加深记忆。目前我正在写一个关于Libgdx的教程: Libgdx教程目录 7. 最后一点,但是也是很重要的一点,必须具备一些额外相关知识:要掌握Libgdx的源码最好知道 设计模式 的相关知识,了解OpenGL的知识更好了,我就因为不懂,导致走了很多弯路。

程序=数据结构+算法
首先搞清楚程序中的数据结构有哪些,数据的组织形式是怎样的
然后搞清楚程序使用了哪些运算,以及哪些数学模型和算法

如果你方便调试的话,最好就是在调试过程中进行阅读。在你想要重点阅读的地方加上断点,然后进行调试。在调试过程中可以清晰看到调用过程以及变量的变化。不过你最好应该先对整个程序有一个大体了解,不然看到调用栈(call stack)里一堆不熟悉的方法或者函数,也够头大的。 如果不方便调试,比如linux内核,你可以使用一些源代码阅读工具。比较有名的是source insight,或者Understand for c++,它们共同的特点是通过为函数啊变量啊建立符号存档来快速定位浏览,并且支持显示某一个函数的调用过程。总之source insight真的是一个很强大的软件,你可以试用一下。 不过不管哪种方式,先看一下程序的总体说明,源码的组织结构等都是很有用的事情。

首先声明,我看到源代码都是面向对象语言的。下面是我读源代码的方式:1 从这个软件最核心的API开始,先使用UML里的类图建立静态结构,分析出类与类之间的关系(继承,组合,实现,依赖,关联等等)2 使用UML里的活动图,配合IDE工具分析核心业务流程,理解软件是如何工作的。3 从设计模式角度思考这个软件为什么要这么设计4 自己写unit test来调试源代码(这一步其实可以和1,2,3并行执行)

最好有当次阅读目标。为了解决/理解一个什么问题而看源代码(也可以在记事本上写下问题列表)。一次一个问题,目标明确,不容易晕菜。当次阅读所遇到代码的数据结构(接口/数据类),有时间的话可以理清楚。一张大纸,一支多色笔,草图。理解源代码就像是理解一帮子有性格的人,代码没有完美的,不要老想着为了理解而去修改既有代码,理解是理解,重构是重构,两码事儿。
遇到“大”、“长”、“乱”的方法,不要烦躁,可以尝试先找这个方法的输入输出,然后从输出往前,寻找重点代码,一步步分析。

下载源代码,建工程编译,读系统的概要涉及,大体了解各模块的功能。
从单元测试入手, 可以帮助你更快掌握代码。

阅读源码 对于可直接编译调试的代码 更改 添加log 编译 运行看效果 是最佳途径对于代码框架 前人的文档也是不错的参考 若没有 那么各个IDE的call tree生成功能也是很方便的.对于逻辑冗杂的代码 代码折叠功能也是分析利器中文注释也是方便记忆回溯整合的利器 便于统筹理解 可惜的是公司大部分要求英文注释

先找到软件功能需求,也就是这个软件包是干什么的,然后找到合适的IDE,编译查看效果。最后就是从主函数开始一点一点往下看了呗,遇到封装的函数语句就看进去怎么实现的。

工具

  1. Source Insight
  2. Understand

参考资料:
https://www.zhihu.com/question/37240878
https://www.cnblogs.com/ToDoToTry/archive/2009/06/21/1507760.html
https://www.codedump.info/post/20190324-how-to-read-code/

部署
https://www.jianshu.com/p/de61298316b2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值