读书笔记 -- 通用源码阅读指南

之前有看过Mybatis3相关源代码,现在无意中又看到了这本书《通用源码阅读指导书:MyBatis源码详解》,因此想要对比下自己看的思路和作者思路的差别,顺便总结出适合自己阅读源码的门路。

最早我阅读Mybatis3源码时,大概工作已经1年左右,此时经验很不成熟,也没有过多的规划,日常中使用多了就想着开始看看了。现在回想起来主要有以下两个问题:

  1. 直接从框架的数据库操作主流程开始阅读,看起来很痛苦,对框架外围功能流程熟悉程度不够,因此有点瞻前顾后。
  2. 太专注细节,比如TypeHandler 阅读时,扣的就太细,缺少全局性把控,阅读源码最重要的是学习设计,具体实现是次要。

在本书中,作者在阅读前,会先做很多辅助性功能,比如搭建好调试环境,理清楚框架脉络,以及最重要的将功能拆分,作者始终认为需要事先有一个上帝视角,然后再深入细节,这样事半功倍。接下来讲下本文的阅读流程,以及中间自己的理解。

第一步:全面了解项目

在开始一个项目的源码阅读前,首先需要对整个项目有较为全面的了解,需要了解项目的产生背景以及演进过程,使用方法,主要目地是勾勒出项目的整体轮廓,了解了项目的轮廓,便于更好的构建上帝视角。

第二步:搭建可调试环境

借助对项目的了解,搭建可以调试的本地开发环境,调试是非常重要,如果无法调试就意味着无法去验证项目的处理逻辑,只靠看代码,这个过程会痛苦万份。不是必要的话,针对不可调试项目,阅读源代码的必要性需要再斟酌。

第三步:追踪项目的骨架脉络

借助调试,把项目的核心流程给梳理出来,这个阶段只需要分析出项目的一个核心流程主要分成了哪些部分,之间如何配合,最好能产出每一部分的核心模块。相对复杂的逻辑,切忌不要深入,跳过就好,这个阶段重要的是形成项目的全局视角。

以Mybatis为例,核心流程如下:

  • 配置加载流程
    • Configuration
  • 数据读写流程
    • SqlSession,Executor
  • 结果解析流程
    • ResultHandler

第四步:将源码的所有包从功能上进行划分(核心)

这一点我认为作者的想法很好,从包结构就直接将项目的整体架构给描述的清清楚楚,能够确定哪些是核心,哪些是外围,以及之间的层次关系,前面的骨架梳理更多的目地也是产出这张模块图。以Mybatis为例,作者产出了如下的图,可以很容易看清楚里面包含了哪些模块。

这个其实变相的对所看项目提出了要求,如果所看的项目在模块上规划杂乱无章,那么自然就很难理出来这个图,留给阅读者更多痛苦,至于这种项目该不该深入研究,那就看实际所需了。

image-20221003143607655

第五步:从外围包开始阅读源码(核心)

源码有很多,一上来就跟着主流程看,势必很快就晕掉,因此合理的做法是先看外围包,比如Mybatis的基础功能包。先看外围包,相当于在积累一定的项目知识储备,等到了一定程度再看核心包,难度自然会降低很多。作者用了个剥洋葱的比喻,由外及内,逐层深入。

eg:基础功能包 → 配置解析包 → 核心操作包

第六步:边看边思考以及记录why(核心)

从外围包开始看起,可能会遇到很多设计不知道为什么,因此不了解核心逻辑。此时就需要思考和记录,等到最后看核心逻辑时,再回过来看这些,有很大可能触发恍然大悟,从而带来个人理解的质变,这样能够更好的深入理解设计原理。

第七步:遇到同样本质的东西时归类总结来看

主要针对一个接口,多种实现情况下,比如MyBatis的TypeHandler,本质是映射,但存在非常多的映射实现,这些其实没必要看完,只需要看顶层或者抽1-2个实现来看即可。

第八步:针对复杂的包,进一步按照功能拆分

有些包可能很大,包含了很多功能实现,那么最好的做法是先按照功能拆分,然后按照功能分别看各自相关代码逻辑。比如Mybatis的mapping包,主要完成以下功能:

  • SQL语句处理功能
  • 输出结果处理功能
  • 输入参数处理功能
  • 多种数据库种类处理功能
  • 其他功能

这样拆分后,看起来会轻松很多。

Linux -- Expect Script入门
实践 -- Rome源码阅读