Ant Design 今天的圣诞门闹得沸沸扬扬,Ant Design 内建的圣诞彩蛋在各个使用 antd 的产品中被「强制」弹出,令许多人措手不及,造成了很大的社会影响。但事实上,Ant Design 使用的是 MIT LICENSE,完全是一个使用者「后果自负」的协议。然而,Issue 里哭天喊地要开发者「负责」的舆论却又一面倒。

在此,我要问一个问题:「Ant Design 错了吗?」

is-ali-wronh

就我来看,毋庸置疑,错了。

但这篇文章讨论的是以下几点:

  • Ant Design 犯了什么错?
  • 开源的权利与责任的界限在哪里?
  • 我们应当怎么从这个事件中获取教训?

Ant Design 犯了什么错?

从产品的角度来看,这个彩蛋,连彩蛋的定义都不符合。彩蛋(Easter Eggs)是一个隐藏在程序中的信息,而不是突然糊在你脸上的定时炸弹。所以从想出这个问题的那个人就已经不太对劲了。但我们抛开这个产品的问题,从实现上,这个 Santa.jsx 文件也同样是非常糟糕。作为一个组件级项目,很多人会对组件样式做二次开发,这一坨硬编码(Hardcoded)并没有起到它彩蛋的作用,相反还把很多网站弄得一团糟。如果你试图阅读过 Ruby 的代码,你往往会发现 Ruby 有那么多错误命名的 C API 为什么一直不把它改对呢?因为这种语言级别的东西,你无法确定用户是怎么使用的时候,就必须保持最低限度的兼容。Ant Design 也是如此。

然而「人主之患在莫之应,故曰:一手独拍,虽疾无声。」导致 Ant Design 问题的,不单单是彩蛋本身的错,更大的是 Ant Design 开源社区开发流程的问题。或者换一句话说:是软件工程的问题。

如果我们现在要往一个开源项目中加入一个不合适的东西,其实并不那么容易。Ant Design 有基于 GitHub Pull Request 系统的 Code Review 机制。一个并非紧急的代码,为什么可以直接跳过 Code Review 直接推上去?Ant Design 作为一个组件级的基础项目,到底应该怎么设计测试?

这个 2017 年 12 月 25 日 写下的代码,写入到发作的这一年中,暴露的并不是谁的错,而是这个项目本身就是一个错误。

如何运行一个开源项目?

Ant Design 错了,需要检讨,需要反省,需要道歉。但另一方面,在 Issue 下大骂「要阿里负责,要阿里赔偿」的则是走向了另一个极端。今天的开源项目,在使用常见的 Copyleft 许可证的情况下,大多数(包含且不止包含 MIT、BSD、GPLv2、GPLv3、AGPLv3、LGPLv3、MPL 2.0、Apache License 2.0、The Unlicensed)都在许可证中明确写了,不包括任何保修的条款,使用者自行负责。这让很多人听起来匪夷所思,觉得 Ant Design 一个阿里的产品,怎么也是阿里在背书。然而事实上,可能除了信誉,没有规定任何东西是实质的背书。前几天有人在 Ruby China 上开了个帖子问:

到某某网站上浏览时,发现上面说,以上版本均需获取商业授权,方可做商业运营使用,既然是开源的,咋还涉及到商业授权啊,不理解,请指教。谢谢!

然而版权的实际情况却恰恰相反。源代码放出来只是让你看,并不能让你用。就像别人放在那里的芒果,你不能寻思是别人不要了吧。代码是不是开源,需要取决于使用什么授权协议。哪怕是 GPL 的 RedHat 也有卖商业服务的。如果人家没有设定任何授权协议的话,那就只能默认是 Copyright 私有了。而只有签了具体包含保修责任的条款的协议后,对方才有保修的义务。不然,我自己写着玩开源出来,你用的时候也已经同意免责了。你用出问题了为什么要来找我呢?有问题你自己 fork 了改不就好了?

这就牵扯到了另一个问题:开源的社会价值。当一个开源产品,比如 Ant Design,有大量的用户在使用的时候,对于这个开源社区的期待是完全不同的。这也是为什么世界上大多数的大型开源项目,都有一个庞大的组织在维护着。其目的很大程度上,就是要维护代码的可靠性,担负起其社会价值。你觉得阿里价值观能担负起社会价值吗?

有人在我微博下呛:

照右边这个逻辑的话,广大 MIT 框架作者应该纷纷往自己代码加挖矿,这世界不需要开源,人与人也不需要信任。别人写好的高级语言也别用啊,一起汇编起来。

然而事实上,如果你愿意找一下,GitHub 上许多 MIT 项目是有暗藏挖矿的,甚至还有暗藏后门的。至于「别人写好的高级语言也别用啊」也是如此,UNIX 创始人 Ken Thompson 在 30 年前获得图灵奖的获奖演说中,就有提到这种类似的暗藏在 C 语言编译器中的手段实现攻击。这也是为什么一方面 C 语言编译器也有一套复杂的自举发布流程,像 gcc 还会有严格的代码审查机制来避免这种问题的发生。然而甚至硬件本身,也不是 100% 可信的。这不是「人与人的信任」问题,相反,就算 100% 相信别人不去做坏事,但是由于人都会犯错,总会做出错误的东西,我们需要的是通过机制来避免它发生。

在以前一个非常有名的 NVIDIA 开源驱动的维护项目 bumblebee 中就有出现过开发者疏失,导致更新的用户直接把所有的 /usr 用户文件不小心删了个精光。甚至有人曾试图通过给 Linux 项目提交 patch 的形式,将后门埋入操作系统中。并且这些看起来不经意的错误,甚至会使得一些人为的 Code Review 失效,所以 Linux 还有复杂的安全性和回归测试来保证其可靠性。

如果这不是无意的行为,而是有意的。那么对于开源世界,我们有个更简单的方法:fork。我们只要分叉一个自己的版本,自己维护自己负责就可以了。MySQL 被 Oracle 收购后,虽然 Oracle 暂时还没有做什么坏事,大家为了谨防这种情况发生,就有一些开发者 fork 出了 MariaDB。

但是,我也反过来问一句:你 fork 后的项目,你真的能维护得更好吗?

软件工程是一个复杂而庞大的东西,把七个积木搭在一起,和把七千万块积木堆在一起是完全不同的系统工程问题。开源软件的管理看起来松散,于是更需要设计合理的制度防范于未然。在挑选开源项目的时候,并不只是挑一个能用的就行了,对于其质量、维护能力、开源协议都必须是评估的内容。我不是在说「用开源的东西不审查代码,出了问题活该」,但是什么都不看,不出问题才奇怪吧?

教训

为什么包括谷歌微软在内的大公司,在使用别人的开源项目时,都要经过内部审查。虽然不至于精确到每行代码,但也要大致确认一下这个项目的状况。这也是为什么,Facebook 之前内部许可证事件沸沸扬扬,因为这真的很重要。就好像,警察在努力阻止盗窃案的发生,但我们自身平时就要做好防范,而不能大门敞开,出了事去骂警察吧。

然而现实的情况却是,用 Ant Design 的本来就是一群想用个组件库草草了事的人,根本没有可能去参与到开源项目的审查中。而 Ant Design 目前草率的开发流程,确实也无法承担如此大的社会责任。如果今天不是「偏右」的圣诞节代码出了问题,明天后天一样会出别的问题。如果今天是「偏右」辞退就来平息风波,那么明天后天 Ant Design 还是会继续出问题(毕竟是阿里嘛)。

judge

今天 Ant Design 的问题是一个典型的软件工程问题,让任何一个个人来负责,都只是息事宁人的策略,并不能从根本上解决问题。对于一个「开发公司 HR 工具的离职谈话功能推到开发者头上;匿名表达对老员工,特别是对彭姓员工不满,大老板可能含沙射影地让你滚;用脚本在公司网站抢月饼,可能违反价值观」的公司,你指望它在软件工程上有秩序吗?

我觉得你在做梦。

总结一下:

  • 开源项目本身并没有所谓的「责任」的概念,你要有自己评估其可靠性的能力,并承担风险。
  • 评估可靠性不在于其背后是多大的公司,更在于其是否有健全的开发流程,因为人为疏失不可避免。
  • 越是底层、组件级的项目对于可靠性的要求越高。
  • 只要不是主观上故意犯错误,我们更应该检讨我们的系统工程,而不单单是检讨个人。