目录

背景

1、总览全局

2、分解

那么到具体的方法,怎么读效率高?

欢迎大家在评论区分享自己的经验

3、合并&闭环

4、循序渐进

背景

在工作中,除了写代码,很多精力用在了阅读代码。比如,阅读已有功能框架,读懂了框架才能更好在此基础上扩展;阅读学习优秀源码;根据错误日志定位问题,往往出问题的关键代码只有那么一两行,等等。那么,如何高效阅读代码呢?我总结出以下几步

1、总览全局

我觉得看代码就像看书,看书先看什么? 看目录。为什么先看目录?为了总览全局,知道这本书大概讲的是什么,跟已有的知识做找联系,做到心中有数。

如果之前读过类似的内容,那么能很快建立联系。举个例子,比如阅读消息队列的代码。因为我之前了解过rocketMq代码,知道rocketMq整体上由:生产者、消费者,nameSrv,broker,还有一些监控等组成。今天我想了解kafka源码,我会跟我了解过的rocketMq框架类比,对每个大块找相同、找不同,很快把kafka并到我的知识体系中。

如果一开始没想起来跟什么联系,觉得没读过类似的,先使劲找找,实在找不到,就重新建立。比如你说,我没读过rocketMq框架,那你有没有听说过队列?那如果也不知道队列,那就得先去学一下基础,学习下队列的原理。原理,是我们知识体系的基础,是地基。

2、分解

心里有数之后,把代码分解,大模块分解为小模块,分解到能理解的粒度。

还是rocketMq,我想了解消息消费的过程。那消息消费有哪些模式呢?push和pull。push和pull分别是什么呢? push模式让人感觉由broker将消息主动push到consumer。但在实际实现时,这两种模式都采用了类似长轮询(long polling)的机制,即由Consumer主动向Broker拉取消息。 在Push模式下,Consumer通过DefaultMQPushConsumer类与Broker建立连接,并保持心跳。Consumer定期向Broker发送请求获取消息,但Broker并不会立即返回空响应,而是会挂起Consumer的请求,直到有新消息到达或者达到预设的最大等待时间(例如5秒)才返回消息。从外部表现来看,仿佛是Broker将消息推送到Consumer,但实际上还是Consumer主动发起拉取操作,只是Broker对Consumer的拉取请求进行了优化处理,使其看起来像是推送。pull,是consumer也是定期向Broker发送请求,如果没有消息,broker会返回空响应。

以我的阅读经验为例(欢迎大家点击,哈哈哈):rocketMq-Consumer的两种消费模式:push和pull(含源码解读)_defaultmqpushconsumer-CSDN博客

我想了解下push,我就先把它代码分解:

rocketMq这种代码量非常大,一开始可能自己不太好划分模块,也可以先从网上翻翻别人的总结的流程图,提高下效率。(但注意这里是借鉴,批判的看,别人写的也不一定对,dddd懂的都懂)

那么到具体的方法,怎么读更高效?

有的方法设计的好,“像诗一样”,功能独立,入参,返回值定义的非常清晰,方法名起的得体,没有歧义。比如,各大持久层框架的 “增删改查”方法,是不是很清晰,看一样就知道怎么用。但遇到相反的情况,怎么看呢?最近读了一些,有一些小小心得,跟大家分享。

首先,总览,还是看入参、返回值、接口名,看个大概,知道这个方法大概要干啥。

然后,重点来了,找对象,对该对象属性的set方法,构造器等,看看“都对它做了点啥”,千万不能忽略构造器。如果有通知调用,看看调的哪个service。

最后,调试,验证自己的思路是否正确。这也是有技巧的,可以通过单元测试,打log验证。

3、合并&闭环

阅读完,我们会分析出这个功能由哪些对象组成。在功能实现过程中,我们对对象数据进行了修改,那么最后,这些对象的数据闭环了吗?

拿外卖订单举个例子,这笔订单付款由两部分组成:微信支付+红包抵扣。订单支付后,要核对微信支付金额是否正确,是否有重复扣款;是否扣除了用户可用红包;订单送达后,给用户赠送的内容是否到账,额度是否正确。

整个功能由3个对象组成:订单、红包、用户账户。那么最后我们要核对:订单对象数据是否完整? 红包对象数据是否完整? 账户对象数据是否完整?

数据不完整,逻辑必定有缺失。

4、循序渐进

阅读代码,是个学习的过程。一口吃不了个胖子,就一口一口吃掉。多阅读多调试,会发现祖师爷的教训,字字箴言:高内聚、低耦合……封装、继承、多态……

欢迎大家在评论区分享自己的经验