11

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

 3 years ago
source link: https://www.phodal.com/blog/why-opensource-hard/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

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

Posted by: Phodal Huang Dec. 23, 2020, 8:14 p.m.

几个月前,因为项目的需要,我大量地阅读了 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 源码等一系列的上下游,以及其它大量的开源软件。哪怕只是一处小的功能修改,可能还要涉及到一系列的子系统。单单只是理清逻辑,就不是一件容易的事情。而理解业务逻辑最麻烦的一点是,你可能不知道业务,只是凭着感觉走。

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK