一、介绍
最近接到了一个安排,需要对一个开源框架进行学习,未来可能会需要开发、维护这个框架的代码,所以必须对它的源码进行学习。
学习源码其实就是对代码的深入研究,其实也算是一种对代码工程的科研,也就是说可以从科研套路中获取一些学习源码的方法。
提取了学源码和科研的相同点,总结出大致有以下5步:
- Introduction: 了解该源码是在哪个领域或模块大致要做什么;
- Related Work: 了解在该领域内的现有方法,以及它们存在的局限性;
- Method: 在该源码中的某个模块、函数是以什么思路实现的;
- Experiment: 该源码是如何使用的,它能比现有方法提高多少点性能指标;
- Conclusion: 该源码的优缺点,后续待解决的问题。
然而一套成体系的工业级源码必然是一个庞然大物,如果用论文做比方的话,可能是数个大论文(毕业论文)支撑才能完成。所以学大型源码时,要以看毕业论文的角度去学。毕业论文和小论文有以下不同点:
- 体量庞大:有限时间内无法搞懂论文中所有方法的细节。以代码来看就是,在时间较短的情况下,没法完全从头到尾的学懂每行代码的实现细节。
- 涉猎广泛:一篇论文中可能涵盖多个领域的知识。以代码来看就是,整个代码会实现多个独立的子模块,然后用独立模块共同完成整个开源项目的预期功能。
上面阐述了学源码和读论文的一些异同点,接下来说下具体的步骤。
二、具体步骤
1. 前期准备 Preparation
前期准备是要把原材料准备好,例如要对某个论文进行阅读,可能需要找到他的论文、支撑代码、博客等。那这里就需要把源代码的官网、代码仓库、说明文档先找到。
2. 阅读介绍 Introduction
目的:了解该源码是在哪个领域或模块大致要做什么
介绍一般都会在官网、说明文档或者网上的博客中有,这一步做完,就要知道整个项目是要做什么。还需要大致知道和他完成类似功能的框架还有哪些,它们有什么简单的异同。
3. 简单实验 Experiment
按照官网的安装指南,把环境搭建起来,把常用的API尝试使用一下,例如核心类的常用方法、核心功能的调用流程。
4. 阅读方法 Method
由于源码体量很大,所以无法面面俱到的阅读所有内容。这里就需要选一个感兴趣的、急需掌握的模块,将这个模块作为一个学习细节的切入点,沿着这个模块深入去学。完成这一步就需要掌握:该模块如何初始化、如何起作用(输入从哪里来、输入是什么、算法处理细节、输出是什么、输出送到哪里去)、如何销毁。
5. 记录总结 Conclusion
以上过程完成后,就需要把读到的收获记录下来,可以用博客、思维导图、流程图等多种形式,其实并不是后面可能自己会看(自己的笔记大多数时候是不会看的。。。),而是在记录的过程中,有可能会发现自己看的时候没有想清楚、忽略的问题,在输出的时候就能重新整理一遍,也是加深印象。
三、从大局到细节
人体结构上,大致可以分为骨骼、关节、肌肉。代码上也是一样:
- 骨骼:整个项目的根本基础。有骨骼就有项目基本样貌了。
- 关节:项目中各个模块的接口。只有一个骨骼的项目必然会很臃肿。所以要把大骨骼划分成小骨骼和关节。也就是把大项目分解成小模块和接口。
- 肌肉:为了健壮性、可用性存在的一些附加模块。肌肉的目的是让骨骼和关节运动的效率更好。比如在某个模块中加入日志记录、异常处理、并发提速。它们不影响核心功能的基本使用,但是会让核心功能使用得更好。
所以在看代码的时候,应该先抛开肌肉,只看骨骼和关节。也就是代码的初代发布版本(如1.0版本、0.1版本)。
后续版本肯定会对当前版本存在的问题进行修复、增强可用性、增加一些模块。完成当前版本阅读后,再逐渐看后面改进版本。
后面再看当前的最新版本,就能发现还有什么问题等待解决。也就可以对这一部分上手开发和维护了。
四、其他思考
1. 为什么面试官总喜欢问基础原理或框架源码?
从前文第二章可以看到,其实大多数开发者在做项目中,限于时间上或者认识上的原因,只停留在读源码的前3步(搭环境、知道是什么、知道怎么用),而对后续的method和conclusion并不清楚,也可以说是学习不深入。
而基础原理(并发、线程、NIO、xgboost方法细节、bp算法细节等)和框架源码(如Spring、Mybatis、redis、tensorflow)就可以考验开发者对一个东西的学习深度,不仅考察了实践技术、也考察了思想认识。
2. 怎么提高自己的代码能力?
感觉自己代码写的差,但是身边有不可能有人手把手教自己写代码,没有办法提高自己?
这种问题放在这种学习资源满天飞的信息时代,如果不是自己认识不足,那么完全就是扯淡。
代码看上去很差的原因无非就是:实现细节冗余、类间关系复杂、代码风格凌乱。
自己的代码写的差,就去学别人的优秀代码。
- 实现细节冗余可能是算法思想不清晰,所以需要加强对算法的学习,学习经典算法的设计思路和实现方法。为什么经典的实现能够用精炼的代码清晰的表达出算法原理。
- 类间关系复杂可能是多个模块、类的耦合性很高,方法调用混乱,架构组织混乱。这里就需要学习设计模式。知道类间关系如何设计才是易于开发和维护的。
- 代码风格凌乱会让代码直观看上去就不太好,比如驼峰和下划线混合,变量名随意起,注释乱写。这种情况就要学习常见的代码规范,看看别人根据实际开发经验中总结出来的编程规范好在哪里,有没有自己可以借鉴的地方。
五、总结
这里从理论的角度对学习代码进行了一些分析,可以说只是方法学,而不是非常细节的实际操作流程。实际学习还是要具体问题具体分析,活学活用。
评论0