People Die, but Long Live GitHub

不知道有没有人注意到,Joe Armstrong 最近几个月都在忙着迁移博客到 TiddlyWiki。我很早就关注了他的 Twitter,然而之前并没多想。听闻大师在 4 月 20 号去世,我才反应过来,原来他之前的举动是在未雨绸缪。

TiddlyWiki 是个单文件的 Wiki 系统,但这并不重要。重要的是,你把信息存在哪?如果你希望存储一段信息,让 100 年后的人也能访问,要怎么做?

  • Facebook, Twitter, 微博?不要说 100 年,我都怀疑 20 年后它们还在不在;
  • Google Cloud, Amazon, 阿里云 + 个人域名?他们大概会存在地更久一些。但没有人能保证不出事故,比如之前的腾讯云事件,比如万一服务器被入侵,黑客把文件删了。还有,你怎么让信息能一直被访问?域名会过期。到某个时候,跑着旧版本操作系统的机器也可能被强制下线或升级,你的服务一定能够在新版本正常运行吗?
  • Dropbox, Google Drive, 百度网盘。同样地,这就要看你信不信这些公司一百年后还存在了,哦不对,他们即使还在,服务也可能早关了(望向 Google
  • Wiki。Wiki 很好,但并不适合存储个人信息,且可能被删改。
  • 去中心化存储,比如区块链。说实话,我对区块链了解有限,但直觉上,我怀疑它能否帮助我们达成目标。对比另一个去中心化的例子:BT。当你要下一些老动画或者电影的时候,拖不下来是常事,因为"死种"了。这才几年呢。当然或许区块链有某种神奇的魔法可以解决这个问题?欢迎了解的朋友们补充。

所以,我们还有什么选择?想来想去,也只有 GitHub 了。

GitHub 已经成为互联网最重要的基础设施之一,有太多人,太多事都直接或间接地依赖于 GitHub,除非人类在未来完全不需要开源代码(这显然不可能),否则我想不出 GitHub 有关闭的可能。对 GitHub 来说,存在 100 年简直是小意思,500 年也不是不可能。这是我的预言,不一定准确,但我还挺有信心的。

不管怎么说,对我们的目标 100 年来说,GitHub 完全可以胜任。除了服务本身的持久性,GitHub 还有两个独特优势:

  • Git。Git 能保存所有历史。
  • Fork。就算黑客黑进了一个账户,删掉 repo,他能把所有 fork 都删干净吗?

综上所述,目前来看,我认为 GitHub 是在百年尺度上存储信息并让其能被访问的唯一途径。未来也许会有 option 2, option 3 出现,但 GitHub 作为 option 1 依然会存在。我相信,Joe 用 GitHub 来 host 博客绝不是突发奇想,他一定是在了解自己的身体状况的前提下,思考了一遍现存所有存储方式,然后同样发现只有 GitHub 才能满足需求。

人总想留下某种痕迹,证明自己活过,然而事实上,99.999% 的普通人就这么被历史遗忘了——曾经是这样。我们处在信息时代的早期,同样也处在人类文明的早期。从今往后,被数字化的东西只会越来越多。既然有人意识到了 GitHub 的独特性,随着时间推移,越来越多的人总会意识到。那时候会发生什么?自然是,越来越多的人会把自己的信息搬到 GitHub 上,依托 GitHub 实现曾经人们可望而不可及的"永生"。人有两次死亡,第一次是肉体,第二次是被人忘记。我忘记这句话是谁说的了,但现在我们已经可以回避第二次。只要 GitHub 支持,就一定会有人这么做,至少我是其中之一。几十几百年后,GitHub 将成为世界上最大的数字公墓,注册用户大部分都已去世,然而个人主页,项目,commit 历史 还述说着他们生前做过的事——就比如 Joe 的博客。这虽然是个比较 creepy 的推论,但从另一个角度想,却证明了人类的巨大进步:对抗死亡是人类文明的永恒主题,而我们已经实现了阶段性胜利。现在是文章、照片、视频,也许还有以个人习惯作为输入训练的模型。再往后呢?会不会有基因信息,乃至意识的完整复制呢?依托于稳定的存储,我们能做的事情实在太多了。反例是现在的一些 Memorial Websites,他们把逝者的信息放在自己网站上供亲友吊唁。这不能说没用,但在我看来去使用这类服务实在有些草率——就算他们再信誓旦旦,也摆脱不了某一天关站的风险,那时候还指望他们好好管理这些数据?没可能的。

既然 GitHub 变成数字公墓是一种必然,我对他们的唯一希望,就是保持某种道德义务。我完全可以想象某一天他们出台一个政策,把二十年内没有活动迹象的账户全部 archive,GitHub Pages 全部下线。那就实在太恐怖了。我祈祷那一天不会到来。

近几年我看过最好的一部同人

许多漫画都能让我大呼过瘾或是沉浸在剧情中无法自拔。相对而言,能触动我的同人本不多,毕竟篇幅和剧情你们都懂,最多也就感叹一句画风真还原或者这 TM 都可以。

然而前几天我看了一本丧女同人,第二天又看了一遍。我想我要写一篇文章。

本子的名字叫《大学生だしルームシェアする》,作者是 sanada

不夸张地说,这是近几年我看过最好的一部同人。我真的被打动了。

这部作品牛逼在,作者基于对角色的深刻理解脑洞了一些角色之间的互动,其大胆又合理的想象甚至让我觉得可以直接作为原作后传,而且几乎每一页都可以让读过原作的人笑出声。

作品讲述的是临近高中毕业,黑木开始思考以后是要自己租房还是跟人合租。然后就是后宫团成员们纷至沓来,每个人都脑补出了和小丧一起租房的场景。选几页有代表性的图吧。

上图是百合和小丧一起租房的场景。小丧和优打电话,然后百合果断吃醋。

面无表情找小丧一起睡的百合,awsl

接下来出场的是加藤。

作者对加藤妈妈的刻画实在太绝了,后面百合和尼姆的眼神我看一次笑一次。她还画过一个的小丧 x 加藤的本子,也非常赞。

颜文字和尼姆的图就不放了。漫画的每一页都很有意思,每一页。

然后就是让我决定写下这些文字的一幅图:

Y-Yuri-chan, I…

When I'm with you…

I can have fun being myself.

这个理解,真的太太太太太强了,除了牛逼我想不出别的形容词。因为我自己是站百合的,所以我很清楚小丧和百合的相处模式和与其它人不一样。但直到看到 sanada 借小丧之口说出的台词,我才真正明白了区别所在。我可以肯定 sanada 也是站百合的。她对角色的理解的深刻程度,可以说达到了 EVA Re-Take 的级别。

同人本是一类特殊的作品,要从中获得愉悦是有门槛的,因为它要求读者对原作熟悉并喜爱到一定程度。类比一下,就好像只有天才们才能体会到数学的美。我恰巧超级喜欢丧女的原作,这也是为什么我会被本作深深打动。没读过原作或是对原作无感的朋友,很遗憾,你们错过了一份珍贵的礼物。

最近遇到的几个问题

最近我负责维护的一套系统出了不少问题。痛定思痛,决定总结一下。

根本原因有两个。

没有及时删掉不再使用的代码

在最近的重构中,我重写了一部分功能,导致原来的一些代码成了幽灵代码。问题源自一个 getter,它返回一个类的属性。这个属性在旧逻辑中一定会被设置,但新逻辑中不会。因为需要删除的代码很多,我在重构时加了不少 TODO,想的是等测试没问题了再一起删掉。然后就出问题了。一块我没注意到的代码调用了这个 getter,并且依赖它的返回值进行一系列判断,由于拿不到正确的值,这部分功能直接挂了。

这给了我一个教训:删除幽灵代码是实现新功能以及重构的必要工作,而不是后续。不仅仅是要最终删掉,还要删得及时。想把代码多留一会是程序员的本能,“万一有用呢”。我们必须去对抗这种本能。

单元测试真的不靠谱

按理说有测试,前面那个问题应该能发现。但实际上并没有。单元测试里该 mock 的东西都被 mock 掉了,包括那个不应该继续存在的属性,导致测试 false positive.

从本质上来说,单元测试之所以不能发现所有问题,是因为程序有无穷多的输入和内部状态,而单元测试只能检测其中一部分,即使代码测试覆盖率达到了 100%。依赖别的组件的测试又往往需要 mock,一旦实际运行状态和 mock 不符,等于什么也没测。因此测试不挂说明不了任何问题。

一般而言,集成测试(integration test)是单元测试的良好补充。然而这套系统是一个 streaming system,数据来源又多,想搞集成测试是真的难,我并没有足够的时间来做这件事。这种情况下,能做的也只有起一个测试环境,手动测试。其实重构后的代码在测试环境里也跑了几天,但我恰恰没去测试那个功能。以前看见 QA 们照着文档一遍遍重复相同的操作,觉得真繁琐,现在想来,这种繁琐和机械化是不可或缺的。

类似的,另外一个 bug 也是因为测试里输入设置得不对,并且最后没有实际验证。

话说回来,如果有无限时间,那么我们完全可以把整套运行逻辑都想得很清楚,检查每一个单元测试是否需要更新,这样所有的问题都可以避免。然而人不是机器,一定会有注意不到事,并且我们也没有无限的时间。因此我们只能尽量运用一些“原则”,去减小犯错的可能或是提早发现错误。

要学的东西果然还有很多啊。


top