首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何深入理解开源项目从小代码集看起聚焦请先看文档关注资源的生命周期找一个好工具建立调试环境看代码很累,要坚持

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

作者头像
大宽宽
发布2018-05-14 11:33:10
7390
发布2018-05-14 11:33:10
举报

感谢这个时代,我们有了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
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.01.04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 从小代码集看起
  • 聚焦
  • 请先看文档
  • 关注资源的生命周期
  • 找一个好工具
  • 建立调试环境
  • 看代码很累,要坚持
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档