为什么要看源码、如何看源码,高手进阶必看

简介: 为什么要看源码、如何看源码,高手进阶必看

由于项目的需求,最近花了较多的时间来看开源项目的代码,在本文中,简单总结一下对为什么要看源码、如何看源码这两个问题的思考。


看源码的意义

看源码只是一种方法、手段,而不是目的。我也曾经给自己制定过“阅读xxx源码”的目标,现在看起来真的很蠢,一点不smart(specific、measurable、attainable、relevant、time-bound)。


只有搞清楚了阅读代码的目标,才能有的放矢,抓住重点,高效达成任务。


看源码的意义总结起来包含但不限于以下几点:


一、解决问题(BUG)

只要是代码,就会有bug,只是说bug的多与少、深与浅罢了。现在大家都喜欢发布、使用开源项目,不同的开源项目社区成熟度、代码质量又会有较大的差异,遇到bug就不足为奇了。


当然,遇到bug肯定是先在网上搜索是否有类似的问题,一般可以在google、Stack Overflow、项目的issues里面有对应的关键词搜索。如果搜不到,那么就只能看源码解决了


二、知其所以然

我在[如何学习新技术、团队技术选型时要注意些什么][Link 1]里面提到过,如果我们需要将一个开源项目用到自己的项目中,那么就必须了解这项项目的优缺点,并深知原理,对部分细节(尤其是项目的优势、feature)进行深入研究。


如果是成熟的开源项目,遇到问题也许能google到很多答案;但如果是一个处于快速发展中的开源项目,多了解其架构、核心原理,也能帮助快速定位问题。


另外,有的项目文档可能不那么丰富,但又不得不使用,那么如何以正确的姿势使用呢?也得参考源码


三、学习

看源码也是一种不错的学习方式(虽然不一定不是最佳的方式),尤其对于比较优秀的开源项目,能让人大开眼界。


即使是出于学习的目的,也是有很多侧重的,比如


学习语言:代码风格、规范、惯用法、高级语法。对于某个语言的新手,找一个熟悉领域的开源项目来深入掌握这门语言,也是一个不错的注意。


学习设计:数据接口、框架、整体架构


学习理论:算法、协议。比如我之前写过的[raft协议][raft],光看论文是很枯燥的,而且算法理论到工程实践还是有一定的差距,这个时候结合开源项目([mongodb])实现往往更事半功倍。


四、改造

一般来说,我们刚开始仅仅是使用一个开源项目,但随着使用的深入,会发现一些自己需要的功能并没有很好的支持,向项目组提的issues也可能得不到快速的响应,这个时候就要自己开分支,改代码,加功能了。


[当然,比较好的是将自己分支比较好的新feature 给原项目提merge request,反哺开源项目,比如阿里的[Blink]。


五、借鉴

他山之石可以攻玉,如果有需要重新开始自己造轮子,那么参考一些已有的、优秀的轮子肯定是有好处的。


六、副产品

这一点,不应该作为我们阅读源码的出发点,但是确实能在实际中对找工作、面试有加成,算是副产品吧。


如何看源码

看源码的目的很大程度上影响了看源码的方式、需要阅读的代码的范围。比如说,如果是为了修一个线上bug,那么阅读代码的范围就紧紧围绕bug本身;而如果是为了了解某个分布式算法,那就需要按大量的、可能运行在不同节点(进程)上的代码,了解其交互原理、工作流程。


下面说一些通用的方法。


先看文档,整体把握

一般来说,文档是对代码的高度凝练,一个高质量的开源一般会包含tutorial、specification、API reference等documents,通过选择性的略读、精读这些文档,就能大致了解项目的整体架构、设计原则。6 大设计原则,你知道吗?


正确的路线是通过文档去认识这个项目,然乎通过阅读代码去验证文档、深入细节,而不是通过直接啃源码来了解这个项目,以偏概全。


理解代码组织,文件名,类名

当需要看代码的时候,不要找到一个文件就开始,先看看代码组织,粗略看看文件名、类名,基本就能猜测到每一部分。比如redis的源码就组织得很好,基本上看文件名就可以快速定位每一个command的实现位置。


关注一个问题,从问题追踪代码

看源码的目标决定了此时此刻的关注点,不管是解决遇到的bug还是学习某个算法,都让我们聚焦到一个具体的问题,从这个具体的问题去追踪代码,忽略掉当前无需关注的细枝末节,步步深入,直达目标。


当然在解决一个问题的时候,有可能会引发新的问题,尤其是学习的时候,此时只需记录新问题(放到收集篮,不要立即发散),待之前追踪的问题解决之后,再来看新发现的问题。


解决一个issue

如果自己没有问题,那么就帮忙解决别人的问题,通常来说,开源项目都有许多待解决的issue,从中选择一个入手即可。


调试

只要可以,一定先让代码编译通过、跑起来,这样不管是加log、打印调用栈还是断点调试都方便很多。尤其是对于像python这种动态类型代码,不跑起来很难知道到底在干啥。


加注释,做笔记

如果某份源代码的阅读并不是一锤子买卖,日后还可能回顾、重新阅读,那么就一定要做好代码注释和笔记。笔记主要是框架图、类图、流程图,目标是建立索引,方便日后快速回忆。


而注释就是阅读代码时的细节,重新阅读的时候看注释(特别是函数的注释)能节省很多时间。


推荐去我的博客阅读更多:


1.Java JVM、集合、多线程、新特性系列教程


2.Spring MVC、Spring Boot、Spring Cloud 系列教程


3.Maven、Git、Eclipse、Intellij IDEA 系列工具教程


4.Java、后端、架构、阿里巴巴等大厂最新面试题


觉得不错,别忘了点赞+转发哦!


相关文章
|
前端开发
Axios请求成功和失败时分别执行哪个函数?
Axios请求成功和失败时分别执行哪个函数?
|
6月前
|
小程序 搜索推荐 Android开发
Axure原型模板与元件库APP交互设计素材(附资料)
Axure是一款强大的原型设计工具,广泛应用于APP和小程序的设计与开发。本文详细介绍Axure的常用界面组件元件库、交互设计素材,涵盖电商、社区服务、娱乐休闲、农业农村、教育等领域的多套交互案例。通过手机模型、矢量图标、通用组件等资源,设计师可高效构建原型并模拟用户操作,评估界面效果。Axure支持导出和分享,助力团队协作,推动更多优秀应用的诞生。
714 6
|
8月前
|
Java 测试技术 应用服务中间件
Spring Boot 配置文件总结
Spring Boot 提供全局配置文件 `application.properties` 和 `application.yml`,用于修改自动配置的默认值。前者使用键值对配置,后者使用缩进和冒号。不同环境(开发、测试、生产)可切换配置文件,通过 `spring.profiles.active` 指定。例如,开发环境端口为4790,测试环境为4791,生产环境为4792。配置示例展示了属性、List、Map定义及引用方法。
212 14
|
9月前
|
机器学习/深度学习 人工智能 自然语言处理
《驾驭随机梯度下降:C++ 实现与优化算法全解析》
本文深入探讨了随机梯度下降(SGD)及其变种优化算法在C++中的实现与应用。从SGD的基础动力,到动量法、Adagrad、RMSProp、Adadelta及Adam等算法的优化升级,文章详细解析了各算法的工作原理、实现方法及其在图像识别、自然语言处理等领域的实践案例。强调了在C++实现中,内存管理、计算效率、超参数调优及代码可扩展性的关键考量,为开发高效、精准的人工智能应用提供了坚实保障。
272 33
|
9月前
|
机器学习/深度学习 自然语言处理 算法
政府部门文档管理革新:实现90%自动内容抽取与智能标签化处理!
本文介绍了多模态数据处理技术,涵盖自然语言处理(NLP)、光学字符识别(OCR)和图像识别的技术原理,以及智能分类、标签化处理、系统集成与国产化适配、安全与合规、算法优化等方面的内容。通过这些技术的应用,实现了文档管理的全流程智能化,为用户提供高效、可靠的解决方案。
273 3
|
12月前
|
前端开发
Vue3基础(十ba)___在css中使用props或者计算属性的变量,来实现动态样式
本文介绍了如何在Vue3中通过CSS变量和props或计算属性来实现动态样式。
277 0
|
SQL 关系型数据库 API
Python 开发环境的准备以及一些常用类库模块的安装
在学习和开发Python的时候,第一步的工作就是先准备好开发环境,包括相关常用的插件,以及一些辅助工具,这样我们在后续的开发工作中,才能做到事半功倍。下面介绍一些Python 开发环境的准备以及一些常用类库模块的安装和使用的经验总结,供大家参考了解。
|
Java 网络安全 开发工具
UNITY与安卓⭐一、Android Studio初始设置
UNITY与安卓⭐一、Android Studio初始设置
|
12月前
|
Shell Linux Python
python执行linux系统命令的几种方法(python3经典编程案例)
文章介绍了多种使用Python执行Linux系统命令的方法,包括使用os模块的不同函数以及subprocess模块来调用shell命令并处理其输出。
389 0
|
JavaScript 编译器 API
什么是Composition API
【8月更文挑战第16天】什么是Composition API
699 2