如何高效、优雅、愉快地阅读项目源码?
点击上方蓝色字体,选择“标星公众号”
优质文章,第一时间送达
引子
能够读懂独立类和基本容器的实现; 能够读懂小型的基础库和框架; 通过源码阅读来调试和解决实际中的问题。
预思考
需求是什么?用一句话说清楚; 设计目标是什么?用一句话说清楚; 核心优势和适用场景是什么?分别用一句话说清楚; 基本原理是怎样的?先自己思考怎么实现,然后阅读框架原理文章; 整体设计是怎样的?先自己思考怎么设计,然后阅读架构设计的文章; 技术难点是什么?先自己思考其中的难点及解决方案,然后阅读相关文章; 数据结构及算法流程是如何设计的?阅读框架的源码解析文章。
需求:有一套通用机制去创建和装配应用所需要的完整的 Bean 实例,使得应用无需关注 Bean 实例的创建和管理,只要按需获取; 设计目标:根据指定的配置文件或注解,生成和存储应用所需要的装配完整的 Bean 实例,并提供多种方式来获取 Bean 实例; 核心优势:支持多种装配方式、自动装配、依赖关系自动注入;支持不同作用域的 Bean 实例创建和获取;稳定高效; 适用场景:有大量的 Bean 需要创建,这些 Bean 存在复杂的依赖关系; 基本原理:反射机制 + 缓存; 算法流程:创建 bean 工厂对象 -> 扫描资源路径,获得 bean 的 class 文件 -> 生成 bean 定义的 beanDefinition 实例 -> 根据 beanDefinitioin 实例创建 bean 实例并缓存到 bean 工厂对象 -> 依赖自动注入 -> 执行钩子方法 -> 完整的 bean 实例准备就绪。 技术难点:依赖自动装配、循环引用;解决自动依赖注入和循环引用问题需要用到缓存机制。
需求是宽泛的,目标是具体的; 目标是需求的一种实现途径,往往是设计一个具备某些关键特性的系统或产品。
方法
确立目标,通常是理解某个模块的原理、设计或者为了解决实际问题; 写个 demo,能够将主流程运行起来; 找到框架运行的入口点,通过静态代码分析,大致了解整个实现流程; 在预估会经过的关键地方打断点,单步调试; 仔细查看主流程经过的主路径、每一个主要对象及其成员变量的值及变化,细细揣摩其设计意图和方法技巧; 绘制整体流程框图和类的交互图; 学习和理解关键类及关键方法及实现(代码)。
首先把主流程及涉及到的主要类弄透彻; 理解其扩展机制; 理解主要扩展实现(需要的时候徐图之)。
接口调用有多个实现,难以确定是哪个是具体实现时; 查看某个比较复杂的具体类的成员时; 理解实现细节时。
框架解析
问题域及解决方案构成的抽象层,解决问题的核心部分; 封装和交互构成的设计层,确保灵活性、可扩展性和应用集成; 各种细节构成的实现层,用于保证性能和容错等。
有哪些子模块,子模块的设计意图是什么; 子模块之间的关联是怎样的,如何串联成一个完整的设计意图。
常用设计模式:工厂、单例、外观、策略、适配器、装饰、代理、模板、组合、观察者、迭代器; 不同问题域可能会用到的设计模式,比如 DB 驱动接口实现会用到生成器模式和桥接模式,web 请求处理用到职责链模式。
如果需要创建实例,则通常离不开工厂和单例模式; 如果涉及较为复杂的算法流程,部分算法需要在子类实现,则会用到模板方法模式; 如果需要多种实现,并依据特定场景来选取使用,则会用到策略模式; 如果要将客户端接口及实现与框架的调用隔离,则会用到动态代理模式; 如果要灵活叠加多种功能,则会用到装饰器模式; 如果涉及到事件机制,则离不开观察者模式; 如果需要在库实现的基础上提供简洁接口,则通常用到外观模式; 如果要将多种实现与多种接口定义进行连接,则会用到桥接模式; 如果需要涉及大量配置(规格)并生成实例,则通常用到生成器模式; 如果涉及容器元素访问,则离不开迭代器模式; 如果需要以统一接口访问整体与部分的行为,且整体由部分组成,则通常用到组合模式。
克服障碍
原材料 => 子部件 => 组合与集成。 原材料:砖、石、木、铝、铜、玻璃等; 子部件:墙、窗框、窗户、门、地板、楼梯、锁、通道等; 房子:由子部件进行组合和集成而成; 机制:子部件的组合与集成的原理支撑,比如形状的组合与契合、承压计算等。
如何理清其中的复杂交互关系,从而理解其中蕴含的设计思想呢?需要先理清楚框架的概念图景。
由于接口定义了具体类的行为规范,可以通过阅读接口定义及文档来了解其设计思路和骨架; 查看具体类的实例成员(暂不涉及方法),根据经验揣摩其设计意图。
按快捷键 Alt+7,可以查看该类的所有成员及方法,概览一下,大致猜测其意图; 首先只关注那些对核心问题求解有重要影响的成员,暂时忽略那些用来提升性能、可扩展性等方面的成员; 单步调试,仔细看看运行时的成员对象如何,这样会更加直观具体一些。比如 DefaultListableBeanFactory 这个类,单步调试后得到如下图示:
数据结构与算法:比如 HashMap 用到了哈希表和红黑树,需要先阅读文献(比如《算法导论》)理解其结构与算法; 原理机制:比如 IO 读写、内存管理、文件系统、编译原理、网络协议,先学习相关的原理机制,夯实基础; 编程模型:特别的编程手法和技巧,比如读 hystrix 源码,就要先熟悉函数式编程和响应式编程。
经典书籍:比如数据结构与算法,就有《算法导论》、《算法》、《计算机程序设计艺术》(排序与查找)等; 经典论文:一些还没来得及写入书籍的论文解读,比如 Raft 算法等; 技术书籍:比如 Linux 操作系统内核实现,TCP 协议详解等; 官方文档:优秀项目主页的文档部分,往往有相关原理机制的介绍,比如 ES 的官方文档; JavaDoc:优秀源码的 Java Doc 往往会引用相关出处,比如 AQS 的源码; 优秀博文:优秀博文往往有一些文献引用,可以阅读相关文献引用; 百科与搜索:在维基百科上搜索出处和引用来源;或者使用搜索引擎。
边听音乐边阅读代码; 拉取代码分支,边读边做标记并提交; 阅读原理、架构及源码分析文章。
小结
作者 | 琴水玉
来源 | cnblogs.com/lovesqcc/p/14403497.html
评论