专栏首页大宽宽的碎碎念如何深入理解开源项目从小代码集看起聚焦请先看文档关注资源的生命周期找一个好工具建立调试环境看代码很累,要坚持

如何深入理解开源项目从小代码集看起聚焦请先看文档关注资源的生命周期找一个好工具建立调试环境看代码很累,要坚持

感谢这个时代,我们有了github,有了近乎无穷的开源项目可以看,可以学。

记住,看的目的是学,但是看不等于学

从小代码集看起

对于一个新手,是绝对不适合一上来就追求spring,web容器,数据库这种级别的代码。万事开头总是要从简单的来。如果没有太多阅读开源代码经验的话,请从一个代码量在千行级别或更小的repository开始吧。在阅读代码中,也慢慢留意一些约定,如

  • 代码的文档一般写哪里了(README.md ? 或者 docs目录?)
  • 代码的起名字和目录组织大概遵循什么规范
  • 代码如何配置
  • 代码如何build

这些将帮你构建一个初步的可以深入代码的路径,并为进一步深入理解代码打基础。

这一点不得不夸一下javascript的npm。npm有相当多的很小的好代码。老牌web框架express的代码数才4000多行。一些小工具比如随机字符串产生器、分布式ID产生器只有数十行。非常适合入门学习。

聚焦

有多少人是抱着一颗不切实际的预期去看代码的?有人说,我Java想提升一下去看看Spring吧;有人说我Web没有太理解,去看看Tomcat吧。结果可想而知。正像问问题时不应该问过于宽泛的问题,看任何代码都不应该抱有看一遍全都看懂的期望——因为就连代码作者自己都做不到。

写代码时往往都会做一些抽象,把某个特定问题拆解。比如分层、比如抽象为一个class代表一个实际的概念等等。每个抽象都可能解决一个具体的问题。看代码也是如此,一定要先聚焦,把看代码的scope限制住,不要贪多。

比如当看Java Collections代码,可能是希望学习其数据结构的实现方式——到底链表、树、跳表等是怎么实现的,内存中一个个object是如何关联起来的,如何被快速访问的;又或者是特定算法的实现(比如Collections.sort用的是什么排序算法)。此时,其他的部分就不要太过于在意,直接忽略那些抽象隐藏起来的地方,以及不相关的细节。

对于更复杂的服务就更要聚焦。比如Jetty解决了相当多问题,比如:如何启动、如何找到Java Runtim、如何加载配置文件、如何load核心class、如何打log如何处理IO、如何解析HTTP协议的数据、如何将数据转换为Servlet标准的处理、如何管理集群…… 并且,这些代码里还会夹杂着一些设计模式的层,比如XXXXFactory,XXXXAdaptor…… 如此复杂的代码,即使是很有经验的人也不可能兼顾着在短时间内全看懂。所以,每次看代码之前,务必先确定一个要学习的目的。如果代码量很庞大,就可以安排一个学习计划,每次聚焦于一个目的。

对于像Java这样的面向对象语言,优秀的设计往往都是基于一组代表概念的类生成的对象的相互交互。学习代码时,优先去看类名,组织起高层的全局感非常重要。比如,如果希望学习一个“驾驶模拟”系统的代码中有关“如何驾驶”的部分,一定会找到代表操作人、油门和方向盘概念的类。然后去观察他们是如何互动的。此时绝对不该扯上变速箱、发动机和传动轴。

作为像C这样的语言,其源码大致是面向过程的,即分多个步骤做一件事,每个步骤再细分为更多子步骤。例如,nginx分配一段内存来存储一个http请求头就大概包括

  1. 利用一个工具函数分配指定大小的内存
  2. 从socket中将数据读出来,并填充到分配的内存上

而第一步可以进一步细化为:从一个内存池把一段内存借出来,如果没有可用内存了就得找操作系统要,要到了内存可能还需要填充为零……等等子步骤。这时预先画画流程图对理解代码会非常有帮助。

总之,如果你被庞大的源码打败,大概率不是因为你笨,而是因为你过于贪心急躁了。

请先看文档

任何代码,总得有个出现的动机和大致的工作原理。好的代码一般会在文档里(一般是README.md)里讲得比较明白。比如Redis的源代码的README.md就给出了非常概要性的信息,见https://github.com/antirez/redis。如果还需要对某个特定的主题的解释,Redis官网也提供了大量的文字来说明,比如

这些文档能非常好的指导阅读相关的源代码。

更复杂的开源系统往往都有对应的书籍来解释其内部工作原理。比如,《MySQL技术内幕:InnoDB存储引擎》是很好的指引如何理解InnoDB源代码的书,大名几乎每个做业务的同学都会接触到;当年侯捷先生的《深入浅出MFC》非常细致的剖析了MFC内部的C++是怎么把本来C++运行时做不到的事情通过一些歪招给搞定的;《C专家编程》(又称鱼书),用很多小例子来解释比如一个复杂的函数指针的是怎么被parse的,变量是如何被保存和传递的。等等等等。

如果你阅读的是著名系统的源代码,请尽量先从文档/书籍入手找到切入点,往往能事半功倍。对于可读性,给人写的东西总是好过给机器写的东西啊。

关注资源的生命周期

有生产意义的系统一般总是会有一些核心的资源需要管理,而这些资源的生命周期的维护往往是这类系统代码的核心。

比如

  • 对于spring-core来讲,其核心资源是“Bean”。一个Bean被创建、初始化、被使用、被解构,是整套代码的核心;
  • 对于spring-webmvc,其核心资源是“HTTP 请求”。一个http请求从被收到开始、其数据被注入到请求handler,其返回的数据结构被设定,是整套代码的核心;
  • 对于一个池 (比如commons-pool,thread-pool),其核心资源是池中的Object。Object从创建,被借出,被使用,被归还,到最后被销毁,是整套代码的核心

数据库系统、队列系统、web系统、一些业务系统(比如做活动、发红包)、安全系统等等,都有这样的资源的存在。把握住核心资源的生命周期就能掐到代码的命门。

找一个好工具

很多年前我们做C开发时都喜欢用一款叫做"Source Insight"的软件来学习代码。他可以开很多窗口,在不同的函数间跳来跳去,还可以做书签方便定位。

如今,基本上是个IDE都会有这些功能,就连没有类型的js也能很方便的在VS Code中做各种符号跳转和多串口切换。

代码嘛,了解其执行顺序,而非其写作顺序更有利于学习。

建立调试环境

如果对于某些系统需要特别细致的理解,就需要把代码跑起来。通过打断点,输出log验证等方式印证自己的想法。

对于js,python这类会相当简单,因为npm/pip等工具解决了很多依赖问题,而且无需编译,直接启动-修改-重启-修改-……即可不断的尝试。jvm类的系统只要能满足mvn install或者gradle build这样的通用编译约定,或者通过IDE直接加载,也能相对容易的把系统跑起来。

对于C/C++的系统就要麻烦许多,需要自己建立一个虚拟机,然后自行安装必要的包。对于它们,远程GDB之类的技术是非常必要的。

对于前端代码,使用jsfiddle配合chrome开发工具这样的工具可让你快速的构建一段js+html+css代码的片段,并且实时的看到效果。

值得提一句的是,有些系统可能涉及到比较复杂的多进程/线程并发执行,对调试学习非常不利。此时需要优先寻找将系统退化到单线程/进程的运行方式(毕竟代码作者自己也得靠这个模式调试不是:)。一个典型的例子是nginx通常会有1个master进程+多个worker进程并发运行,但在开发时只要配置中设定:

daemon off;
worker_processer 1;

即可使其退化为单进程运行时模式。

看代码很累,要坚持

就像跑步能跑多远,跑多久,都是要靠自己。阅读代码的确能极大地提高个人能力。但是能走多远要靠毅力坚持。而坚持的大敌就是过大的挫折感。上面提到的种种方法——从简单的入手、聚焦、有计划、找好工具,说白了就是尽量减少挫败感,最大限度的提高“正反馈”。但是即便如此,不可否认的是,对于大多数人,看代码是一项非常枯燥的过程。这时你的恒心,你的毅力,你的“熬”的劲头决定了你能走多远。毕竟,想成为高级程序员并不是轻轻松松的事情。

横下一条心来,挑战自我吧。


最后附上部分我曾经看过的高质量开源代码:

  • nginx
  • MFC
  • Redis
  • Lucene
  • Jetty
  • Kafka
  • Thrift
  • Java Executors
  • Java Collections
  • Java Concurrecy
  • express
  • koa

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 如何积累知识和技能答网友-如何积累知识和技能一个故事凡事都有目标形象化关联不断的学,灵动的用结论

    大宽宽
  • 如何避免问渣问题?

    大宽宽
  • 分布式系统如何定位压力问题监控监控什么呢实际的压力问题怎么发生的我用的工具

    大宽宽
  • 你好我好大家好--吐露一点我在编程规范上的心得!

    但是,如果你的代码要共享或者和他人协作一起写代码,那就必须要收敛自己放荡不羁的灵魂和天马行空的想象力,按照团队制定的协作规范来完成代码工作。

    1480
  • 写出高质量代码的10个Tips

    文|汤涛 很长一段时间以来,我都在关注如何提高代码质量,也为此做过一些尝试,我想这个话题可能大家会比较感兴趣,在这里分享一下我关于如何提高代码质量的一些体会。 ...

    BestSDK
  • 什么代码会遭人耻笑,什么妹子会受人喜欢?从妹子角度戏说代码优劣。

    在日常生活中,丑姑娘和好姑娘一眼就能识别;在代码中,好代码与坏代码却不容易觉察,这里面有标准,但每个程序员都觉得自己创造的代码好。了解这些标准,可以有效避免写出...

    李艺
  • 优秀的代码是反复修改后创造出来的

    优秀的代码是反复修改后创造出来的  近些年来,越来越多的人开始转向敏捷开发,而且这些敏捷开发的技术已不再新鲜,大多都是在80和90年代设计形成的。但是,最近几年...

    用户1289394
  • 为什么优秀的程序员也是优秀的设计师

    为什么优秀的程序员也是优秀的设计师 在高科技行业中,我听过很多伟大的开发人员声称对设计一无所知。他们将设计当作是一个神秘的世界,一个编程世界之外的世界。他们觉得...

    用户1289394
  • 十一条程序员的编码黄金法则,实践经验总结

    这是一篇值得收藏起来,隔三差五就拿来重读的文章!因为作者向你保证,他“遇到的所有糟糕的代码,都是因为没采纳这些实践经验。而任何一段优秀的代码,都采纳了至少部分实...

    挨踢小子部落阁
  • 顶尖程序员的五种思维模式,你具备吗?

    《THe Effective Engineer》的作者Edmond Lau采访了很多硅谷顶级科技公司的顶尖软件工程师。他发现这些给世界带来巨大影响的的工程师们至...

    CSDN技术头条

扫码关注云+社区

领取腾讯云代金券