开源无法开箱即用:开源背后的学习成本

2021-01-03 14:50:12 浏览数 (1)

几个月前,因为项目的需要,我大量地阅读了 Android Studio 和 Intellij Community 的源码,以及它们配套地大量上下游的代码。然而,这并不是一个简单的工作,因为你接触到的大部分东西都没有文档。而且在复杂的系统里,没有人能知道所有功能背后的场景。

举一个简单的例子,在我调试 Intellij Community 的时候,发现了其中的一处 bug。向官方提了 issue 之后,辗转了多次,最后还是我自己找到了问题的原因。这部分相关的代码都没有与之匹配文档,除了因为再造一个 Android Studio 的公司屈指可数。也是因为专门针对一个没啥人会关注的代码、模块,编写文档的成本也就非常高。

就会发现阅读、修改开源软件源码的最大难点之一:大量的知识蕴藏在代码的背后,不深入代码是无法理解的。

PS:这一篇文章基于的一个前提是,大型的开源项目。

开始之前,介绍一点基本概念:根据知识能否清晰地表述和有效的转移,可以把知识分为显性知识(Explicit Knowledge)和隐性知识(Tacit Knowledge)。

开源项目的知识转递

在经历了 Android Studio 的源码阅读之前,我阅读过一部分 JVM 的代码,那个体验就比较好 —— 因为可以参考和阅读的相关资源比较多,还有各种简化的版本可以试着运行。进而,我能从中构建出全貌,再去获取我所需要的知识。再结合我最近编写 Charj 的时候,边阅读 Rust 的源码,边阅读了 Rust 官方的《Rustc Dev Guide》,便也能理解源码背后的思想。

源码背后的知识转换

整个理解源码的过程:从源码中领悟隐性知识,以文档和 Demo 的方式显式地介绍原理。学习的人,通过文档和 Demo 便能转换为自己的知识。

回顾我们对于 Intellij Community Android Studio 的源码探索和架构摸索过程。为了探索如何进行通信机制,我们做了这么一些事情去掌握背后的知识。

  • 寻求官方指导。就是到官方论坛提问,简单粗暴。但是因为时差,所以比较慢。
  • 通过社区求助。你懂的 StackOverflow GitHub issues。
  • 测试驱动知识管理。从测试用例中了解当时的场景,以及所针对的情况。
  • 调试。调试对于小型开源项目非常有用,但是对于 IDEA 这样的项目的一大痛点是:找不到断点。
  • 编写迷你的 Demo 应用。通过编写插件来回溯整个过程。

那么对于这些源码来说,需要通过注释来释放知识。虽然说,日常我们都喜欢宣称注释无用,但是在这次阅读和调试 Android Studio 的源码时,我们真的发现注释非常有用。因此,对于工具型项目来说,为了更好地对内沉淀知识,就需要

  • 编写架构和流程文档
  • 关键步骤编写适量地注释

令人遗憾的是,有些文档仅存在于这些项目的团队内部,并不会对外开放。

最后我们花了半天的时间写了一个在此机制下运行的 Demo,但是我们花费了半个月的时间在探索以及理解背后的机制,而一个 Demo 解释了所有的东西。但是,我们只有真正去运行这样一个 Demo,才能真正理解它是如何运行的。

生态降低了学习成本

上面的这个过程中,我们持续不断地通过框架的生态,来降低我们的学习成本。

最近的一段时间里,开源在国内不断地被提起,也越来越多地被讨论。尽管绝大部分的程序员依旧在 996,也许未来会有一些改观。在这个其中最有意思的一环就是,出现了越来越多的技术布道师

我曾经对这项工作也是颇为兴趣的,但是比不上软件咨询来得有挑战性 —— 遇到的问题各类多。他/她们做的事情有很多

  • 进行技术布道。
  • 开发者关系。
  • 与内部协作。
  • 技术输出。如文档编写与总结等等
  • ……

其背后很大的一部分工作就是:对于知识的管理。因为,作为一个布道师,需要:

  • 让人能快速上手。简化上手成本的一种方式就是通过 Demo 或者文档,显性化这些知识。
  • 能发现问题。手把手教会别人如何调试
  • 解决别人的问题。

而正是行动让每一个人都能快速上手一个开源项目。因为,有了更多的 Demo 和文档。

记得在我那篇《开源?不好意思,你们都理解错了》中提到了国内开源的一些问题,其中有一个问题就是:一次性开源。即开源软件一次性提交到 GitHub 上,缺少文档和相关的资料,也没有相关的历史。唯一有的是一系列的推广文档,还有不断更新地 README。

我们无法:

  • 理解某个修改背后的历史原因
  • 了解整个的架构设计和未来演进
  • 探索整个系统的构建过程

所以,我不太愿意去阅读这样的开源软件代码。

公司的知识体系

接着,让我们再回顾一下软件开发的一些有趣的知识管理机制:文档化将隐性知识转为显性,再一步通过成熟度模式隐性化。

为什么让新人写文档?

不厚道地说,我也经常做(让做)这样的事情。其中这是一个从隐性知识到显性知识的过程。

在传统的文化中,我们主要通过结对编程的方式,也就是一种社会化的方式,将知识从我们的脑海传递给新来的小伙伴。而在没有发生知识流动的情况下,我们并不会影响到这些知识是隐性知识。因此,当我们发现它对于新人的帮助时,就会下意味地用语言来记录它们。

为什么我们总在提炼知识?

过去的一年里,我的主要工作是在帮助客户重构项目、优化系统、完善工程体系等等。我们做的事情,便是提炼知识和贩卖经验。而这个也是每个团队一直在做的事情。

持续不断地练习、学习、使用,而后将这些个人练习的知识总结下来。从某种意义上来说,它们便是在提炼隐性的知识,同时将这些知识以显性地方式记录下来。

为什么我们有应用成熟度模型?

一个学习型的组织,总会从不同的团队中吸取它们的优秀经验,并将这些经验放大到组织中使用,逐渐地它们被作为一个标准,用来度量不同团队的效率、成熟度等等。只是其中的一些显性知识被隐藏掉,变成一些具体的数值和抽象的表达。

所以,这就是我们提炼的顺序。

教授与结对编程

为了在软件开发中,为了显性化知识,我们做的一些事情是:

  • 轻量级架构决策记录。
  • C4 Model。
  • 代码生成文档。
  • 代码提取文档。
  • ……

但是,这些都是显性知识,还有大量的知识需要我们去从代码中知晓,从别人的口中理解工作的原理。所以,我们一直在提倡通过结对编程与技术分享,来传递这些知识。

隐性知识与显性知识

整个过程,实际上就是知识管理中的各种转化。

从……到……

隐性知识

显性知识

隐性知识

社会化

外显化

显性知识

内隐化

组合化

  • 社会化(socialization,共同化):从隐性知识到隐性知识。即从人 A -> 人 B
  • 外显化(externalization):从隐性知识到显性知识。如用语言描述
  • 组织化(combination):从显性知识到显性知识。加工、重构等
  • 内隐化(internalization,内在化):从显性知识到隐性知识。由员工进行转换

结论:开源无法开箱即用

我们在日常开发软件时,通过一系列的行为来降低整个学习成本。而在开源世界里,如果我们没有日常成为某个开源软件的一份子。那么,我们将面临巨大的学习成本,它将导致我们花费海量地时间学习。而且,这个成本是无法预估的。

再回到 Android Studio 那个场景,因为还要对应用进行编译。在这个场景下更可怕的是,你还要面对 Android SDK、Android 源码等一系列的上下游,以及其它大量的开源软件。哪怕只是一处小的功能修改,可能还要涉及到一系列的子系统。单单只是理清逻辑,就不是一件容易的事情。而理解业务逻辑最麻烦的一点是,你可能不知道业务,只是凭着感觉走。

就这一点来说,对于大部分的系统都是一样的。有很多国内的大公司,从开源社区拿到相关的代码,在缺乏系统性地分析和设计之后,便直接开始修改。最后衍生出一个不伦不类的分支,直至被抛弃。

0 人点赞