如何高效阅读源代码?

2024-05-04 22:42

1. 如何高效阅读源代码?

 下面是之前写的一篇文章:《如何快速阅读源码》
   本文探讨在需要了解一个开源项目时,如何快速的理清开源项目的代码逻辑!  
   以下是个人认为行之有效的方法:
   本文以Mybatis为例来进行演示!
   先“跑起来”   程序界有个老传统,学习新技术时都是从「Hello World」开始的!无论是学习新语言时,打印「Hello World」;还是学习新框架时编写个demo!那为什么这里的「跑起来」要打个引号呢?
   实际上,当你想要阅读一个开源项目的源码时,绝大部分情况下,你已经能够使用这个开源项目了!所以这里的“跑起来”就不是写个「Hello World」,也不是能跑起来的程序了!而是能__在你的脑子里「跑起来」__!什么意思?
   Mybatis你会用了吧?那么请问Mybatis是如何执行的呢?仔细想想,你能否用完整的语句把它描述出来?
   这里是Mybatis的官方入门文章!你是如何看这篇文章的?读一遍就行了吗?还是跟着文章跑一遍就够了吗?从这篇文章里你能获得多少信息?
   我们来理一下:
   回答出了上面这些问题!你也就基本能在脑子里把Mybatis「跑起来」了!之后,你才能正真的开始阅读源码!
   当你能把一个开源项目「跑起来」后,实际上你就有了对开源项目最初步的了解了!就像「 书的索引 」一样!基于这个索引,我们一步步的进行拆解,来细化出下一层的结构和流程,期间可能需要深入技术细节,考量实现,考虑是否有更好的实现方案!也就是说后面的三步并不是线性的,而是__不断交替执行__的一个过程!最终就形成一个完整的源码执行流程!
   自顶向下拆解   继续通过Mybatis来演示(限于篇幅,我只演示一个大概流程)!我们现在已经有了一个大概的流程了:
   虽说每个点都可以往下细化,但是也分个轻重缓急!
   很明显,SqlSession去执行 sql才是Mybatis的核心!我们先从这个点入手!
   首先,你当然得先下载Mybatis的源码了(请自行下载)!
   我们直接去看SqlSession!它是个接口,里面有一堆执行sql的方法!
   这里只列出了一部分方法:
     
   SqlSession就是通过这些方法来执行sql的!我们直接看我们常用的,也是Mybatis推荐的用法,就是基于Mapper的执行!也就是说「SqlSession通过Mapper来执行具体的sql」!上面的流程也就细化成了:
   那SqlSession是如何获取Mapper的呢?Mapper又是如何执行sql的呢?
   深入细节   我们来看SqlSession的实现!SqlSession有两个实现类SqlSessionManager和DefaultSqlSession!通过IDE的引用功能可以查看两个类的使用情况。你会发现SqlSessionManager实际并没有使用!而DefaultSqlSession是通过DefaultSqlSessionFactory构建的!所以我们来看DefaultSqlSession是如何构建Mapper的!
     
   它直接委托给了Configuration的getMapper方法!
     
   Configuration又委托给了MapperRegistry类的getMapper方法!
     
   在MapperRegistry类的getMapper中:
   在这里knowMappers是什么?MapperProxyFactory又是什么?mapperProxyFactory.newInstance(sqlSession)具体做了什么?
   其实很简单,knowMappers是个Map,里面包含了class与对应的MapperProxyFactory的对应关系!MapperProxyFactory通过newInstance来构建对应的Mapper(实际上是Mapper的代理)!
   快接近真相了,看mapperProxyFactory.newInstance(sqlSession)里的代码:
     
   这里干了什么?
     
     
     
   最终实际还是委托给了sqlSession去执行具体的sql!后面具体怎么实现的就自行查看吧!
   延伸改进   现在我们的流程大概是这样的一个过程:
   现在我们大概知道了:
   那么,
   这个问题列表可以很长,可以按个人需要去思考并尝试回答!可能最终这些问题已经和开源项目本身没有什么关系了!但是你思考后的收获要比看源码本身要多得多!
   再循环   一轮结束后,可以再次进行:
   不断的拆解->深入->改进,最终你能__通过一个开源项目,学习到远比开源项目本身多得多的知识__!
   最重要的是,你的流程是完整的。无论是最初的大致流程:
   还是到最终深入的细枝末节,都是个完整的流程!
   这样的好处是,你的时间能自由控制:
   而不像debug那样的方式,需要一下子花费很长的时间去一步步的理流程,费时费力、收效很小,而且如果中断了就很难继续了!
    总结    本文通过梳理Mybatis源码的一个简单流程,来讲述一个个人认为比较好的阅读源码的方式,并阐述此方法与传统debug方式相比的优势。
   阅读源码是每个优秀开发工程师的必经之路,那么这篇文章就来讲解下为什么要阅读源码以及如何阅读源码。
   首先来说下为什么要读源码,有学习源码的必要吗?
   为什么要阅读源码?
   关于为什么阅读和学习源码,我个人认为可能有以下几点:
    (一)吊打面试官,应对面试 
   为了找到更好的工作,应对面试,因为在面试中肯定会问到源码级别的问题,比如:为什么 HashMap 是线程不安全的?
   如果你没有阅读过源码,面试官可能会对回答的结果不满意,进而导致面试结果不太理想,但如果你对源码有所研究,并能够很好地问答面试官的问题,这可能就是你的加分点,可以形成自己独特的竞争力,吊打面试官,升职加薪不是梦。
    (二)解决问题(bug) 
   在开发过程中,我们或多或少会遇到 bug,比如:在 foreach 循环里进行元素的 remove/add 操作,为啥有可能会报 ConcurrentModificationException 异常?
   我们可以先在 Google、Stack Overflow 以及对应项目的 Issues 里看有没有类似问题以及解决办法,如果没有的话,我们只能通过阅读源码的方式去解决了。如果我们对相关源码有所涉猎,就可以快速定位到问题所在。
    (三)提升编程能力 
   和阅读一本好书一样,阅读源码就是和编程大牛面对面交流的机会,在许多优秀的开源项目中,它们的编码规范和架构设计都是很棒的,另外在设计上也使用了大量的设计模式,通过阅读和学习源码,能够快速提升我们的编码水平,以及对设计模式有更深的理解。
   同时,在我们阅读完一个源码后,可以触类旁通,能够快速地对其他框架的源码进行阅读和学习,减少时间成本。
   除了上述提到的原因之外,可能还有许多,在这里就不一一赘述了,那么在确定了要阅读源码之后,就让我们看下如何阅读源码吧!
   如何阅读源码?
   如何阅读源码取决于你为什么要读源码,比如:
   下面大概说下阅读源码的几点建议:
   在阅读之前,可以先从开源项目的官网上看它的架构设计和功能文档,了解这个项目的 整体架构、模块组成以及各个模块之间的联系 。
   如果没有对应的项目文档,可以根据代码的模块进行梳理,以形成对项目的初步了解,或者 查看已有的源码解析文章或者书籍 ,在阅读源码之前,了解项目的架构和思路会使阅读源码事半功倍。
   在了解一个类的时候,可以使用 ctrl+F12 来查看类中的成员变量和方法。
   可以通过 IDEA 的 Diagrams 功能去了解一个类的继承关系。
   多打 断点调试 ,断点追踪源码是很好的阅读源码的方式,可以先通过 debug 了解下调用逻辑,都和哪些类有关联,有大致了解后再通过 debug 了解整体代码的功能实现,各个类都起到了什么作用,有没有涉及到设计模式等。
   另外,优秀的开源项目中肯定会有许多地方应用到了 设计模式 ,建议在阅读源码之前,需要对常用的设计模式有大致的了解,不然阅读源码的效率会大大降低。
   如果遇到读不懂某部分源码的时候,可以先跳过,之后再回来看,如果属于搞不懂这部分就茶不思饭不想的人,可以在网上找是否有该部分源码的解析或者文档,也可以自己通过 源码注释和测试用例 去阅读学习。
   一般优秀的开源项目都会有 单元测试 ,可以通过对应类的单元测试去了解方法的含义和用法,加深对源码逻辑的理解。
   在阅读源码的时候,可以在代码上加上 注释和总结 ,同时还可以画出 时序图和类图 ,这样对阅读源码有很大的帮助,可以很清楚地知道类之间的调用关系和依赖关系,也方便以后回顾,重新阅读。
   在这里推荐大家一个 IDEA 插件 SequenceDiagram,可以根据源码生成调用时序图,便于阅读源码。
   刚开始阅读源码,不建议直接看框架源码,可以先从 jdk 源码看起:
   jdk 源码也是非常庞大的,可以分模块来阅读,下面是建议的阅读顺序:
   其他包下的代码也可以做下了解,JDK源码阅读笔记:https://github.com/wupeixuan/JDKSourceCode1.8
   再有了一定的源码阅读经验后,可以再去学习 Spring、Spring Boot、Dubbo、Spring Cloud 等框架的源码。
   总结   主要介绍了为什么读源码以及如何读源码,供大家参考,每个人都有适合自己的阅读源码的方式,希望可以在学习中去摸索出一套属于自己的方式。
   阅读源码不是一蹴而就的,这是持久战,只要你能够坚持下来,肯定受益匪浅。阅读源码的过程比较枯燥,可以在社群里一起讨论学习,这样可能效率更高些。
     没看过源代码,都不好意思出来说了,最近刚好在看一些,来说一个。
   先看使用  https://element.eleme.cn/#/zh-CN/component/installation     
   先看一下这个库是做什么用的,然后提供了哪些功能。
   看GitHub https://github.com/elemefe     
   一般会看下项目最新的情况,然后没有关闭的issue,看下wiki,大家在讨论什么。
   再看代码     
   clone 一份到本地,然后先看下目录结构,然后根据文档看几个简单的组件的时候,一边看掘金上的分析,一边自己看下实现。
     
   e le
   饿了么这个框架代码结构还是很清楚的,基本上每个组件都是分开的,所以你只要看其他的一个文件夹就行。然后一些工具的都在src文件夹。
     
     
   要学会看issue,一般开源的项目都有人会来提建议,有些是bug,有些是功能,你可以看看自己是否有能力去解决,如果可以的话,你可以去fork代码,然后自己修改,再提pr。
     我最近恰好找摸索出一个梳理遗留系统架构的技巧:自底向上 找到一个典型的切面 沿着调用和回调的路径 在代码中添加结构化注释(比如eclipse中加//TAG 流程A1.1 甲->>乙),这样便得到了一个code地图,并且在tasks视图中看起来很直观(看起来跟书的目录一样)可快速跳转。将目录copy到有道云笔记的markdown序列图中 就自动生成了一个序列图。
   我觉得这基本上就是可缩放的可视化架构地图了,对维护一个比较乱和庞大的遗留系统非常有帮助,定位代码 修改维护都方便多了。
   1、需要过硬的基础知识,这个前提。不然基本语法、常用的模式都不晓得怎么读。
   2、多参考 历史 版本和更新变化,好的源码都是反复迭代出来的精华,开始就读精华是很不明智的,所以看看版本更新说明,版本的 历史 演变。就想人一样是怎样进化过来的。
   3、参考别人阅读注释,想必在你读源码之前也有人读过了源码,并且总结,注释。和分享原理,可供你参考,毕竟每个人读一篇文章,理解的东西是有差异化的。
   4、直接买书,有些作品直接出书就是源码精解
   5、找个大神给你慢慢分析,这个最快。娓娓道来,直接面授比啥都强。缺点是,你容易跟着他的思维走下去。
   我觉得阅读代码就不应该高效,而应该像看小说一样,看的过程就像是在和作者交流,有趣才是看代码的动力。
   画图,看数据走向,逻辑走向
   
   先弄清楚这些代码实现了哪些功能,然后从主线开始往下看,好的代码光看变量和接口名称就能明白是什么意思?扒出源码实现的整体框架逻辑,然后再对自己感兴趣的模块进行剖析,还是从整体把握,细节深入,慢慢地整个框架就被丰满了。
   接下来是思考为什么要如此设计,这样设计的好处是什么?如果是你来做应该怎么设计,把你觉得源码缺点的地方进行仔细研究,了解里面是否包含自己不清楚的细节,避免遗漏。
   接下来就是根据代码改造或者是调试错误,对于源码中遇到的不理解的地方一定要弄明白,有的确实是画蛇添足,有的有独特的作用。
   多多学习,对每一种主流框架铭记于心,对主流设计模式了如指掌,万变不离其宗,源码看多了,跟看一个电视机遥控器的操作说明一样。
   
   1、一边阅读代码一边写注释。这是我用过的最好的方法,对代码理解得更深入,看一些重要代码或者特别难懂的代码时挺有用。更何况,注释也是一种文档嘛。
   2、一边阅读代码一边绘制UML。这个方法适用于类之间的关系较复杂和调用层次较深的情况,我一般都是先绘制顺序图,然后为顺序图中的类绘制关系图。
   3、通过Debug来跟踪程序的主要执行过程,这样就可以分清主次了,阅读的时候更有针对性。
   4、类的快速阅读。先弄清楚它在继承链中的位置,看看它的内部状态,也就是成员变量,一般来说,类的对外接口都是对成员变量的访问、加工、代理等,然后看看它的对外接口,也就是公有成员函数,识别核心的一个或多个函数,这时候你应该可以大概了解这个类的职责或作用了。可能这个类是某个设计模式中的一个组成部分,所以,设计模式的掌握对代码的快速阅读也是很有帮助的。
   5、带着问题去阅读。比如想了解android中的消息机制,那么看看Looper、Handler、MessegeQueue这几个类就可以了,其他的不要去看,要不然就跑题了。
   下面列几个阅读源码时所处的情景,在特定场景下用哪些方法:     不太熟悉业务逻辑,还不是很清楚它是干啥的,可以用3、5。     代码量很大,有几十万行,甚至百万行,可以用2、3、5。     你无法看见程序的运行过程,比如没有用户界面,也有可能是无法运行的,可以用3、5。     设计复杂,用了大量的设计模式,调用链很深,可以用1、2、3、4、5。     时间有限,没有那么多时间让你看源码,可以用3、5。
   画出逻辑流程图,先了解整体流程,再详解具体函数

如何高效阅读源代码?

2. 如何阅读源代码

最近有做源码阅读的事情,觉得有些费尽,做了一些思考。
一个大项目的源代码,不要过份详细的阅读。大项目,其代码量基本上是可以吓死人的。过份的关注细节,常常会拘泥于细节,而忽略了整体框架。当你能够看清框架的时候,亦花费了太多的时间。
因此,阅读一个大项目的源代码,其目的不在于欣赏代码细节,而在于迅速看清项目整体框架的大概面貌:都有那些模块,这些模块是干嘛的(不关心具体怎么干),模块之间的通讯机制大概是怎样的,然后在考虑子模块,通常只要掌握两级子模块就够了。花上1,2天的时间掌握这一切,就达到了阅读大项目源码的目的。因为一旦你掌握了框架,你就可以按照这个框架实现这个项目,虽然和原项目全然不同,但是完成的需求却是一样的。
在软件中,架构才是本质。
也许你指望详细阅读大项目源代码能看到高质量的代码,但是,大项目通常都是团队的劳动成果,每个人的不同水平造就了代码质量的高高低低,一个人在不同时间不同环境的代码质量也是不同的。要指望在大片源码面前找到高质量,简直是天方夜谭。
也许你要从阅读源码中掌握某项技术细节,比如bsp,又或者换装,那么,最好的建议是查找相关的技术文档以及文档上所附带的sample code,这种sample code一般不会附带任何干扰,简洁得只是为了证明该技术而存在的。如果没有这些东西,而只能从大项目源码中找的话,你提前先了解了框架,能更快的查找和定位到表达该技术的文件。但是通常都会比较不幸,因为你为了明白这一技术,通常要先理解混入其中的另一技术。
最后谈谈怎样才能阅读到高质量的源代码。何谓高质量?是指算法出人一表(比如某种o(1)的排序法)?还是采用了极端深奥的语言特性将某实现完美表达(比如模板的灵活运用)?无论是哪种,最好的来源是书,如《STL详解》,或者《inside XX》这样的东西。书的作者通常就是这些高质量代码的作者,他会带领你探索这些源码背后的真相。

3. 如何阅读开源代码

通过阅读开源代码,可以学习其中的框架和模式、代码技巧、算法等。但是经常有些人拿到开源代码以后不知道如何下手,这里分享一下我的一些经验。
1.拿到代码以后编译运行它,了解它干什么的,实现了功能。
2.从入口点开始阅读,按照流程,了解这个软件是怎么运行起来的。
3.从整体上观察这个软件是有哪些模块组成的,最好能画一画图。
4.修改软件的功能,并且能够调试它。不能仅仅停留在阅读代码上,一定要改代码,这样才能增加对开源代码的理解。
5.做笔记,把这个开源代码实现的功能,实现方式、设计框架、模块组织、以及代码技巧等记录下来。

以上,这些仅仅是我个人的经验,希望可以帮组到您。

如何阅读开源代码

4. 如何阅读开源项目代码

基本功什么的就不在此赘述,进入正题
1.运行
如果是一个工程的话,建议首先自己运行起来。只有运行起来看到效果之后才方便之后打断点DEBUG调试。
过程之中也许涉及到各种环境啥的搭建,可能过程很苦逼,很耗耐心和意志。总之,没有什么困难能够阻碍你,如果你真的想要去做的话。
2.入口点
找到程序的入口点,方便跟进。算是毛线球暗藏的那个线头,找到之后只管拽就肯定能拆解。
3.把对的改错,再想办法绕开
个人没有实践过,不过日常开发过程中倒是经常碰到把对的改错了。纠错再改正的过程确实能够让自己对系统有更一步的了解,并且记忆深刻。
4.模块化阅读
将整体系统划分成不同的模块,再逐个解决。此处的意义不是具体一个项目功能模块的意思,而更倾向于在抽象一层理解,如网络层,缓存层,持久化层……
5.个人化
换了一个词表示“使用”,自己动手去使用,去实现,去架构。只有这么做了才能真正体会到自己哪里还不会。
6.跟“人”沟通
其意义很重要,书籍上确实东西能够起沉淀很多有意义的东东,但是很多实际使用过程中遇到的问题还需要向大神请教,途径包括公司资源,包括外网论坛博客啥的。
以上主要是提供一个思路,经过自己这段时间的实践,发现确实能给黑暗中的自己一个摸索的方向,并且有一定的效果。
另外还有几点,不知道插在哪一步进行说明,就没有总结在下面了
多思考,为什么要写成这样,这样写有什么好处。
注重Demo&Sample,很多使用上经验可以学习。
阅读代码时最好分两遍进行阅读,第一遍主要熟悉代码结构,了解流程,划分模块;第二遍再注意细节,分模块的进行熟悉。
一定要记住的是,回味,总结,沉淀。只有转化成为自己理解的东西之后,才能算学会了,时间才没白费。
最后说一下,尽可能的在代码中找答案。跟别人沟通(当然除了跟代码作者本人沟通外)只能进行经验的交流,别人所输出的是经过他的理解和加工之后的,不见得一定是对的。

5. 如何读懂源代码

(1)了解对应编程语言的基本语法结构 ;
(2)多看代码;
(3)别光看, 注意分析, 抓住主脉络. 看的同时应该画画程序的流程图, 结构图, 抓住关键变量, 结构体或者类的内容, 理清关键数据的交换关系;
(4)尝试修改. 定义一个新功能, 尝试在源码上修改. 当你尝试更改后, 会更容易在实践中深入的体会源码的思想.
(5) 如果是算法类的源码, 那有必要先去了解算法的基础理论知识.

如何读懂源代码

6. 如何阅读源代码

这样阅读源代码:
1、你会懂的这些代码是什么意思,点击右键

2、点击查看网页源代码,就会出现一些代码

提示:专业人士才能看懂的

7. 如何阅读程序源代码

阅读源代码的第一个工具,就是你手中的code base。把它编译出来,运行它,加log,试着修改一些数据和代码,看看有什么变化。

第二个重要的工具就是debugger,而debugger最重要的功能是获取call stack。在你感兴趣的use case里pause一下,在你不知道有什么用的函数里加个断点,显示出来的call stack都能让你对系统有更清晰的认识。

一个软件系统就是一个小宇宙。别期待有什么高明的文档。要把自己当成探求自然真理的物理学家。

必须找好切入点。你要解决什么问题。是要fix bug;还是要把这个系统和其它模块集成;还是要增加新功能。物理学家没有上来就研究整个宇宙的,必须选好分支。
如果你有一个猜想,但是又和你的目标关联不太大,那就坚持这个猜想,直到出现明显反例。物理学有很多这样的例子,和数学不同,为了旁支猜想投入过多研究是不明智的。
如果有明显证据证明你的某个旁支猜想大错特错,你就要放弃主要目标,暂时把解决旁支猜想作为主要目标。比如,你本来以为某个结构是LRU的cache,结果发现怎么做都不对,那就先放弃原来的目标,专门研究这个结构的用途。
对于旁支猜想的不断切换,要做好自己的task stack保留。在旁支猜想解决之后,要根据结论尽快回到上次中断的任务。

复杂的软件系统更像一个动物,待久了你会了解它的脾性。有些是通过逻辑,有些是通过感觉。玩车的尚且有这种感觉,我们玩的东西比车复杂上万倍,就更不能对它缺乏感情投入。(这也是我不爱做企业开发的原因,我不爱养个爬行类当宠物,还是猫猫狗狗的亲切。)

如何阅读程序源代码

8. 怎样阅读源代码,怎样提高阅读源代码的效率

为什么你读书和没读一样?快来试试这个方法吧~