程序员每天都和代码打交道。经过数年的基础教育和职业培训,大部分程序员都会「写」代码,或者至少会抄代码和改代码。但是,会读代码的并不在多数,会读代码又真正读懂一些大项目的源码的,少之又少。这种怪状,真要追究起来,怪不得程序员这个群体本身 —— 它是两个原因造成的:

  • 我们所有的教育和培训都在强调怎么写代码,并没有教大家如何读代码
  • 大多数工作场景都是一个萝卜一个坑,我们只需要了解一个系统的局部便能开展工作,读不相干的代码,似乎没用

我常常把写代码和写作进行类比 —— 二者有很多相通之处;但从培养写代码和写作的过程来看,二者又有很多不同。我们的写作能力,是建立在大量基础阅读的基础上的,是除了学习语法和文法知识外,从小学开始,经年累月,通过阅读各种不同层次的名家的作品,再加上各种各样的写作训练,累积出来的;而我们的写代码的能力,在了解和掌握了语法/文法之后(学习和抄写 example 代码也算语法/文法学习的一部分),跳过了大量阅读名家作品的过程,直接 biu 地一下就自动养成了:学会基础的语法和试验了若干 example 后,我们就火箭般蹿到了自己写代码打怪赞经验的阶段。这样略过大量阅读代码的阶段有三个害处:

  1. 写代码的基础是不牢靠的,打怪升级的过程也是最慢的。道理很简单 —— 前辈们踩过的坑,总结的经验教训,你都不得不亲自用最慢的法子一点点试着踩一遍。
  2. 很容易养成 stackoverflow driven 的写代码习惯 —— 遇到不知如何写的代码,从网上找现成的答案,找个高票的复制粘贴改吧改吧,凑活着完成功能再说。写代码的过程中遇到问题,开启调试模式,要么设置无数断点一步步跟踪,要么到处打印信息试图为满是窟窿的代码打上补丁,导致整个写代码的过程是一部调代码的血泪史。(见我的文章:你要避免的软件开发模式)
  3. 你周围最强的那个工程师的开发水平的上限就是你的上限。

我们再回到读书进行类比。

从小学到高中,就语文而言,12年时光,单单课本我们要读十二册,数百篇文章。如果每篇文章平均一千字,那么我们读了数十万文字。这些文字,我们是精读过的(有些甚至要求全文背诵)。每篇文章我们需要总结中心思想,段落大意,归纳出论点论证论据或者时间任务地点起因经过结果,会分析长句难句,会学习起承转结,并反复训练基础的遣词造句能力,并最终模仿那些文章写出自己的文章。在这个过程中,我们学会了赋、比、兴,我们掌握了三段论,我们知道了如何用更优雅地方式表达自己的思想。更重要的是,这些阅读训练让我们在我们在脱离学校的基础教育后,可以自己独立完成一本书的阅读。我们不再依赖老师或者参考书为我们给出段落大意,中心思想,我们知道如何粗读,细读甚至类比阅读一本书,我们能把书中的精髓浓缩成思维导图,也大段大段摘录书中精彩的句子,段落或者篇章。

这十几年的时光,算上各种课外阅读,世界名著,古典文学,金庸古龙,修正玄幻,一个大学毕业的二十几岁的青年人,阅读量应该不下几百万字。而稍稍涉猎广些的读者,上千万字的阅读累积是常有的事。有了这些累积,你才能在迎面走来一位妙龄女子,想到的是肌肤胜雪,明眸善睐,桃腮带笑,齿如含贝,气若幽兰,美艳不可方物,一笑倾城,再笑倾国,沉鱼落雁,闭月羞花这些词句,而非不知如何表达,只能吞吞口水,在肚子里闷上一句:「我擦,美女啊」。

这是读书的第一大功用:累积素材(information)。你是否写文章时,经过一番搜肠刮肚,也不知该如何描述某事某物?同样的,写代码时,有没有毫无头绪,不知从何写起的时候?或者有了些的思路,双手却在键盘上迟滞,不知所措?这些现象,大多是缺乏累积所致。

读书的第二大功用:是开拓思路。有时候,一段文字,甚至一个句子,在你意料之外扑面而来,让你有种醍醐灌顶的感觉。比如『围城』里,赵辛楣和方鸿渐鸿初次见面,钱老描述赵的傲慢无礼,是这么写的:「傲兀地把他从头到脚看一下,好像鸿渐是本一览而尽的大字幼稚园读本」。初读围城的时候,我关注点是其故事性,将这样的句子轻易放了过去,几年前再读时,才发觉它的精妙:竟能如此简单地以物喻人,就把整个场景复原到如同发生在我的面前一样活灵活现。随后,我自己的文字里也模仿着,有时甚至刻意地如此这般使用比喻来增强画面感。前些日子偶尔再读到这句,因我有了作为一个成人,给女儿读幼稚园读本的经验,不由得莞尔一笑,旋即明白了一个道路:精妙的不是比喻本身,而是对生活的细微观察。

我在边学 elixir 边做 policy engine(见:Policy Engine 的前世今生)的过程中,除了官方的文档和零星的博文外,可读的内容少得可怜,我要解决的一些问题,论坛里也没人能给我较好的思路。于是我转而读了部分 iex 的代码,了解了 elixir 代码编译的方式,最终完成了一个 auto compiler 的 app —— 它能接受一些 API 请求,对预先配置的属于其他 app 下的源码可以在 cluster 里的有且仅有一个 node 上进行编译,编译完成后在整个 cluster 的所有 node 里重新加载;在做 API 的过程中,我读了 plug(elixir 下官方的 connection adapter 实现)里面的主要逻辑,尤其是精读了 Plug.Router 的代码,搞明白了为何 Phoenix 的 router 敢宣称在 route match 阶段,其 performance 就甩同行好几个数量级。于是我做 API 时,对如何在 match / dispatch 前后如何做些动作实现 middleware,甚至 hook 进 before send,有了更清晰的思路,在写代码时,也更加明白如何写出类似的 composable adapter。

累积素材是基础,被启发出来的思路将这些素材串成线,这就形成了知识(knowledge)。书读得越多,越勤于思考的人,知识也就越丰富。而知识的融会贯通,最终形成读书的第三大功用:通过了解,吸收别人的思想,去芜存菁,最终形成自己的思想,或者说智慧(wisdom)。

information -> knowledge -> wisdom 是个长期的累积,并非一朝一夕之功。

我的文章除几篇广告外,全部是原创,而原创中 99% 是我自己原创。这些原创完完全全是我「原创」么?我在 『如何选择工作』一文中借用了『黑客与画家』的思想:可测量性和可放大性。我赞同这个思想,同时将其融入了我自己的思考;在『程序员和拉条子』一文,我其实是写了个现代版的庖丁解牛;『代码重构之道』我借用了松本行弘,Martin Fowler,荀子等人的思想,形成了我自己的见解。当然,我书还是读得太少,所以,真正有价值的思想还贫瘠得很。

同样的,阅读名家的优秀的代码最终的归宿是形成你自己写代码的思路。我去年撰写的一个基于 node restify 的 API framework(见:再谈 API 的撰写 - 总览 系列),虽然有很多不完善的地方,但内核还是相当稳定,一年多来只是些许小修小补。撰写它的过程,是我对之前所读各种项目的一个融会贯通:为了确定我是否该基于 restify,我通读了它的代码(没多少),融合进了 hapi 和 loopback 的一些思路,提供了一套类似于 rails 的 CLI,再加上早年在 parser 上的一点经验,把 framework 逻辑上分出了:compile time(严格讲 nodejs 没有 compile time,但 configuration 的处理,route / middleware / model / task 对应的内部数据结构的生成,算进了 compile time 中),load time 和 run time,用前两个阶段的「低效」换取后一个阶段的高效(其实也类比了我的老本行,路由器/防火墙上的 control plane / data plane,first path / fast path 的设计)。如果没有之前各种源码阅读的累积,我很难做出这样的设计。

同样的,阅读 elixir unicode 实现的过程在两年前激发我做了一个使用同样思路的汉字的 slugify,或者汉字转拼音(解决多音字问题)的暴力方法(see github: chinese_translation),这一思路在今年年初进一步发扬光大成了我们现在在 Tubi TV 使用的 policy engine 和 content engine,为每日不计其数的内容请求保驾护航。我们使用了 code as cache 的方法,把数据库里的内容的不必在运行时做的 transformation 都在 compile time 完成,然后在 run time 结合记叙文三要素,得到最终的结果。以前我们系统中我们最慢的 API,采用新的 engine,如今快了至少数十倍 —— 尤其是在低并发下就惨不忍睹的 95 percentile response time(高并发都无法完成测试),如今在高并发,没有任何 failure 的情况下,99 percentile response time 都能控制在 500ms 左右。

所以你说,阅读优秀的,有启发性的源代码,多重要?

解决了 why 的问题,过两天我们讲讲 how。

作者:陈天

来源:51CTO

为什么我们要阅读源码?相关推荐

  1. 起飞,会了这4个 Intellij IDEA 调试魔法,阅读源码都简单了

    前言 上一篇文章 IntelliJ IDEA 高级调试之Stream Trace 算是 IntelliJ IDEA 高级调试技巧的开胃菜,很多小伙伴被这个小技巧征服.趁热打铁,今天给大家带来几个我日常 ...

  2. 朋友问我学习高并发需不需要阅读源码,我是这样分析的!!

    来自:冰河技术 写在前面 最近正在写[高并发专题]的文章,其中,在[高并发专题]中,有不少是分析源码的文章,很多读者留言说阅读源码比较枯燥!问我程序员会使用框架了,会进行CRUD了,是否真的有必要阅读 ...

  3. android源码阅读笔记1-配置源码路径/阅读源码方法讨论

    开始之前 android studio中配置android源码路径 android studio中有源码的路径,你只需要打开SDK Manager下载源码然后重启android studio即可查看源 ...

  4. 为什么优秀的程序猿都阅读源码

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:后端程序员必备:书写高质量SQL的30条建议个人原创+1博客:点击前往,查看更多 来源: CSDN(ID:CSD ...

  5. 源码面前没有秘密,推荐 9 个带你阅读源码的开源项目

    在文章开始之前,请各位先回忆下在日常开发过程中,都使用或依赖了哪些开源项目?是不是发现,开源项目已经完全融入到日常开发! 如今大多数的程序员技术栈和工具箱里,或多或少都有开源项目的身影:大到操作系统. ...

  6. java程序阅读技巧_Java程序员阅读源码的小技巧,原来大牛都是这样读的,赶紧看看!...

    1.Quick Type Hierarchy 快速查看类继承体系. 快捷键:Ctrl + T 查看类很多人可能都知道,可源码阅读的时候更多用来查看方法体系更重要,可以方便快速的定位到方法的实现类.如: ...

  7. jdk源码分析书籍 pdf_如何阅读源码?

    点击上方"IT牧场",选择"设为星标" 技术干货每日送达! 阅读源码是每个优秀开发工程师的必经之路,那么这篇文章就来讲解下为什么要阅读源码以及如何阅读源码. 首 ...

  8. 【转】使用 vim + ctags + cscope + taglist 阅读源码

    原文网址:http://my.oschina.net/u/554995/blog/59927 最近,准备跟学长一起往 linux kernel 的门里瞧瞧里面的世界,虽然我们知道门就在那,但我们还得找 ...

  9. flink的dataset/stream/sql三套API的选择以及是否应该阅读源码

    我常常在钉钉群群里面请教,群里也有阿里P7/P8的专家. 但是每当我请教dataset/datastream相关问题的时候,即使是专家也没有响应. 钉钉群里面P7的是云邪,擅长使用的也是flink s ...

  10. Linux下阅读源码工具

    闲来无事,于是又想进到Linux内核里面去逛逛了,但是只装了个ctags的工具,虽然说它可以在源码中到处跳动查看代码,但是感觉应该会有更好的方法. 虽然说可以转到windows下面去使用SourceI ...

最新文章

  1. fastjson获取json方法
  2. 时雨月五| AI机器学习实战の电磁导航智能车中神经网络应用的问题与思考
  3. windows查看系统信息方法
  4. 变频器输出功率_变频器的输出功率该如何选择?
  5. 【虚拟机】关于VMware 提示“无法获得VMCI驱动程序的版本:句柄无效”的解决方案...
  6. 数据库SQL语句学习笔记(6)-使用函数处理数据
  7. height百分比失效
  8. OC基础1:一些基本概念
  9. ROS笔记(13) 记录与回放数据
  10. 阿里2019财年收入达3768.44亿元 盘前涨幅一度超4%
  11. 分区分服游戏框架设计
  12. Matlab实现Sandbox方法计算分形维数
  13. 通过搜狐号引流靠谱吗?
  14. 用友U9 SOA引领企业IT架构全面升级
  15. Mac下解决v2端口被占用,shadowsocket(ss)程序残留问题
  16. unity开发 HTC vive手柄控制 手柄上各个按钮的点击事件
  17. 免费LOGO在线生成
  18. 防疫与复工同行,长沙望城进入“双统筹”的关键时刻
  19. CNDS 创建属于自己的专栏
  20. 【ChatGPT4】王老师零基础《NLP》(自然语言处理)第三课

热门文章

  1. 初学者必备Linux指令
  2. ubuntu16.04没有声音解决方案( 通俗易懂)
  3. python异常 Exception
  4. 如何优雅处理前端异常?
  5. 解决新电脑的系统安装问题:针对BIOS的UEFI模式
  6. LINQ聚合算法解释
  7. 如何将列表分成大小均匀的块?
  8. win11文件夹无法删除怎么办 windows11文件夹无法删除的解决方法
  9. win11系统怎么样 Windows11系统好用吗
  10. PHP里面最难的是那部分,那个PHP中号称最难的‘递归函数’