读源码时,我们到底在读什么?

村上春村有本关于跑步的书:当我谈跑步时我谈些什么

而我们软件工程师,经常会提到读源代码,读优秀开源作品的源代码。我们谈起读源码时,到底是读什么呢?

读者可能会说,你这不是装X,明知故问嘛,读源码,当然就是读源码了。

当然,源码是我们阅读的对象,我前面的文章也提到了一些源代码阅读相关的内容。我今天想谈的是,我认为源码阅读除了提高设计能力外,也是学习相应实现语方语法最佳实践的好例子,以及简洁代码、类/方法/变量等命名、注释编写等方面的榜样。

代码是写给人看的。这句话在许多编程的书里面都提到过。我们每次的代码写好后的刹那,以后的漫长岁月里,可能要无数次的阅读它,修改它,或者交给其他人来填坑,来重构。而写代码时的一点点追求,一个变量的命名,一段注释的描述,可以为后来的填坑侠争取来不少做好梦的夜晚。

而读优秀源码,就是学习其编写Clean code的过程,就是和作者交流的过程。各种代码的组织,小函数的封装,行前注释的解释,甚至某一小段代码的增加是为了解决某个Bug,对应bug系统中的bug号都能更清楚的让你理解它。

留意代码阅读中,对当前阅读主线不直接相关但语法不明所以然的地方,这些是学习实现语言语法以及相关背景知识的一个不错的方式。

例如,在读源码时,可能会发现,在阅读主线之外,有类似于日期格式化这样的工具类源代码调用。也许代码类似下面的样子:

public static final String RFC1123_DATE =
        "EEE, dd MMM yyyy HH:mm:ss zzz";

private static final SimpleDateFormat format =
        new SimpleDateFormat(RFC1123_DATE, Locale.US);

/**

     * Get the current date in HTTP format.

     */

    public static final String getCurrentDate() {

        long now = System.currentTimeMillis();

        if ((now - currentDateGenerated) > 1000) {

            synchronized (format) { // 注意这里

                if ((now - currentDateGenerated) > 1000) {

                    currentDate = format.format(new Date(now));

                    currentDateGenerated = now;

                }

            }

        }

        return currentDate;

    }

如果之前不曾详细了解过SimpleDateFormat,你不禁会想,此处为什么会使用synchronized进行同步加锁呢,那一定是它不是线程安全的。为了在多线程环境进行日期格式化,还有哪些方式呢。了解了之后就不会在多线程环境中依然使用一个全局的dateFormat进行格式化了,从而避免了以后的问题。

此处,对于某些教科书或XX天掌握XX这种书中较少深入讲解的内容,在出现时,可以以此为契机深入了解。

例如某段代码中,出现了类似于下面的内容

    private volatile boolean stopAwait = false; // 注意这里

// Loop waiting for a connection and a valid command

            while (!stopAwait) {

                ServerSocket serverSocket = awaitSocket;

                if (serverSocket == null) {

                    break;

                }

此时,就需要了解volatile的作用,如果不标识为volatile,会对程序的执行有哪些影响。而在了解的过程中,除了了解到其对指令重排序的影响外,顺便内存的可见性Java的内存模型等一系列内容就深入你的脑海,「只是因为在代码中多看了你一眼啊」。

同时,优秀的源代码,都会有许多的单元测试,顺着这些例子,可以学习到测试的组织方式;

会使用到不同的依赖管理工具,构建工具,也许你熟悉Ant、但源代码默认提供的是Maven/Gradle,就顺手了解了另一种工具;

也许你常用的Xml解析库是使用Dom4j/Jdom这些工具,而源代码中是使用JAXB的实现,在阅读的时候,你就会了解到另一种选择。

而这些内容,是你在读源码学架构,学设计模式,学原理之外,看似无意义的东西。

也许,就像当年乔布斯在里德学院学习衬线体和非衬线体一样,看似无用的东西,在他后来设计Macintosh的时候,「It all came back to me」。而我们现在主线之外的阅读,我想也会无心插柳,但在不经意的时候柳树成荫,让你炎热的时候好乘凉。

相关阅读

怎样阅读源代码?

怎样调试源代码?

Tomcat那些事儿
本公众号由曾从事应用服务器核心研发的工程师维护。文章深入Tomcat源码,分析应用服务器的实现细节,工作原理及与之相关的技术,使用技巧,工作实战等。起于Tomcat但不止于此。同时会分享并发、JVM等,内容多为原创,欢迎关注。

扫描或长按下方二维码,即可关注!

时间: 2024-08-08 05:56:09

读源码时,我们到底在读什么?的相关文章

vs2010查看quartz.net 2.1.2的源码时其中一报错的解决方法

问题: 使用vs2010查看quartz.net 2.1.2的源码时,报错: ..\Quartz.NET-2.1.2\server\Quartz.Server\Quartz.Server.2010.csproj : error  : 无法读取项目文件"Quartz.Server.2010.csproj". ..\Quartz.NET-2.1.2\server\Quartz.Server\Quartz.Server.2010.csproj(178,3): 未找到导入的项目"..

c# ilspy-应用VS2010运行ILSpy 的源码时,显示有个组件与VS当前版本不兼容

问题描述 应用VS2010运行ILSpy 的源码时,显示有个组件与VS当前版本不兼容 用VS2010运行ILSpy的源码时,提示ICSharpCode.Decompiler.Tests(incompatible)这个组件与当前VS版本不兼容,请问能不能在什么地方找到一个能够通过编译的源代码,或者有其他的什么方法让这个源代码运行起来,我的ILSpy源代码是2.1.0.1603版本的 解决方案 用2010编译一下源码.

eclipse-Eclipse编译Hive0.9.0源码时出错

问题描述 Eclipse编译Hive0.9.0源码时出错 我在用Eclipse编译Hive0.9.0时,编译通不过,如下所示: Buildfile: /home/cdl/branch-0.9/build.xml ivy-init-dirs: [echo] Project: hive [mkdir] Created dir: /home/cdl/branch-0.9/build/ivy [mkdir] Created dir: /home/cdl/branch-0.9/build/ivy/lib

eclipse anroid-eclipse导入系统源码时ProgressInfomation对话框一直存在

问题描述 eclipse导入系统源码时ProgressInfomation对话框一直存在 点击取消也一直存在,如果用任务管理器强制退出,再打开eclipse还需要导入.ps:本来之前源码已经成功导入了,但是不知道为什么隔一段时间就得手动导入源码一次....求解 解决方案 应该看一下details详细信息,看看在执行什么操作 解决方案二: 如何导入hadoop源码到eclipseEclipse 导入 Hadoop 源码导入hadoop 1.2.1源码到eclipse

请教:Visual C# 2005运行一个源码时,为什么不能生成网页,而只是生成文件目录?谢谢

问题描述 请教:问题一:VisualC#2005运行一个源码时,为什么不能生成网页,而只是生成文件目录?谢谢!http://localhost:4160/WebSite2/目录清单--/WebSite2/--------------------------------------------------------------------------------Saturday,May10,200804:05PM<dir>App_CodeSaturday,May10,200804:05PM&l

IHTMLDocument2获取网页源码时总是弹出安全警告

问题描述 .net中当获取网页源码时总是提出安全警告,代码如下:publicstaticstringGetDynamicHtmlFromUrl(stringsinaUrl,Encodingencoding){mshtml.HTMLDocumenthtmldoc=newmshtml.HTMLDocument();mshtml.IHTMLDocument2htmldoc2;mshtml.IHTMLDocument3htmldoc3;IPersistStreamInitips=(IPersistStr

jquery源码-jQuery.fn到底是个什么东西?

问题描述 jQuery.fn到底是个什么东西? 看jq的源码可以看到它的定义,jQuery.fn = jQuery.prototype = { ... },我用console.log()输出它,看到的样子是这样的: [constructor: function, init: function, selector: "", jquery: "1.7.1", size: function-] _toggle: function ( fn ) { add: functio

jQuery 1.5 源码解读 面向中高阶JSER_jquery

几乎很难从jQuery分离其中的一部分功能.所以在这里我分享下应该读 jQuery 源码的一些成果,以及读源码的方法.啃代码是必须的. 1. 代码折叠是必须的. 因此必须在支持语法折叠的编辑器里打开源码. 根据折叠层次,我们可以很快知道: 所有 jQuery 的代码都在一个函数中: (function( window, undefined ) {// jQuery 代码 })(window); 这样可以避免内部对象污染全局.传入的参数1是 window, 参数2是 undefined , 加快j

iOS 热更新解读(二)—— JSPatch 源码解析

关于 JSPatch 的实现原理,JSPatch 作者本人 bang 已经有一系列文章阐述: JSPatch 实现原理详解 <一> 核心 JSPatch 实现原理详解 <二> 细节 JSPatch 实现原理详解 <三> 扩展 JSPatch 实现原理详解 <四> 新特性 JSPatch 实现原理详解 <五> 优化 这些文章是对 JSPatch 内部实现原理和细节诸如"require实现"."property实现&qu