如何正确的阅读源代码?
写完「你也可以像 Prisma 一样渲染图像」之后,有读者提了这样一个问题:
我猜您平时应该有阅读开源项目的源码,好的开源软件或者框架,动辄数万行的源码,虽说是宝藏,但我看源码一直不得要领,投入时间不少但收获甚微,请教下:
您阅读源码的关注点一般有哪些?
您看源码有没有什么方法论呢,如何抓住重点下手?有时面对优秀的开源框架,想学习,我甚至都不知从哪看起。
关于这个问题,我说两句。
阅读优秀的源代码是软件工程师提高自己编程能力和学习开源框架的最佳手段之一。作为一名运动员,除了持续的刻意练习,还需要观摩大量对手的比赛视频。作为一名小说家,除了笔耕不辍,还需要阅读大量的其他作家的伟大作品。当然,观摩和阅读不是目的,是手段。路遥在创作《平凡的世界》之前读了大量的「名著」,然后,他把所有尊敬的作家都安放在远方历史为他们准备的「先圣词」中,让他们各自光芒四射,照耀大地,然后开始创作百万巨著《平凡的世界》。照耀你的世界的光芒,应该是自己发出的。
程序员亦是如此。在编程的路上,有无数的大师写出了伟大的代码和软件,去学习他们的编程技巧和技术风格,取其精华,去其糟粕,最后完成自己的作品。2005年左右我有幸参与了一个类似 CORBA 的分布式应用系统的开发,我在那段时间差不多通读了这个项目的早期代码,其整体架构规划和代码设计的精巧程度让人叹为观止(代码的编写者是早期的 CORBA 规范制定者)。这个经历对我后来的编程之路产生了深远的影响。
与编程一样,阅读别人的源代码永远不是一件轻松的事,或者说,是一件困难的事情,需要持续的投入,阅读、研究、把玩、实践。很多人觉得拿到了源代码就像买了本书一样,放到书柜上,立刻就产生了一种学会了的错觉(我就是这样,微笑),但真正实践起来才会体验到强烈的挫败感。大部分情况下,读不下去,不是方法不好,而是投入度不够。
阅读源代码,一定要找到好的开源项目。什么是好的项目?口碑好且应用广泛的项目就是好项目,比如 Docker、Spring、OpenResty,都是非常好的阅读素材。另外,完善的文档和足够的 test case 覆盖率,都是衡量一个开源项目是否优秀的标准。很多人说,代码即文档,好的代码本身就是自解释的。但是,对于规模宏大的开源软件来说,没有文档是不可想象的。所以在阅读源代码之前,一定要读文档。尽管读了文档之后,你可能不知道代码的技术细节,但至少可以了解项目的轮廓。结合开源项目的代码目录,差不多可以绘制出一个粗粒度的整体架构图,类似这样的:
然后为每个目录(或模块)做记录和标识,逐一阅读,或者直接去读你最感兴趣的部分。
我读源代码喜欢自顶向下的方式,先把整体脉络理清楚,然后按照模块去阅读代码,把类和类、函数和函数之间的调用关系记录下来,如果可以进行逆向工程,用类似 Intelli IDEA 这样的工具把代码之间的调用关系用 Diagrams 展现出来,阅读会更加直观一些,不同的语言有不同的工具可以选择。
另外,阅读 test case 同样能帮助你理解作者的代码设计意图。正常情况下,测试用例都是从文档和设计衍生出来的,而不是完成了代码再写 test case。阅读测试用例,可以让你更清晰的知道对应的类和函数想要做什么事情。
阅读源代码需要顺手的工具,我自己喜欢用 Vim,配合 NERDTree、CtrlP、ctags、taglist 等插件,Vim 可以成为一款优秀的代码浏览工具,而且非常轻量级。你可以在终端里用命令迅速打开、关闭、查找和索引程序,并进行有效的关联跳转(静态代码)。如果你不习惯,也可以用 Sublime Text,Atom 等工具。当然,如果你要进行调试和跟踪,那最好使用相关程序栈的 IDE 工具,比如 Eclipse、Jet Brain 系列工具,Xcode 等等,这样你可以在 debug 状态跟踪所有的函数调用和变量参数在执行时间线上的变化。
如果你喜欢 Vim,可以看下这篇「Vim 8.0,姗姗来迟」。
重复一句,工具和方法永远不是最重要的,去读,并在遇到困难的时候,看不明白的时候,咬牙坚持下去,抽丝剥茧,逐个击破。最终,你会在冰冷黑暗的二进制世界里面看到一张地图,找到一座灯塔,然后去解释和还原这个底层世界里每一个细微方面的语义,重建出高层次的抽象概念和关系。
最后推荐两本书,《Docker 源码分析》和《Go 语言学习笔记》,这两本书,都是关于 Go 语言的,可以说是源代码阅读的典范,有兴趣可以找来读读。
作者:佚名
来源:51CTO

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
《深入理解Nginx:模块开发与架构解析》一3.1 如何调用HTTP模块
3.1 如何调用HTTP模块 在开发HTTP模块前,首先需要了解典型的HTTP模块是如何介入Nginx处理用户请求流程的。图3-1是一个简化的时序图,这里省略了许多异步调用,忽略了多个不同的HTTP处理阶段,仅标识了在一个典型请求的处理过程中主要模块被调用的流程,以此帮助读者理解HTTP模块如何处理用户请求。完整的流程将在第11章中详细介绍。从图3-1中看到,worker进程会在一个for循环语句里反复调用事件模块检测网络事件。当事件模块检测到某个客户端发起的TCP请求时(接收到SYN包),将会为它建立TCP连接,成功建立连接后根据nginx.conf文件中的配置会交由HTTP框架处理。HTTP框架会试图接收完整的HTTP头部,并在接收到完整的HTTP头部后将请求分发到具体的HTTP模块中处理。这种分发策略是多样化的,其中最常见的是
- 下一篇
刘地生|微服务的实践
一.为什么大家都在谈微服务? 背景:随着互联网业务的极速增长,不仅仅体现在用户的增长,你的代码规模也会有直观体现。伴随系统规模的上升,传统的单体架构就像一艘不断变大吨位的巨轮,变得越来越笨重。系统规模所带来的挑战也不断影响着相关的参与者。开发者开发一个新功能、重构一小段代码、引入一个新技术变得不再敏捷可控。测试者的回归测试边界难以琢磨。部署一次变得小心翼翼或提心吊胆。这些都让应对变化变得迟钝。 是的,那个老头(Martin Flower)又出现了,又捣鼓出一个新概念【微服务】。他确实很喜欢捣鼓概念(不做过度解读) 微服务其实也不是那么新,它的提出之前,大家已经在服务化的路上走了好一会了。或者叫SOA或者叫ESB。都尝试解决服务规模导致的开发问题、重用问题、治理问题等等。当然微服务也不完全跟他们一样,至少为了适应现在的新环境提出了一些自
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
-
Docker使用Oracle官方镜像安装(12C,18C,19C)
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- SpringBoot2配置默认Tomcat设置,开启更多高级功能
- MySQL8.0.19开启GTID主从同步CentOS8
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- CentOS7,8上快速安装Gitea,搭建Git服务器
- SpringBoot2编写第一个Controller,响应你的http请求并返回结果
推荐阅读
最新文章
- CentOS关闭SELinux安全模块
- Docker安装Oracle12C,快速搭建Oracle学习环境
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8安装Docker,最新的服务器搭配容器使用
- CentOS7设置SWAP分区,小内存服务器的救世主
- Linux系统CentOS6、CentOS7手动修改IP地址