阅读源码很重要,以logback为例,分享一个小白都能学会的读源码方法
作为一个程序员,经常需要读一些开源项目的源码。同时呢,读源码对我们也有很多好处:
1.提升自己
阅读优秀的代码,第一可以提升我们自身的编码水平,第二可以开拓我们写代码的思路,第三还可能让我们拿到大厂 offer。无论那种情况,优秀的代码就是提升我们开发水平的资粮,而把这些优秀的代码读懂、读透并不很容易。
2.修复 Bug
有些时候,我们用的一些开源组件,出现了一些预想不到的问题。而这时候,也没有前人经验可借鉴,也没有文档可供参考,只能靠自己修复。阅读代码,理解项目,才能顺利修复问题。如果阅读代码水平不够,修复 Bug 这事儿就成了个棘手的事儿,影响咱们的工作。
3.增加新功能
在工作中,我们会遇到翻遍开源库也没有特别合适的组件的情况。这就只能对现有的组件进行改造,而这种改造的前置条件就是去理解开源组件。这时候,我们只能去阅读代码。
读源码好处很多,但是,读源码本身不是件简单的事。
相反,这是件非常困难的事情。一般来说,读代码比较困难的情况体现在:
- 代码读起来太枯燥,读了一会儿就犯困、犯糊涂;
- 代码读了很长时间,结果发现不知道得到了什么,花了时间却什么也没学到,读了个寂寞;
- 一个开源组件,读代码就花了好几天,就这也才弄懂了一两个文件里的代码,结果耽误了正常工作。
自我工作以来,长期和各种开源组件打交道,也被迫读了许多的代码。在经历了以上种种困难之后,花费了好几年的时间,我才算总结了一套自己的打法,才算能真正的去快速的读懂、读透许多开源组件。
恰好也有许多读者朋友问起我该如何读代码,所以,我决定把我总结的一些套路写出来,望能给大家一些帮助,能更快的提升自己。
那我们来看看我个人读代码的一些办法。
一、纵览全局
阅读代码之前,首先我们要用上帝视角去看源码,用上帝视角目的在于去了解这个组件的全貌。
全貌包括:
1. 开源项目的主要用途
我们要知道项目主要是用来干嘛的,因为这是项目的终极目标。
所有开源项目的源码本身都是为了这个终极目标才写出来的。
例如,对于 logback 而言,它的用途就是打日志。而它所有的代码无论多复杂,终极目标就是要让 logback 能健壮高效的打印出日志来。
2. 项目的架构
了解项目架构的价值在于,能了解系统的层次结构,就能理出项目的核心脉络。有了核心脉络,我们就能把有限的时间用在阅读最有价值的代码上。
如果项目的官方文档有架构图,那么就从官方的架构图去了解项目的整体架构。如果文档中没有架构图,就去搜一下有没有民间大神画出来,如果还没有,可以根据官方文档的描述,自己画出来架构图。
以 logback 为例,由于官方没有提供架构图,我根据文档大概画了一个架构图。
二、把玩无厌
摸清楚了系统的核心脉络,我们还需要把项目运行起来。
运行项目有两个目的:
1. 知道这个项目运行前有哪些必须的前置条件
还是回到 logback 的例子上。
当我们能成功运行 logback 后,其必然存在了一个 logback.xml 文件,否则无法运行。
这个 logback.xml 文件其实对于我们看源码非常重要,它点出了 logback 需要的关键元素。
并且,如果读源码遇到了困惑,明白了这个配置文件,就能有效帮助我们跨过障碍。后面谈到如何具体的读源码时再细说。
上面是一个基本的 logback 配置,里面列出了 logback 运行需要的关键组件。
2. 读代码出现疑惑,可以通过调试去解开自己的困惑
我们读的开源项目往往都很复杂。最典型的有三种情况:
- 方法变量不知其意
- 逻辑跳转绕来绕去
- 封装对象层次太深
而以上的情况,都只能通过代码调试才能解决。
三、抽丝剥茧
全貌、核心脉络知道了,项目运行起来了,你心里说,这下我要读代码了吧?
错,你还差一步,那就是细化目标。
我前面说过,我们读源代码的目的有三类:
- 提升自己
- 修复 bug
- 添加新功能
但是,这些目的过于模糊了。提升自己,那读哪些代码能提升自己?修复 bug,读哪些代码能修复 bug?添加新功能,读哪些代码能把新功能加上?
所以,得把这些有效的代码选出来。如何选呢?
当我们从事开发工作,听得最多的一件事就是把问题分解:把大问题分解成小问题,分而克之。
选择并阅读有效代码也是一样的。
对于过大的代码量,过多的功能,我们紧要的一件事儿就是把比较模糊的目标分解成能具体落地的精准的小目标。这些小目标对应到项目中,其实就是项目的一个一个的业务流程。
比如我们想给 logback 添加个新功能,能让公司的日志打印出统一的固定格式。看看我们如何做:
1. 纵向分解
纵向分解就是在我们已知的架构图上分解出来一条条纵向的业务流程。
由于我们想统一公司的日志格式,那肯定就需要在打印到文件前,把日志内容格式化好。所以,业务流程就应该选择从应用日志调用 logback 打印日志开始,一直到日志内容输出到目标文件结束的业务流程。
2. 横向扩展
横向扩展定下了我们如何组合业务流程,从而可以完整的达成咱们开始定下的大目标。
比如,这里就可以定下在看完 logback 打印日志的流程后,再去看看 logback 的日志是如何切换的。
四、腾龙入海
好了,现在我们终于要开始看代码了。
但是看代码也是要讲究技巧的,并不是上来就瞎翻瞎看。
1. 请将我心照明月
首先,我们曾经细化了目标,抽出了一条完整的业务流程。有此之后,我们就可以把业务流程和代码逻辑给映射起来。
看看logback的情况:
2. 一入侯门深似海
业务关系映射完毕,我们就能开始读代码了。在读代码的时候,我们还需要掌握几个技巧:
技巧一:代码一定跳着看
有件事我们得明白,不是所有的代码都值得仔细看的。我们最优先的,就是看正向流程的,核心的代码,其余代码皆可以跳过。
可以跳过的代码大概有:
判断异常输入的代码——这类代码对咱们理解系统意义不大,等到以后想提升自己编码能力的时候,可以回头专门找一些优秀的代码集中学。
出错处理和异常状态处理的代码——和上面理由一样。
数据处理的代码——往往就是解析输入数据,包装输出数据,有些时候还用 DTO 或者 DAO 方式去传递数据。这些代码有些很复杂,也很长,读了之后,耗费精力、扰乱思维不说,往往对掌握项目原理毫无帮助,务必跳过。
底层交互的代码——老实讲,底层交互技术含量是很高的,需要很多的底层知识。一时半会儿也无法弥补,而且一旦读不懂了,对信心打击很大,建议跳过。
技巧二:调用关系需确定
在看代码的时候,有一些方式会严重我们读代码。
如果你一旦读代码发现你找不到后续流程了,就得考虑考虑,作者是不是用了非顺序调用方式去调用后续方法或者对象。
一般来说,开发人员常用以下几种方式做非顺序调用:
- 通过中间件继续后续流程,比如 MQ
- 通过异步方式继续后续流程,比如 Future 模式、Promises 模式
- 通过回调方式继续后续流程
- 通过代理委托方式继续后续流程,比如动态代理
- 通过依赖注入方式继续后续流程,比如 Spring 的 autowired 注解
这些非顺序调用会严重影响我们阅读代码。而对于这几种情况,解决的办法大概有两种:
- 直接猜——其实后续流程我们在做业务流程映射到实际的代码对象的时候已经大概知道了,如果是接口,我们看看实现类不多,就可以大概挨个看下,一般都能猜着是哪个。
- 运行起来调试下——这种办法是很普遍的,对任何不确定的任何事情,其实都可以用这个方式。
技巧三:超难算法放最后
对于某些开源项目,它会采用很多经典的算法。很经典,当然也很难。
但是,对于理解整体项目来说,这些算法会严重阻碍我们的进程。我建议这些算法,可以先记下来位置。在后续集中就着算法资料,慢慢理解。
上面是 logback 日志文件分割的算法,在理解业务流程时,不建议马上去理解算法,可以放在后面自己另外定个目标理解。
以上就是我多年来一直沿用的代码阅读套路。
总结下
首先,阅读代码之前,我们应该对项目的全局做一个了解。我们可以从官方文档、民间博客之类的去加快了解全局的速度。最好能参考一些架构图、时序图,如果没有现成的图,最好能自己画出一些来。
然后,我们把项目运行起来,运行起来才能有助于我们后续的调试,才能有助于我们快速的理解那些难懂的代码段。
再后,把我们的目标细化成一条条业务流程。没有这些业务流程,我们一下子去读大片大片的代码,第一没有清晰的脉络,第二也没有可及的任务目标……结果就是一片混乱。
最后,才开始去真正的读代码。而读代码,我们应该有技巧的读,要知道如何跳过某些代码,要知道如何技巧的找到后续调用流程,还要知道如何把一些困难去集中攻克。
正是通过这种套路,我读代码不仅速度快,而且理解够深入。
另外,代码读的多了,还有一大好处:当我在设计项目架构的时候,写一套框架的时候,不自觉就会浮现出类似的项目或者代码块来。
总之,读代码令我获益颇多,这也是我职业生涯比较顺利的重要原因之一,也在此希望帮助到后来者。
如果你觉得这篇文章对你有帮助,请帮忙点个赞,一个小小的点赞也算是对我原创的支持。
你好,我是四猿外。
一家上市公司的技术总监,管理的技术团队一百余人。
我从一名非计算机专业的毕业生,转行到程序员,一路打拼,一路成长。
我会把自己的成长故事写成文章,把枯燥的技术文章写成故事。
欢迎关注我的公众号,关注之后还可以获取算法、高并发等干货学习资料。
我建了一个读者交流群,里面大部分是程序员,一起聊技术、工作、八卦。欢迎加我微信,拉你入群。
阅读源码很重要,以logback为例,分享一个小白都能学会的读源码方法的更多相关文章
- 分享一个与ABP配套使用的代码生成器源码
点这里进入ABP系列文章总目录 分享一个与ABP配套使用的代码生成器源码 真对不起关注我博客的朋友, 因最近工作很忙, 很久没有更新博客了.以前答应把自用的代码生成器源码共享出来, 也一直没有时间整理 ...
- 分享一个难得的YiBo微博客户端应用源码Android版
今天给大家分享一款,YiBo微博客户端应用源码,这是一款专为Android用户打造的聚合型微博客户端,完美支持新浪微博.腾讯微博.搜狐微博.网易微博和饭否五个微博平台,界面清爽,使用简单轻巧,支持多账 ...
- 分享一个基于web的满意度调查问卷源码系统
问卷调查系统应用于各行各业,对于企业的数据回收统计分析战略决策起到至关作用.而现有的问卷调查系统大都是在线使用并将数据保存在第三方服务器上.这种模式每年都要缴纳费用并且数据安全性得不到保证.所以说每个 ...
- 分享一个公众号h5裂变吸粉源码工具
这次我是分享我本人制作的一个恶搞程序,说白了就是一个公众号裂变吸粉工具,市面上有很多引流方法,例如最常见的就是色流,哈哈,今天我跟大家分享的方法是有趣的,好玩的,恶搞的.这个程序上线一天已经收获了61 ...
- 【整站源码分享】分享一个JFinal3.4开发的整站源码,适合新手学习
分享这个源码是14年开发上线的<威海创业者>站点的全套整站源码,前后端都在一个包里.当时开发使用的是JFinal1.4,最近改成了JFinal3.4.使用的JSP做的页面.有一定的参考价值 ...
- 转:Eric Lippert:阅读代码真的很难
转自:http://blog.jobbole.com/438/ 相关文章 微软资深软件工程师:阅读代码真的很难(第2篇) 阅读优秀代码是提高开发人员修为的一种捷径 学会阅读源代码 如何阅读大型代码库? ...
- 曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎
曹工说Spring Boot源码(26)-- 学习字节码也太难了,实在不能忍受了,写了个小小的字节码执行引擎 写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean De ...
- [一起读源码]走进C#并发队列ConcurrentQueue的内部世界
决定从这篇文章开始,开一个读源码系列,不限制平台语言或工具,任何自己感兴趣的都会写.前几天碰到一个小问题又读了一遍ConcurrentQueue的源码,那就拿C#中比较常用的并发队列Concurren ...
- 源码分析 | 手写mybait-spring核心功能(干货好文一次学会工厂bean、类代理、bean注册的使用)
作者:小傅哥 博客:https://bugstack.cn - 汇总系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言介绍 一个知识点的学习过程基本分为:运行helloworld ...
随机推荐
- React-条件渲染
<!DOCTYPE html> <html> <head> <meta charset="UTF-8" /> <title&g ...
- vscode插件(摸鱼神器-小霸王游戏机
vscode插件(摸鱼神器-小霸王游戏机 步骤 vscode扩展搜索小霸王,点击下载即可. 使用 默认有一个demo小游戏,即超级玛丽. 本地仓库 可以通过local菜单上的添加按钮添加本地nes r ...
- Day006 方法的定义和调用
方法的定义 Java的方法类似于其他语言的函数,是一段用来完成特定功能的代码片段,一般情况下,定义一个方法包含以下语法: 方法包含一个方法头和一个方法体.下面是一个方法的所有部分: 修饰符:修饰符,这 ...
- 【小技巧】Eclipse 中创建Maven项目后没有WEB-INF文件夹以及web.xml文件
懒得截图了,一张图配下面步骤搞定. 1.右键项目,选择propertities后选择图中①(被遮住了): 2.先不②勾选去掉,点击Apply:然后在把②处勾选上.此时④位置会出现东东,点击蓝色超链接. ...
- 【转】docker打包python应用
转自https://www.cnblogs.com/shenh/p/9518343.html 一.前言 容器使用沙箱机制,互相隔离,优势在于让各个部署在容器的里的应用互不影响,独立运行,提供更高的安全 ...
- 查询某软件所连接的外网IP地址
一:背景环境: 1>:某机械公司用的某些特殊软件,需要实现所有使用某软件的屏蔽其软件所连接的外网ip,其他上网功能不做限制. 二:需求分析:可以查出此软件所连接的外网ip,在路由器的ip过滤中将 ...
- InnoDB存储引擎简介
前言: 存储引擎是数据库的核心,对于 MySQL 来说,存储引擎是以插件的形式运行的.虽然 MySQL 支持种类繁多的存储引擎,但最常用的当属 InnoDB 了,本篇文章将主要介绍 InnoDB 存储 ...
- JVM虚拟机 类加载过程与类加载器
目录 前言 类的生命周期 类加载过程 加载 连接 验证 准备 解析 初始化 类加载器 三大类加载器 双亲委派模型 概念 为什么要使用双亲委派模型 源码分析 反双亲委派模型 参考 前言 类装载器子系统是 ...
- 简单介绍下自动化框架:Robot Framework
一.简介: Robot Framework:Robot Framework是由Python编写的一款功能丰富并且扩展性强的自动化测试框架,也可以在Java和 .NET 上运行. HttpRunner: ...
- (五)Jira Api对接:修改任务状态
项目迭代结束后我们需要把sprint下面的story.task任务状态修改到结束状态,如果手动修改会花费不少时间,本文就介绍如何通过jira api自动修改任务状态,提高工作效率. 一.查看任务工作流 ...