阅读 4450

为什么源码分析味同嚼蜡?浅析技术写作中的思维误区

优秀的技术社区每天都会生产出不少干货内容,《XX 框架源码分析》就是其中的一类。然而,这类文章往往叫好不叫座,人气常常不如《手把手教你 XX》。真的是我们太浮躁了吗?本文希望用另一种角度看待这个问题。

从大学教材到技术写作

中国的大学课堂以照本宣科而著称,而各个学校自己编写的大学教材也是出了名的枯燥无味。那么,一本烂教材一般满足什么条件呢?这里随便列出几个:

  1. 讲述的主题本身很复杂,很难脱离课本自学。
  2. 课程内容明明早有更好的经典国外教材,却偏要自己重写一套。
  3. 几乎不讲每个章节的意义,上来就是大段大段枯燥的定理、证明。
  4. 带了一大堆习题却不给答案。
  5. 小出版社没有什么审校,有各种明显的错漏。

然后让我们对比一下,一篇冷门的《XX 框架源码分析》又满足什么条件呢?

  1. 分析的框架本身很复杂。
  2. 这个框架已经被人分析过很多遍了。
  3. 上来就是大段大段的代码。
  4. 某些关键的地方被略过了,贴完源码还是读不懂。
  5. 排版措辞混乱。

看到了吗,这完全一一对应啊!非要说二者有什么不同的话,可能就是烂教材收钱而烂文章免费了吧。

技术文章的价值观

能写源码分析文章的同学,多半是有不少靠谱干货的,我也绝不是说源码分析的文章都是垃圾。在此,我们不妨换个问题考虑一下,即为什么中国的大学教材会遭人唾弃

没有对比,就没有伤害。让我们看看高等教育发达的美帝,其本科理工教材的行文方式是怎样的吧:

  1. 告诉读者,这门课要做什么,要解决什么问题。
  2. 用大段的文字描述,向读者展示如何一步步庖丁解牛地分解问题。
  3. 给出一些公式和推导过程,讲解如何(在简单情形下)解决问题的原理。

把美帝教材与天朝教材的编写思路相对比,我们就可以总结出二者在价值观上的偏差了:

  • 天朝:以规范为本的价值观,关注如何系统、结构地陈列知识
  • 美帝:以读者为本的价值观,关注如何让读者理解知识

这就是差别所在:许多【技术干货】和中国的大学教材一样,并没有把将知识传达给读者作为第一诉求,而是花大量篇幅贴出代码,告诉你【这个很复杂,我读懂了!】。然而,即便是硅谷的白板技术面试,代码量也不会超过 50 行,动辄几十上百行美其名曰【完整示例】的源代码,没有读过的读者真的能在短短的几分钟阅读时间里看懂吗?

然而,拜【先赞后看】的商业互吹风气所赐,没看懂这类文章的新手同学多半不敢把看不懂的责任归结到文章的行文思路上,而只会自卑地认为自己【水平不够】。于是,新人们为了提升水平,也投入到了源码阅读的大军里来,在历经困难后终于获得了成长,写出了一篇对同样框架同样源码的同样分析,想要屠龙的勇士也终于变成了龙。

所以,许多让人感觉晦涩的技术文章,其问题可能并非出在所介绍的技术内容本身,而是出在更基本的行文思路上。除了上面提及的源码解析类文章,类似的技术内容还包括:

  • 写给自己看的 Debug 笔记,里头都是各种业务细节的流水账。
  • 介绍某个技术点的技术分享 PPT,上来就讲一堆高级特性,生怕别人觉得深度不够。
  • 描述模块接口的文档,不讲自己的特性和概况,直接就丢个【调用示例】把 API 调个遍。
  • ……

然而只要稍稍转变行文的价值导向,按照读者的阅读理解方式梳理一下,它们都很容易变成高质量、能让读者从中学到知识的干货:

  • 把流水账按照多问问几个 Why 的方式来总结,就是非常有借鉴意义的 Case Study;把其中业务性内容剥离,就是节约后来者时间的踩坑指南。
  • 把分享 PPT 整屏整屏的代码换成直观的图示与原理性的伪代码,就是图文并茂的入坑指南(Facebook 当年讲 React 时,记得那个 PPT 只有寥寥几行代码)。
  • 把内部不敢见光的技术文档按照特性、示例、API 的流程讲一遍,就是达到开源级别的靠谱文档了。
  • ……

价值观上哪怕是简单的改进,最终产出的内容往往都会有很大的不同。我个人的例子是:同样是开发模拟器的总结,第一次写 实现 Chip8 汇编模拟器 的时候,主题就是【我这个东西很厉害呢】,这时的内容就是典型的技术流水账;而过了一段时间成长后,改进的 如何用 3KB 不到的 JavaScript 实现微机模拟器 就是一篇旨在分享,希望能够让新人看懂的教程了。欢迎对照它们各自的行文方式,这样就能对文章的可读性做出评价啦。

源码分析的套路与意义

上面介绍的是【转换价值导向】的概念。对许多技术文章,理清思路就能够很大地改善阅读体验了,不过对于源码解析类的文章,个人还有个大胆的想法:即它们的编写难度可能并没有标题看起来的那么大,对新手向的读者也缺乏实际的用处

这里我提出一种算法,能够轻松地完成对任意框架的源码分析

  1. 框架都会把底层复杂 API 封装起来,在源码里找到某个调这类 API 的地方。这种地方随便搜索一下,到处都是。
  2. 在这里加一行 throw 一个异常,运行框架来让它报错。
  3. 找到错误堆栈里的全部函数,把它们的顺序反过来,依次复制到你的《XX 源码分析》中,并把注释翻译成中文

三步搞定!虽然这个算法十分荒唐而无聊,但笔者确实见过一些文章,写得就像是通过这个方式堆砌出来的一样。代码的艺术在于化繁为简,而这样的内容却是在化繁为繁,读起来难受也是再正常不过的了。

另外,由于代码天生的特殊性,最好的代码阅读器恐怕不是技术社区的 App,而是强大的 IDE。源码分析的文章能够拿来下断点调试、能够拿来 mock 测试、能够拿来看运行时变量内容吗?有源码本身就足够了吧。

这就造成了一个尴尬的结果,即我们在想要了解代码的实现细节时,第一选择往往不是其他人写的源码分析文章。比如,在之前编写 Chip-8 模拟器的时候,我发现语言文档中的某一条指令语焉不详。这时我首先想到去参考的,是前人实现过的 Java 版项目源码,而不是找一篇《模拟器源码分析》来读。既然多数情况下源码本身已经是 Single Source of Truth,二手材料的优先级还会很高吗?

不过,对源码的解析难道就一无是处了吗?这个想法就更加错误了。阅读源码的能力绝对算是开发同学的硬技能,那么在什么场合会用到对源码的解析呢?我倒是发现在一个场合它非常适合:写 Pull Request 描述的时候

在向社区提交 PR 的时候,我们一般会说明【要解决什么问题、什么代码引起了问题、解决方案是什么】的三部曲,这时候阅读者都是已有背景知识的维护者,故而这些信息非常有助于 PR 的讨论与合并。

回想一下,中国的大学教材也不是一无是处吧?它们在考前复习的时候可方便了呢。源码解析类的文章就像是这样的提纲,需要给已经读懂过一次的人,才能发挥出最大的价值。

总结

鉴于上文中看起来批评了不少内容,故而有必要在最后澄清本文的主题:

  • 许多技术文章绝不是干货不够,而是干货太干,以至于阅读起来十分乏味。
  • 对行文思路简单的改变,都能很大程度地改善阅读体验。
  • 源码分析类的内容更适合作为 Pull Request 的讨论描述,而非让新人【理解框架原理】。

最后对于可能的质疑,作者个人的 Github 里有不少槽点很高的玩具源码,吐槽请不要客气😅…

关注下面的标签,发现更多相似文章
评论
说说你的看法