Java
C(编程语言)
C++
搜索引擎

有哪些高效阅读源码的技巧?

有哪些高效阅读源码的技巧?
关注者
1,084
被浏览
225,380

38 个回答

来看看这篇阅读开源项目源码的文章,不止有源码阅读技巧,还有适合阅读源码的开源项目推荐!


如今大多数的程序员技术栈和工具箱里,或多或少都有开源项目的身影:大到操作系统、小到精美的图标,优秀的开源项目就像“神器”可以让程序员所向披靡,快刀斩乱麻。但强大的“神器”也带来了一些问题,如果“神器”使用得不熟练或姿势不对,就会出现难以解决的 Bug 和问题,这个时候常见的解决方法:

  1. 问搜索引擎
  2. 查文档
  3. 提 issues

如果上面的方法都没能解决,那就只能自食其力阅读源码,寻找解决问题的办法了。虽然这条路道阻且长,但源码面前没有秘密。同时经过源码的历练你也一定会变得更强,有的时候走慢些才能发现之前错过的“风景”。

今天 HelloGitHub 就带来了多个知名开源项目的源码注释和源码阅读笔记,带你阅读源码、点亮阅读源码的技能,这些项目涵盖:C、C++、Java、Go、Python、JavaScript 编程语言,总有一款适合你。

虽然有的项目已经很久没更新,阅读的版本也已经过时,但是里面的知识依旧闪闪发亮! 最后,要带着问题去源码里找答案,否则很难坚持下来。

深入源码掌握核心技术,才能不止步于应用层面。

走慢些,踩深些。

C 语言

1、redis-3.0-annotated(Redis)

Star 数:7.9k|语言:C

Redis 是一个基于内存、分布式、可选持久性、开源的 KV(键值)存储数据库。

该项目是 Redis 3.0 版本源码注释。

github.com/huangz1990/r

2、linux-0.12(Linux)

Linux 是一种开源的类 UNIX 操作系统。

该项目是 Linux 内核 0.12 版本完全注释版。

我最初是在 GitHub 找到了别人上传的旧版(0.11)注释源码,一通搜索下发现了原作者赵炯老师的网站。第一版发布于 2003 年,最新更新于 2021 年,维护了 18 年。这个阅读 Linux 源码的项目,虽然没有上传到 GitHub 但是内容、注释的源码、配套工具全部开源。

oldlinux.org/Book-Lite/
PDF: oldlinux.org/download/C

C++

3、reading-source-code-of-leveldb-1.23(LevelDB)

Star 数:15|语言:C++

LevelDB 是一个由 Google 开源的持久化 KV(键值)存储数据库。

该项目是 LevelDB 1.23 版本源码阅读笔记,包括:分析 DB 运作流程、STable 等文件格式以及 Compaction 过程。

github.com/SmartKeyerro

Java

4、spring-analysis(Spring)

Star 数:10k|语言:Java

Spring 框架是一个开源的 Java 全栈应用程序框架和控制反转容器实现,多用于构建企业级 Web 应用。

该项目是 Spring 4.3.18 版本的源码阅读笔记,包含源码注释、类图、文字描述。

github.com/seaswalker/s

5、learn_netty_source_code(Netty)

Star 数:1k|语言:Java

Netty 是一个 Java 异步事件驱动的网络应用框架。

该项目是 Netty 4.0.33 版本源码分析教程。

github.com/yongshun/lea

Go

6、grpc-read(gRPC)

Star 数:154|语言:Go

gRPC 是 Google 发起的一个开源 RPC 系统,基于 HTTP/2 协议传输,使用 Protocol Buffers 作为接口描述语言。

该项目是 gRPC Go 版本实现:grpc-go 的源码解读。

github.com/lubanproj/gr

Python

7、annotated-py-projects

Star 数:312|语言:Python

该项目包含多种 Python Web 框架源码解读,包括:Flask、Sanic、web.py 等项目的源码注释。

github.com/hhstore/anno

JavaScript

8、learnVue(Vue.js)

Star 数:11k|语言:JavaScript

Vue.js 是一个用于创建用户界面的开源 JavaScript 框架。

该项目包含 Vue.js 源码注释以及作者学习 Vue.js 源码过程中的一些心得和收获。

github.com/answershuto/

9、react-illustration-series(React)

Star 数:1.3k|语言:TypeScript

React 是一个声明式、高效且灵活的用于构建用户界面的 JavaScript 库。

该项目是以图文的方式解读 react@17.0.2 源码,包含大量配图。

github.com/7kms/react-i



HelloGitHub官网改版上线啦,欢迎大家使用并提供宝贵意见❤️

HelloGitHub 想让更多人爱上编程、开源,所以一直在尝试、摸索如何可以帮助到更多的人。目前HelloGitHub 交流群已全面开放,关注 HelloGitHub,添加:HelloGitHub 为好友入群,可同 CC++JavaGoPython、前端 机器学习等各界大佬谈笑风生、切磋技术~ 还有大学生开源群,叫上你的小伙伴一起感受开源的乐趣吧!

这里是 HelloGitHub 分享 GitHub 上有趣、入门级的开源项目。

编辑于 2022-10-24 13:40

去年,我读了四个开源项目的源码,来分享下心得吧。

四个开源项目分别是: RocketMQ、Kafka、Dubbo 、Tomcat。

其实还看了一点点 Linux、Redis、jdk8,这几个阅读的目的和上面几个是不同的,下面会提到。

相信通过我的分享你不会被源码轻易劝退,其实没什么,不就是代码吗?

而且你一直在看源码,可能你没意识到,你看别人的代码不就是源码?

你新入职一个公司要熟悉代码的时候不就是看源码?

这和你看开源框架源码没有本质的区别,要真说区别无非是代码的质量、整体的设计区别罢了。

那时候你怎么做的?

反正最终结果你应该都是上手了的。

那就得了,开源框架的一样,最终你也会上手。

所以没啥好怕的,不要被劝退了。

我先分享一下我入职一家新公司接手项目的时候是怎么做的。

入职新公司接手项目就是在读源码

新入职接手项目的时候,我先拉上了产品经理和原先这个项目的主力开发开了个会。

这个会的目的就是让产品经理介绍一下这个项目的背景、要解决什么问题、有哪些功能。

开发在旁边补充、解答我的疑惑,毕竟产品经理不太了解细节上的数据交互。

这个会议下来你就能得知这个项目到底是干嘛的,能提供哪些功能。

业务上的理解对你之后读源码非常的重要!!

然后我会去要文档、架构图、流程图、时序图等等(有多少要多少,没的话没办法)。

看完之后对整个项目有了大致了解。

然后让项目跑起来,跑起来之后,开始用这个软件,各种功能点一点,毕竟听产品经理说和自己实际用还有有区别的。

基本上项目主流程都过了一遍之后,开始看源码。

这个时候看源码,单看文件的命名其实已经能知道这个文件对应着哪个模块了,有种胸有成竹的感觉。

然后具体深入细节就看分配到的任务了,几个需求接下来渐渐地细节就都全清楚了。

稳了。

所以入职接手项目是需要了解背景、总览全局然后再细化。

读开源项目的源码也是如此,自顶向下。

如何高效阅读开源项目的源码

读源码我个人分为两种情况:为了提升自己和为了找问题。

为了提升自己而读源码

我默认你是知道你要看的开源项目是干嘛的,比如 RocketMQ 是消息队列,消息队列是干嘛的你应该先知道。

我也默认你用过这个开源项目,业务上没用过自己私下也要先用用,了解简单功能怎么用,让它先跑起来。


首先看官网、wiki。

我截个 RocketMQ 的:

了解具体涉及到的概念、名称、特性、架构这是第一步。

这一步能让你脑子里有个角色分布图和数据流转图,让你明白整体项目的主要角色及之间的交互。

然后看源码目录,你得先知道每个目录是干嘛的涉及哪些功能,这其实和你看业务源码一样。

然后就是找突破口了,这种开源项目都有 demo ,跑,打断点就完事儿了!

比如 RocketMQ 的:

比如 Dubbo 的:

这就是突破口。

然后就开始了源码之路了,是的还是得自己啃,硬啃,这是读源码的必经之路!

但是这时候你不是像无头苍蝇一样乱啃。

你是在知晓大体会涉及到的角色和数据流转之下读源码,这很不一样!

你会对一些方法调用有一种“认可感”,因为你知晓大致的流程,所以觉得本该如此。

读源码有时候会觉得代码很多,分支好多。

没事,先拷贝一份,然后把一些异常处理和不常见的分支先删了

整体核心流程先理清楚!

并且理清楚了一个流程之后开始画图,流程图、脑图都上。

清楚之后再看没删减的代码,把异常处理的一些也理解了,补充完整流程图、脑图等。

看看我之前分析 Kafka 的时候画的图,就类似这样的搞清楚一个流程:

然后这一模块就收工了!搞定!

然后各种分支发散出去,大致的流程就都清晰了,源码也就读的差不多了。

读源码的时候也会遇到一些不能理解的,先略过,主流程先搞懂。

搞懂整体核心流程之后可以抠一些细节了,比如我之前看 Dubbo 的时候就抠了一个

再比如之前看 Kafka 的索引设计涉及到二分查找,但是源码中是改版的二分查找。把索引项分为热区和冷区,深究下去是为了避免缺页中断。

再比如 RocketMQ 里面看预热文件的时候涉及的这个方法。

这时候又涉及到 mlock、madvise 。

这些就是细节,而细节往往就是我们需要学习的地方,所以在理清整体流程之后不要错过细节。

往往你觉得很奇怪的地方可能就是一些“骚操作”,学的就是“骚操作”。

这一趴读源码是为了让自己得到晋升、学习学习优秀开源框架是如何设计而读的源码。

为了找问题而读源码

这个目的性很强,有时候是项目出错,一般而言有日志,所以通过日志搜就行。

如果你本身对这个框架很熟悉那当然最好,如果不熟悉通过日志搜索结合上下文其实也能找到一些缘由。

不过有时候还是得整个链路分析下来才能排查问题,这个看功力了。

有时候是因为看到一些文章的说法冲突了,一篇说 A 另一篇说 B 。

如果你找不到权威的信息你只能自己去看源码,通过关键字搜

比如我 这篇写的

这就是源码之下无秘密。

这种目的性很强的读源码就是结合当时上下文和靠个人功力了。

最后

不知不觉说了这么多。

我只能告诉你不要被源码劝退,你其实一直在看源码。

然后要自顶向下的看源码,不要一头就钻进细节,先从官网等渠道对开源框架有个全面的了解,然后看源码理清主流程。

再配合流程图、时序图、脑图等记录、归类。

然后再看细节,学学优秀开源框架的“骚操作”。

模仿它,学会它,从中能延展出很多额外的底层知识,比如上面提到的缺页中断,预热锁页,分支预测等等。

当然也可以先去网上搜一搜别人的源码分析文章,比如我之前的一些,然后自己再上手,这样会比较舒服和顺利。

我的文章都汇总到这个仓库了,里面有很多消息队列等中间件的原理解析和面试题汇总,自荐一波~

然后还有一些相关的付费专栏,我个人觉得不要排斥知识付费,就这么点钱,比你买个皮肤划算。

人家汇总整理知识,你花点小钱,节省你自己研究的时间,我觉得不亏。

反正我自己买了很多,我自己从中有收获,所以我说的一点都不心虚。

最后,源码是块硬骨头这毋庸置疑,我只能告诉你看源码的准备工作和一些小心得。

道阻且长,行则将至。

冲!

发布于 2021-06-26 10:24

高效读代码的核心不在于读,而在于动手。

IT行业是最典型的工科行业,要的不是多么高深的理论基础,而是不断动手实战,很多问题只看不做,等于没看。要想高效理解,深度理解,必须在看代码的同时配合动手练习。

其实在读代码的同时,做好以下七个步骤即可:

1、弄清楚这个项目的作用和主要用到的技术及框架

2、部署项目,并设置 debug模式

3、先从前端每个主要功能都走一遍

4、每个action的方法打断点,action中因为有断点,比如java后端代码,acting、service、DAO都走一遍

5、用visio或艺图把类结构图和代码流程图画出来(问下自己,有没有可以参考的visio文档?)

6、尝试修改一些代码逻辑,让项目继续跑起来,看看能发生什么奇妙的事情

7、抽离主干代码,重建工程,再重新填充 逻辑代码,尝试是否能让项目跑起来且功能基本一致

这七个步骤反复做,不光能吃透目,也可以拿来学习各种开源项目。

发布于 2022-10-18 18:17
  1. 首先熟悉写这个源码的语言是基本的要求。
  2. 了解源码的整体功能和模块划分,不要去考虑具体实现,只要明白怎么组织的结构。
  3. 选择你感兴趣的模块,功能,类,方法,函数。层层击破。
发布于 2014-02-28 16:18

我自己读代码的水平也很差,这种时候我会:

1 借助一些对代码静态分析的工具。

2 利用链接器的功能在代码 模块之间跳转,搞清楚我感兴趣的程序的脉络。

3 设断点和写单元测试进行调试。

这些方法其实都很简单,也没有什么心得可言。但实际上代码的种种玄机(特别是你找藏得很深的bug的时候),就必须要借助工具的高级调试和分析功能,非如此不足以破解疑难。从这一点上看,光靠读代码来收获一些东西,其实都是很肤浅的。

发布于 2014-03-03 12:54

本人正好最近用github较多,聊聊自己读开源项目的一些体会吧。

1.首先要能运行起来

本人一般都是先想办法让代码运行起来,只有这样,当我对代码做更改的时候,才能通过程序的变化直观的看到我更改的这部分代码究竟是负责哪一部分的。

个人经验表示,github上只要是靠谱点的开源项目都会在README里面写上如何部署的。我一般发现README写的不太好的,都是先去找找别的,实在找不到了才会回来看这个。

比如碰到某个输出函数你不知道到底执行在哪个部分,可以直接改掉里面的输出,再运行程序,发现你设置的输出在哪里粗线了(就是这就是这~),就找到了这句话的执行区间了。

比如你还可以注释掉一些代码,看看程序有什么反应,是崩溃了还是哪些地方消失了。如果你注释掉一部分代码,发现程序数据不更新了,那就可以判断出这部分代码是跟数据更新有关的,如果程序崩溃了,那看看在哪down掉了,那你注释的那部分代码就在这个地方被使用了。等等。

2.要有一个全局搜索的工具

我一般用的是sublime,感觉蛮好用的。它的作用是只要你有一丝线索,就可以迅速定位到你想要的地方。你自己还可以折腾下安装sublime的tag插件,就可以很方便的从函数调用的地方跳到函数定义的地方。

这个方法还是满通用的。

比如android,我clone下来一个网络异步的库volley,但是我觉得他这个库对json支持的达不到我的要求。我想自己更改,那第一步肯定是用sublime打开源码,搜索Json。就可以把范围缩小到局部了。

比如node.js,我想研究下hexo的git push,那我直接用sublime打开源码,搜索git就可以直接把范围缩小很多了。

比如前端我用到了DataTable,但是我觉得他的排序不满足我的需求。那我可以直接用“sort"关键词搜索他的源代码,定位出排序算法,接下来就可以慢慢改了。不然2W多行的源代码,岂不是疯了-_-!

再进一步,可能我不太清楚某个函数的用法与用处,我直接用sublime搜索这个函数名,所有调用到这个函数的代码就在我眼前了,接下来我就可以研究这个函数到底在程序中如何使用了。

3.学会注释与修改
这个其实就是第一步说的。程序跑不起来很多东西都不能确定,你甚至不知道是对是错。

4.多用搜索引擎与官网文档
其实不光是github开源代码,读别人的代码都需要多用搜索。因为很多时候如果源代码的注释不到位,你读起来是很费劲的。这个时候搜索引擎就很重要了。

比如我前一阵尝试iOS的时候,第一次看到block这个东西,根本就不懂这是什么代码怎么能读明白,于是直接粘到谷歌里看了。

比如有时候别人对代码做封装了,你看到的函数根本就不是原生的,但是你刚读可能不知道,完了你又看不太懂,这个时候你可以直接去搜谷歌或者developer center,比如我前一阵看别人源码看到了这个:

[self performDelay:0.5 block:^{}];

谷歌后发现丫根本找不到这个函数是啥。那请不要慌,多半是因为这个函数根本就是项目作者自己封装的。(有iOS大神可能会问你为毛不command直接进去看,求大神们不喷,我就是举个例子。)

5.不建议通读源码
本人作为一个开发没多久的程序猿,水平一般,所以读开源项目的时候很多代码根本通读不能,所以我一般都是用上面的这些方法,从功能入手,一点点研究,慢慢吃透整个项目。
希望能对楼主有所帮助。
以上

作者:涂鸦 链接: zhihu.com/question/2648

最后,计算机基础很重要,如果能参考国内一流大学的教材来学,更能是事半功倍,包含了浙大计算机专业 4 年所学内容:教材+课件+试卷+PPT等等:

今年秋招已经开始了,很多同学问我大厂面试的核心知识点,东哥熬夜整理出来了9大核心知识点,需要的自取:

另外,我当初在准备各大公司技术笔试的时候刷了大量的算法题,其中就是参考了一本谷歌大神的LeetCode刷题笔记,帮我整理了解题思路,归纳了出刷题方法,非常不出错,转给需要的同学:

祝大家前程似锦,在编码的道路上一马平川。

发布于 2023-08-03 11:49

打开日志

发布于 2014-03-03 12:59

大家好,我是三友~~

这篇文章我准备来聊一聊如何去阅读开源项目的源码。

在聊如何去阅读源码之前,先来简单说一下为什么要去阅读源码,大致可分为以下几点原因:

  • 最直接的原因,就是面试需要,面试喜欢问源码,读完源码才可以跟面试官battle
  • 提升自己的编程水平,学习编程思想和和代码技巧
  • 熟悉技术实现细节,提高设计能力
  • ...

那么到底该如何去阅读源码呢?这里我总结了18条心法,助你修炼神功

微信公众号:三友的java日记

学好JDK

身为一个Javaer,不论要不要阅读开源项目源码,都要学好JDK相关的技术。

所有的Java类开源项目,本质上其实就是利用JDK已有的类库和关键字实现一种业务功能,所以学会了JDK相关的类库是看其它的源码基础。

如果你不懂JDK,你去阅读源码会发现有太多看不懂的地方,会影响读源码的心情和信心。

学习JDK主要包括使用和原理两部分。内容大致包括以下几部分:

  • 集合相关,比如常见的Map,List,Queue的实现,包括线程安全与不安全
  • 并发相关,比如synchronized、volatile、CAS、AQS、锁、线程池、原子类等等
  • io相关,包括bio和nio等等
  • 反射相关
  • 网络编程相关
  • ...

了解设计模式

在一个优秀的开源项目中,设计模式处处存在,所以在你开始阅读源码之前最好先了解一下常见的一些设计模式。当你了解了一些设计模式以后,在源码中遇到了相关的设计模式,你就可以快速明白代码结构的设计,从而以整体的视角去阅读相关代码。

同时,学习设计模式不仅可以帮助我们阅读源码,在日常开发中也可以帮助我们设计出更易于扩展的程序。

学习设计模式的话可以看看《大话设计模式》这本书,如果不想看书也可以找一些视频或者专栏。

之前我也写过一篇关于开源项目中常用的设计模式文章 两万字盘点那些被玩烂了的设计模式 ,有兴趣的小伙伴可以看看。

先从官网入手

官网是介绍开源项目的地方,同时也是学习一个开源项目最开始的地方,通过官网我们可以快速的了解项目,比如:

  • 项目的定位
  • 一些核心概念
  • 功能
  • 使用教程
  • 整体的架构和设计
  • 常见的问题及解答
  • ...
RokcetMQ官网

当你了解了项目的一些概念、功能等信息之后,如果你在读源码一旦发现了代码是实现这些概念或者功能的足迹,那么能够帮助你更好的理解代码。

熟悉源码模块结构

当你对项目有大致的了解之后,就可以从Github上把代码clone下来,官网有项目源码的Github地址。

当成功拉下来代码之后,就可以对项目源码模块进行简单的分析,熟悉模块结构,分析模块功能,混个眼熟。

如上是RocketMQ源码,如果前面阅读过官网相关的一些概念介绍,就大致可以知道这些模块有什么功能。

RocketMQ概念介绍

比如说,源码中的broker模块,官网说broker主要是负责消息存储,那么broker模块代码块肯定就主要实现了消息存储的功能。

还有些模块可以根据单词的意思进行判断,比如common模块,一看就是存储一些公共类的模块,example模块,就是RocketMQ使用代码示例的模块等等。

顺着demo开始读

有的小伙伴在读源码的时候不知道从哪里开始读比较合适,最后随便从源码中的某个模块就开始读,读读越来越发现读不下去。

读源码正确的姿势应该是从demo开始读。

比如说,现在我想要阅读一下RocketMQ生产者是如何发送消息的,整个过程是什么样的,那么我首先至少得写个发送消息的demo,看看代码是如何写的。

demo一般可以从官网中查看

RocketMQ官网发送消息代码示例

除了官网,一般开源项目在源码中也会有相应的demo,代码放在示例模块,就比如上面提到的RocketMQ的example模块。

最后还可以通过谷歌搜索一下demo。

DefaultMQProducer producer = new DefaultMQProducer("sanyouProducer");
//指定NameServer的地址
producer.setNamesrvAddr("localhost:9876");
//启动生产者
producer.start();
//省略代码。。
Message msg = new Message("sanyouTopic", "TagA", "三友的java日记".getBytes(RemotingHelper.DEFAULT_CHARSET));
// 发送消息并得到消息的发送结果,然后打印
SendResult sendResult = producer.send(msg);

如上是RocketMQ生产者发送消息的一个demo,消息发送源码阅读就从这块代码开始入手,一步一步进入源码中,这就算开始阅读源码了。

带着目的去读

带着目的去读其实很好理解,就拿上面生产者发送消息流程源码来说,读源码的第一个目的其实就是弄懂生产者发送消息的流程。

除了弄懂生产者发送消息,你还可以带着其它目的去读。

比如说,消息发送的核心逻辑是send方法实现的,那么除了消息发送,是不是可以去弄懂生产者在启动的过程做了哪些事,也就是start方法的作用。

再比如生产者发送消息肯定涉及到网络通信相关的内容,那么了解RocketMQ底层网络通信模型是不是也可以算一个目的。

当你带着这些目的,你读源码就有很强的目的性,读完印象会很深刻。当然如果你最开始想不到这些目的,也没有什么关系,你可以先往下读,在读的过程中再去尝试发现一些其它的目的。

先抓主线,再抓分支

有的小伙伴在读源码的时候,每个方法都使劲一直往下点,最后都不知道代码进入到哪了,这其实是非常不可取的。

正确的方法应该是先抓住主线流程,分支流程先大致看看,知道大概是什么作用,等读完主线之后,再回过头仔细读一下分支代码。

举个例子来说,在Spring中,ApplicationContext在使用之前需要调用一下refresh方法,而refresh方法就定义了整个容器刷新的执行流程代码。

refresh方法部分截图

当在读这段代码,你可以先读一读refresh中各个方法大致都做了什么,等读完之后,你可以具体的去读每个代码的具体实现,比如说prepareRefresh干了什么,obtainFreshBeanFactory是如何获取到BeanFactory的,prepareBeanFactory又在对BeanFactory做了什么事等等。

不要过度抠实现细节

有的小伙伴在阅读的时候特别喜欢深究,想要弄清每行代码是如何实现的,这不仅非常难而且也是不可取的。

就比如说,我们都知道,在Spring Bean的生命周期中,当存在基于xml的方式来声明Bean的方式,Spring会去解析xml,生成BeanDefinition。当你想要了解Bean的生命周期过程的时候,其实是没有太大的必要去过度扣Spring是如何解析xml生成BeanDefinition的细节,这对你整体了解Bean的生命周期没有太大的意义,只需要知道最终会转换成BeanDefinition就可以了。

那什么时候去扣实现细节呢?

  • 当你需要使用到的时候,比如说你遇到了一个bug或者是需要扩展
  • 阻碍你理解功能实现的时候

大胆猜

读源码的时候也需要我们发挥一点想象力,去猜一猜功能是如何实现的。猜不是瞎猜,而是基于目前了解的一些知识、技术或者是思想合理地去猜。

就比如说,当你已经知道了OpenFeign最终会对每一个FeignClient接口生成动态代理对象,之后注入的对象都是代理对象,代理对象中实现了RPC的请求之后,那么当你在学习dubbo的时候,是不是就可以去猜测注入的dubbo接口最终也是一个动态代理对象,并且这个代理对象也实现了RPC的请求?

之后你在读代码的时候就需要着重注意发现是否有动态代理生成的代码,这就算是一个目的,一旦发现了动态代理相关的代码,那么这块代码很可能就是dubbo RPC实现的核心。

学会看类名

不要小看类名,优秀的代码命名都是见名知意的,所以从类名也可能窥探出这个类的一些蛛丝马迹。

如下列举了几个比较常用的命名习惯

  • 以Registry结尾的一般都是存储功能,比如Spring中的SingletonBeanRegistry就是用来保存单例Bean的;Mybatis中的MapperRegistry就是用来保存Mapper接口的
  • 以Support、Helper、s、Util(s)结尾的一般都是工具类
  • 以Filter,Interceptor结尾的一般都是拦截作用,一般会配合责任链模式(Chain)使用
  • 以Event、Listener结尾的一般都是基于观察者模式实现的事件发布订阅模型
  • ...

除了一些比较通用的命名习惯,也有一些项目独有的一些命名习惯。

比如说Spring中常见的以PostProcessor结尾的都是扩展接口,实现这些接口可以拿到某个比较核心的组件,从而实现对Spring的扩展。

其实很多开源项目的命名都比较偏向Spring的命名风格,当你遇到了跟Spring的命名比较像的时候,那么可以大胆猜测类的作用。

学会看类结构

类结构也非常重要,他也能够帮助我们窥探类的大致功能。

ApplicationContext

如上图,是Spring中ApplicationContext的继承体系,当你需要了解ApplicationContext的时候,可以先去熟悉一下它的父接口的作用,当你大致弄明白了每个接口的作用,那么ApplicationContext有啥作用就大致就清楚了。

除了可以看类继承体系,还可以浏览一下类大致提供了哪些方法,了解对外提供的功能。

类方法通过快捷键 ctrl+F12(mac:fn+command+F12)查看,并且还支持模糊搜索方法名,我本人就非常喜欢这个快捷键

ApplicationContext

总结类的职责

当我们在读完一个类的代码的时候,一定要总结这个类的职责,明白这个类存在的意义。一般情况下一个类核心职责只有一个,遵循单一职责的设计原则。

举个例子,在RocketMQ中有一个类MQClientAPIImpl

MQClientAPIImpl

其实从名字大概看不出这个类主要是有什么功能,但是当我读代码的时候发现每个方法最终都调用RemotingClient方法,而RemotingClient只有一个实现NettyRemotingClient,所以从这个实现和类名可以猜出来RemotingClient是发送网络请求的客户端,所以当读完MQClientAPIImpl源码之后,我就知道了MQClientAPIImpl这个类的职责大致是封装参数,然后通过RemotingClient向MQ发送消息的。

当知道这个类的职责的时候,那么其它地方在调用这个类的方法的时候,就知道大概在做什么事了。

习惯阅读注释

当你在读源码的时候,如果有注释,最好能先读一下注释,这样能帮助你厘清类或者方法的功能,先知道功能,再去读源码就容易多了。

注释一般都是英文,如果看不懂,可以装个插件

写好注释

俗话说的好记性不如烂笔头,写好注释也是阅读源码中很重要的一个环节,好的注释可以帮助快速回忆起实现细节和功能。

注释并不需要对每行代码都注释,当然如果你愿意也没多大问题,但是注释应包括以下几点内容:

  • 核心类和方法实现的核心功能
  • 核心功能大致的实现逻辑
  • 核心的成员变量的作用
  • 方法中不易读懂的代码实现细节
DefaultMessageStore

如图,是我读RocketMQ中对于DefaultMessageStore类阅读的注释,这个类是RocketMQ中一个非常核心的类,从名字可以看出来跟消息的存储有关。这个类的功能非常多,所以我写了很多注释,列举了这个类主要有哪些功能和这些功能实现的一些细节。

总结思想,及时输出

当你读完某个功能模块的时候,就可以尝试对这块功能实现逻辑或者思想进行总结。

比如说,当你了解了CAS思想的时候,你会发现,原来保证线程安全不仅仅可以通过加锁的方式,还可以基于乐观锁的方式来实现。

在总结之后可以输出成一个文档,又或者是流程图。我个人比较喜欢画图,这里推荐两个在线画图工具:

  • processon
  • draw.io

processon我平时就在用,功能多,但是需要收费; draw.io的话免费,图标和颜色感觉比processon好看,平时文章中的贴图就是用 draw.io画的。

这里多说一句,总结思想还是非常重要的,在我阅读了很多源码之后,我发现很多技术或者功能的实现原理最终都是殊途同归。

提前了解依赖的技术

一般一个开源项目不是所有的技术都是自己实现的,它也会依赖一些其它的框架或者是思想,提前了解这些框架或者是思想,可以帮助你更好地阅读和理清代码。

比如说,RocketMQ底层是基于Netty框架实现网络通信的,当你对Netty有所了解,知道Netty在启动的时候需要注册一堆ChannelHandler用来处理网络请求,那么在读RocketMQ底层网络通信功能的时候你就可以去找一下Netty启动的代码,看看都注册了哪些ChannelHandler,然后就知道RocketMQ是如何处理和发送请求的。

查阅相关资料

当在阅读源码的时候,对某一块代码功能实现不太清楚的时候,可以通过查阅相关资料来辅助阅读,包括但不限于以下几种通道:

  • 官网
  • 书籍
  • Github
  • 文章
  • 视频

坚持

最后一点也是最核心的一点就是坚持。只有你长期坚持读源码,不停地思考,总结,不断提升自身技术的广度和深度,找到适合自己的阅读方式,阅读源码才会是越来越容易的一件事。

往期热门文章推荐

写出漂亮代码的45个小技巧

扒一扒Bean注入到Spring的那些姿势

三万字盘点Spring/Boot的那些常用扩展点

两万字盘点那些被玩烂了的设计模式

RocketMQ保姆级教程

RocketMQ消息短暂而又精彩的一生

发布于 2023-02-07 12:55

带着问题去阅读源码,庖丁解牛,逐渐吃透整个项目。

阅读源码的准备工作:

在阅读源码之前,你需要先掌握相关的基础知识,比如你要去阅读Python项目源码,但如果你对Python并不熟悉,那么这就无法进行下去。

掌握相关知识后,你可以先去官网看看是否有什么文档,通过阅读这些文档先对整体的项目思路有一个大概的了解,这样在你阅读源码的时候可以起到事半功倍的效果。

网上也有人总结过阅读源码的五步法:

  1. 通过文档和测试用例了解代码的功能
  2. 自己思考功能的实现方式
  3. 粗读源码理清实现思路
  4. 通过 debugger 理清实现细节
  5. 输出文章来讲述源码实现思路

大家觉得有用的可以总结适合自己的方法,学习改进。

如何正确地阅读源码?

1、官方指南—>比如Spring Boot Reference Guide就是对springboot最详细的描述,怎么样使用springboot、springboot特性等等,通过此指南,springboot在你面前一览无遗;以及对Python而言,如各版本的新变化、安装和分发 Python 模块、常见问题等等都可以查阅官方文档。

2、阅读书籍—>国内外优秀的好书都有很多,阅读书籍可以让自己学到的内容自成体系,知识点更系统,这就像是源码的好搭档。

3、看博客—>许多大牛写的博客是非常厉害的,对知识点的讲解很详细、也说的很透彻,论坛、github这些都是可以看的,非常有学习价值,我们也可以获得很多真正实用的学习经验。

4、代码工具:各种编辑器和 IDE,像 Vim,Emacs,VScode,JetBrains 全家桶之类的,这些都可以用来阅读源码,选择适合的即可。

5、记忆并绘制项目架构:项目就是一堆代码的组合,除了学习编程技巧,还要了解项目的架构决策,这对于未来自己写大型项目非常用用。这种理解越补充,你会对它就越来越清晰。

6、学习数据结构:除非你要阅读的是算法实现的源码,否则,对于大多数框架源码或者工程源码来说,数据结构比算法重要。算法很容易被封装起来,即使我们不理解内部原理,但只要我们知道它在做什么事情就好,但数据结构则是和整个程序的结构联系在一起的。

Linus Torvalds 有这样的名言:

Bad programmers worry about the code. Good programmers worry about data structures and their relationships.

烂程序员才关心代码,好程序员关心的是数据结构和它们之间的关系。

最后:

从源码学习的角度来说,好的源码不见得用多高深的技术,而是文档完整,注释全面,函数名变量取得有意义,结构清晰的。希望大家都能学会写好代码。

编辑于 2022-10-19 16:55

阅读源码是有效提高自己的一个好方法。工欲善其事必先利其器;我发现函数调用图可以让我们更加直观地了解到源码函数直接的调用和层次关系,提高阅读源码的效率;

1 前言

看源码的时候,心血来潮想弄一下函数之前的调用关系,想起以前doxygen配合graphviz使用可以生成比较直观的函数调用关系图,但是前提是函数的注释需要严格按照doxygen的规范,具体可以自己去搜索一下,当然使用source insight等利器也很方便;

本文主要通过gcc+egypt+graphviz(dot)三个工具轻松生成源码的函数调用关系图;下图是本人在阅读FreeRTOS源码tasks.c时生成的调用关系图,具体如下所示;

2 graphviz 安装

Graphviz (Graph Visualization Software的缩写)是一个由AT&T实验室启动的开源工具包,用于绘制DOT语言脚本描述的图形。 ubuntu下可以直接安装;

sudo apt-get install graphviz

直接输入指令后,系统开始安装;


成功安装graphviz,这里我们就可以使用dot工具了,具体使用方法如下;

3 egypt 安装

egypt官网: http://www.gson.org/egypt/

下载后的文件为egypt-1.10.tar.gz;找到文件所在路径;

sudo find \ -name egypt-1.10.tar.gz

然后解压:

sudo tar -xvf egypt-1.10.tar.gz

解压得到egypt-1.10;

cd egypt-1.10 && sduo chmod +x egypt

最终可以看到文件结构如下;


egypt移动到/usr/bin,方便后面直接调用,或者将当前egypt所在路径添加到环境变量中;

sudo cp egypt /usr/bin

以上,已经完成了egypt的安装;

使用方法如下;

 egypt [--omit function,function,...] [--include-external] <rtl-file>... | dotty -
 egypt [--omit function,function,...] [--include-external] <rtl-file>... | dot <dot-options>

4 测试

编写程序test.c,具体如下所示;

#include <stdio.h>

void test0();
void test1();
void test2();
void test3();

int main()
{
        test1();
        test2();
        test3();
        return 0;
}

void test0(void){
        printf("hello");
}

void test1(void)
{
        test0();
}
 
void test2(void)
{
        test1();
}
 
void test3(void)
{
        
}

编译需要加上参数-fdump-rtl-expand生成相应的dump文件;

gcc -fdump-rtl-expand -c test.c


这里有我们需要的文件test.c.229r.expand;

输入如下指令;

egypt test.c.229r.expand | dot -T png -o test.png

最终生成了顺利生成test.png,具体如下图所示;

5 结论

对C语言源码的阅读用这个办法还是有点小麻烦,无法一键生成调用关系,另外还需要gcc编译源码生成dumpfile文件,如果想要方便一些,可能还需要自己写脚本实现自动化。

发布于 2023-11-29 13:43
高效阅读方法
744 播放 · 1 赞同
发布于 2021-12-17 10:46· 573 次播放

分享自己总结的一些阅读源码的方法,需要注意的几个点可以注意下

留备份,构造可运行的环境

  代码拿到手之后的第一件事情是先做备份,最好是刻在一个光盘上,在代码阅读的时候一点不动代码是很困难的一件事情,特别是你要做一些修改性或增强性维护的时候。而一旦做修改就可能发生问题,到时候要恢复是经常发生的事情,如果你不能很好的使用版本控制软件那么先留一个备份是一个最起码的要求了。

  在做完备份之后最好给自己构造一个可运行的环境,当然可能会很麻烦,但可运行代码和不可运行的代码阅读起来难度会差很多的。所以多用一点时间搭建一个环境是很值得的,而且我们阅读代码主要是为了修改其中的问题或做移植操作。不能运行的代码除了可以学到一些技术以外,用处有限。

  找开始的地方

  做什么事情都要知道从那里开始,读程序也不例外。在c语言里,首先要找到main()函数,然后逐层去阅读,其他的程序无论是vb、delphi都要首先找到程序头,否则你是很难分析清楚程序的层次关系。

  分层次阅读

  在阅读代码的时候不要一头就扎下去,这样往往容易只见树木不见森林,阅读代码比较好的方法有一点象二叉树的广度优先的遍历。在程序主体一般会比较简 单,调用的函数会比较少,根据函数的名字以及层次关系一般可以确定每一个函数的大致用途,将你的理解作为注解写在这些函数的边上。当然很难一次就将全部注 解都写正确,有时候甚至可能是你猜测的结果,不过没有关系这些注解在阅读过程是不断修正的,直到你全部理解了代码为止。一般来说采用逐层阅读的方法可以是 你系统的理解保持在一个正确的方向上。避免一下子扎入到细节的问题上。在分层次阅读的时候要注意一个问题,就是将系统的函数和开发人员编写代码区分开。在 c, c++,java ,delphi中都有自己的系统函数,不要去阅读这些系统函数,除非你要学习他们的编程方法,否则只会浪费你的时间。将系统函数表示出来,注明它们的作用 即可,区分系统函数和自编函数有几个方法,一个是系统函数的编程风格一般会比较好,而自编的函数的编程风格一般比较会比较差。从变量名、行之间的缩进、注 解等方面一般可以分辨出来,另外一个是象ms c6++会在你编程的时候给你生成一大堆文件出来,其中有很多文件是你用不到了,可以根据文件名来区分一下时候是系统函数,最后如果你实在确定不了,那就 用开发系统的帮助系统去查一下函数名,对一下参数等来确定即可。

写注解

  写注解是在阅读代码中最重要的一个步骤,在我们阅读的源代码一般来说是我们不熟悉的系统,阅读别人的代码一般会有几个问题,1搞明白别人的编程思想不 是一件很容易的事情,即使你知道这段程序的思路的时候也是一样。2阅读代码的时候代码量一般会比较大,如果不及时写注解往往会造成读明白了后边忘了前边的 现象。3阅读代码的时候难免会出现理解错误,如果没有及时的写注解很难及时的发现这些错误。4不写注解有时候你发生你很难确定一个函数你时候阅读过,它的功能是什么,经常会发生重复阅读、理解的现象。

  好了,说一些写注解的基本方法:

1.猜测的去写,刚开始阅读一个代码的时候,你很难一下子就确定所有的函数的功能,不妨采用采用猜测的方法去写注解,根 据函数的名字、位置写一个大致的注解,当然一般会有错误,但你的注解实际是不但调整的,直到最后你理解了全部代码。

2.按功能去写,别把注解写成语法说明 书,千万别看到fopen就写打开文件,看到fread就写读数据,这样的注解一点用处都没有,而应该写在此处开发参数配置文件(****。dat)读出 系统初始化参数。。。。。,这样才是有用的注解。

3.在写注解的使用另外要注意的一个问题是分清楚系统自动生成的代码和用户自 己开发的代码,一般来说没有必要写系统自动生成的代码。象delphi的代码,我们往往要自己编写一些自己的代码段,还要对一些系统自动生成的代码段进行 修改,这些代码在阅读过程是要写注解的,但有一些没有修改过的自动生成的代码就没有必要写注解了。

4.在主要代码段要写较为详细的注解。有一些函数或类在程 序中起关键的作用,那么要写比较详细的注解。这样对你理解代码有很大的帮助。

5.对你理解起来比较困难的地方要写详细的注解,在这些地方往往会有一些编程的技巧。不理解这些编程技巧对你以后的理解或移植会有问题。

6.写中文注解。如果你的英文足够的好,不用看这条了,但很多的人英文实在不怎么样,那就写中文注解吧,我们写注解是为了加快自己的理解速度。中文在大多数的时候比英文更适应中国人。与其写一些谁也看不懂的英文注解还不如不写。

 重复阅读

  一次就可以将所有的代码都阅读明白的人是没有的。至少我还没有遇到过。反复的去阅读同一段代码有助于得代码的理解。一般来说,在第一次阅读代码的时候 你可以跳过很多一时不明白的代码段,只写一些简单的注解,在以后的重复阅读过程用,你对代码的理解会比上一次理解的更深刻,这样你可以修改那些注解错误的 地方和上一次没有理解的对方。一般来说,对代码阅读3,4次基本可以理解代码的含义和作用。

  运行并修改代码

  如果你的代码是可运行的,那么先让它运行起来,用单步跟踪的方法来阅读代码,会提高你的代码速度。代码通过看中间变量了解代码的含义,而且对 以后的修改会提供很大的帮助

  用自己的代码代替原有代码,看效果,但在之前要保留源代码

  600行的一个函数,阅读起来很困难,编程的人不是一个好的习惯。在阅读这个代码的时候将代码进行修改,变成了14个函数。每一个大约是40-50 行左右.

———————————————源码下载网站—————————————————————

跟你说几个我常用的源码下载网站

csdn( 中文IT社区)它是集新闻、论坛、群组、Blog、文档、下载、读书、Tag、网摘、搜索、.NET、Java、游戏、视频、人才、外包、第二书店、《程序员》等多种项目于一体的大型综合性IT门户网站,源码只是其中的一项,但是很实用 里边有很多大牛。

DevStore( 源码下载)主要是开发者服务平台,汇集国内外众多第三方开发者服务,为开发者提供从设计开发到运营推广一站式的解决方案,源码和服务评测也是亮点,很专业,很实用,这里边聚集的都是开发者和PM,可以看看。

站长之家( 网站源码)针对个人站长,企业网管提供的资讯和源码,包含的语言和类型也比较多。

发布于 2014-11-21 16:39

很多回答都讲了宏观上的大致阅读思路和步骤,这里我直接上点微操技术上的硬货,讲下如何利用IDE的各种快捷功能,快速定位源码,以及高效地debug。

本人java程序员,利用IDEA看过spring、springMVC、rocketMQ,mybatis、dubbo源码,并撰有许多源码解析文章, 强烈推荐大家来看看

阅读源码前还是得先来点准备工作,如

  1. 熟练使用框架:没咋用过就来看源码,这不找虐吗???
  2. 搭建源码工程
  3. 了解java相关知识:比如和项目耦合的spring、mybatis用到了反射,netty用到了NIO
  4. 跟着资料先学一点:不求看懂,只求留个印象,有个底层的认知

这些内容在我的文章里有详细说明。

然后,需要以某个功能为切入点,去看源码,而不是漫无目的的搜寻目标。

这里我以阅读springMVC处理请求源码为案例,详细介绍下实操(查看类继承图、跳实现类、debug等)

发布于 2022-10-16 10:13

1. 先看官方文档和架构图
优秀的开源组件官方都会维护文档和架构图,这份架构图上或许有一些最重要的组件之间的关联关系、或许哪些功能的调用流程、或许有一些别的东西,但是相信我,这些东西一定都是从总体来描述这个项目的,这个一定是你要阅读源码时第一个要看的
2. 再看项目的组织结构
下载下来代码之后,不要急着开始。先看一下各个包名和包里的类名,对照着文档和类名先简单猜一下各个类的大致作用
3. 找到启动demo,把项目跑起来
阅读源码不仅仅是阅读,要让项目跑起来,去调试它,去观察和改变它的运行路线
4. 找到阅读的起点
很多人都想阅读源码,但是面对庞大的代码库不知道如何下手。这个时候你就要明确你的目标。
可以从启动方法开始、也可以从具体的哪个功能开始。总之要找到你的起点
5. 理清主干
一个优秀的开源软件总是经过了很多工程师很多年的努力孵化出来的,你去阅读它的时候很难把整个软件全部都整明白。所以一定要认准自己的目标,朝着自己的目标去读,当过程中出现一些不太重要的分枝时可以适当的忽略来节约时间
6. 把你的结论记下来
好记性不如烂笔头,我们从小就知道的一句话。包括且不限于笔记、流程图、截图等任何你擅长的工具,把它记下来。另外,最好总结一下重点部分方便面试的时候快速复习
7. 阅读时使用的小技巧
查看类的继承体系
快捷键:Ctrl+H


查看方法的调用层级
优秀的源码往往调用层级很深,当你debug到某个点却忘掉了怎么进来的或者说不知道哪个地方调用了这个方法,只需要在方法名上使用Ctrl +Alt+H即可查看这个方法的调用层级

查看类UML图
当使用Ctrl +Alt+Shift+u会在新的标签页中展示当前类的UML继承图


这个继承图相比较于第一个查看类的继承体系外还有以下优点:

  1. 使用UML图形展示看起来更舒服更全面
  2. 支持手动排除不相关的类和接口
  3. 支持展示类的属性和方法等相关信息
  4. 当你仅仅只关注UML图时还可以使用Ctrl +Alt+u在当前标签页浮动显示一个图层

Debug时修改变量
当你在Debug的时候可以使用Alt+F8唤起这个界面


在这个输入框中,你可以直接修改当前能够看到的变量,当存在以下场景时这个功能真的是绝配

  1. 当存在很多分支的时候修改某个变量来改变代码运行的逻辑
  2. 不确定某句代码结果时可以直接在文本框输入,而不需要再次重启程序

记住上方这7点,相信你会变得更加优秀,而我则使用这7点在一个月的时间阅读了Spring的源码: Spring源码解析系列汇总

发布于 2019-09-09 09:47

大家好,我卡颂。

经常看技术博客的朋友,可能对Webpilot[1]并不陌生。这是个「能对网页内容提问的AIGC浏览器插件」

他有什么作用呢?

比如,在阅读技术文章前,我们可以让Webpilot对文章内容先做个总结,看完总结再阅读会更轻松。

既然这个项目这么有用,而且代码是开源的,那不看看他的实现原理说不过去。况且,我还发现了作者团队留下的乐子 —— 在Webpilot贡献者一栏中,项目主程居然是ChatGPT

既然代码是ChatGPT写的(姑且这么认为吧),那我们看代码也不要人肉看了。

今天,让我们试试 AIGC读了项目源码后再来教我们。

欢迎围观朋友圈、加入 人类高质量前端交流群,带飞

应用选择

当前,代码相关的AIGC应用的操作对象主要是「代码片段」「某个代码文件」,比如:

  • Github Copilot
  • cursor

但我们希望应用了解整个项目,所以需要应用既能理解「代码片段」「某个代码文件」,又能理解「代码之间的依赖关系」。毕竟,代码逻辑通常是跨文件的。比如,假设项目中存在方法fnA,他:

  • a.js中定义
  • b.jsc.js中使用

那么当提问fnA相关问题,AIGC应用的上下文中起码应该包括以下信息:

  • 项目整体情况
  • a.jsb.jsc.js的代码

才能回答好问题。

要实现类似效果,业界的常用做法是Embedding,即「将内容实体映射为低维向量,通过向量之间的相似度判断内容关联关系」

比如,开源项目pdfGPT[2]可以接收PDF文档,用户就文档内容向他提问。

文档动辄几百页,GPT一次性能够接收的token有限,他是如何实现「就用户提问,在全文档中检索答案」呢?原理大体可以概括为:

  1. PDF文档分割成小的内容块
  2. 将内容块通过Embedding映射为低维向量,并存储
  3. 当用户提问后,首先将问题映射为低维向量
  4. 将3的低维向量与所有「存储的低维向量」比较,寻找关联度最高的向量
  5. 「用户提问」「与用户提问关联度最高的向量对应的内容块」组合在一起向LLM提问
  6. 获得回答

按照上述「解析PDF文档」的思路,我找到了解析代码的应用 —— bloop[3]。

bloop简介

bloop有点类似pdfGPT,只不过他的接收的是代码仓库,用户就代码仓库向他提问。

在官网下载bloop桌面应用后,绑定自己的Github账号,即可免费使用。

注意:bloop会要求你所有publicprivate仓库的读写权限。在意的同学可以像我一样注册个新Github账号

我已经forkWebpilot项目(就是我们要学源码的项目),这里直接让bloop同步Webpilot

bloop内部,这一步应该会建立代码文件的低维向量,如果我理解错了欢迎指正)

现在,我们可以就Webpilot项目向bloop提问了。来看看我们的第一个问题:

简单介绍下这个项目

很遗憾,第一句话就答错了 —— Webpilot「能对网页内容提问的AIGC浏览器插件」,而不是一个文本到图像的程序。

Webpilot项目中确实存在MidJourney(根据提示词生成图片的AIGC应用)相关代码,但这样回答肯定是以偏概全了。

那这是不是意味着bloop不中用呢?并不是的。

刚才我们已经提到,采用Embedding的实现方式只能获得「与提问内容相关的内容」,再就这些内容向模型提问。并非是模型完全理解代码逻辑后再提问。

换句话说,对于上述「提问fnA相关问题」的例子,采用Embedding后,我们会将下述信息整合后输入给模型:

  • 项目整体情况
  • a.jsb.jsc.js的代码
  • 用户的提问

模型根据上述信息回答问题。

而不是模型理解项目代码逻辑后,再回答「fnA相关问题」

所以,在向bloop提问时,我们需要给到一些线索,比如:

  • 文件名
  • 函数名
  • 变量名

这样,bloop才能根据线索,通过Embedding寻找相关内容。

当我们将「简单介绍下这个项目」修改为「根据README的信息,介绍下这个项目的用途」后,bloop给到了我们想要的答案:

其中,README就是我们给到的线索。

用bloop读源码

我们与bloop的对话不仅是为了寻求答案,更是为了给bloop提供更多线索。比如,当bloop回答:

Webpilot允许你与网页进行自由形式的对话,或者与其他用户进行自动的争论......

后,这个答案不仅是告诉我们的,也是告诉bloop自己的。在回答前,他也不知道Webpilot到底能干嘛。在回答后,我们就能继续提问:

“与网页进行自由形式的对话”这部分逻辑在哪里定义的

此时,bloop告诉了我们关键信息 —— 应用的主要逻辑在useAskAi方法中:

那么接下来,我们让bloop详细解释useAskAi方法的作用就能了解Webpilot的实现原理:

现在让我们思考一个问题,如果我们询问:

useAskAi方法都在哪些模块被使用?

bloop能给出正确答案么?答案是:不太能。

这有点反直觉,毕竟,在程序员看来,作为一个代码浏览器,bloop完全可以静态分析模块依赖关系后找到答案。

但是,bloop是基于Embedding技术实现的。在bloop底层,并不存在模块依赖图,而是「代码块对应的低维向量」

所以,bloop能找到部分「使用useAskAi方法的模块」,但可能找错、也可能找不全。

总结

bloop是基于Embedding技术实现的代码问答工具,对他提问需要遵循几个原则:

  1. 问题尽量详细,给bloop更多线索

坏问题:简单介绍下这个项目。

好问题:根据README的信息,介绍下这个项目的用途。

  1. 提问「详细的业务逻辑问题」时,可以分步骤提问。

坏问题:“与网页进行自由形式的对话”怎么实现的?

好问题:

  1. 根据README的信息,介绍下这个项目的用途。
  2. “与网页进行自由形式的对话”怎么实现的?

一句话总结 —— bloop了解很多「关于你项目的知识」,但在向他提问时,得先让他明白你的问题和「他了解的哪部分知识」相关。

能做到以上这点,bloop将会是你得力的源码阅读助手。

参考资料

[1]

Webpilot: github.com/webpilot-ai/

[2]

pdfGPT: github.com/bhaskatripat

[3]

bloop: bloop.ai/

发布于 2023-08-01 12:07