总是看到有人说,动态一时爽,重构火葬场。然而这世界上有的是著名的开源项目, 也有像 Github、Instagram 这样流量巨大的知名网站是基于动态语言开发的,经过了这么多年重构,也未听说哪个作者进了火葬场的,不明白这些人是真的不知道还是装作看不见呢?不过他们说动态语言大到一定程度就无法维护,虽然这话也同样不值一驳,不过也提醒了我,我也很好奇用动态语言开发的项目规模能大到什么程度。
从我知道的信息看,用动态语言开发的***规模的项目可能要算是 OpenStack ,据说代码总量已经达到数百万行,并且还在持续增加中。这当然是一个说明动态语言能力的好例子。不过像这样巨大的项目,要分析起来也并不容易(好吧,真正的原因是我懒得下载那么庞大的代码库)。我选择了 Python 社区中比较知名的一些项目来分析,主要是来自 Github ,也有个别来自其他仓库。这个选择可能包含了一定的主观因素在内,不过我相信大多数项目还是非常有代表性的。
计算代码数量的工具是 cloc 。所有项目均选择截止到 2018 年 1 月 3 日的主干代码,统计中仅包含 Python 文件,排除了其他文件类型。值得说明的一点是, 通过 Ubuntu APT 默认安装的 cloc 版本 1.60 在统计部分项目的时候存在问题,该问题在***的版本中已经得到解决,因此本文中所有统计均使用从官网下载的 cloc v1.72。
上表已经按代码行数排了序。有意思的一点是, 代码规模***的前4名中除了 CPython 之外其他三个全部是运维性质的项目,本来我猜测代码应该比较多的项目比如 Odoo 排名反而很靠后。我对运维项目了解有限,不太清楚为什么这些项目的代码规模会名列前茅,或许是因为要支持的内容比较多而杂?
本次统计中纯 Python 代码量***的 Sentry 几乎达到了 70W 行,这是相当有规模的项目了。30W~50W 行代码的项目有三个,包括基础项目 CPython 在内。20W 和 10W 行代码规模的分别有三个,剩下 7 个则在 10W 行以内。看过这个列表你应当相信,动态语言至少在几十W行代码的项目上是完全没有问题的。这也是绝大多数普通应用的上限了,如果代码真的达到数百万行规模的话,那么无论用什么语言,都势必面临着拆分项目的问题。
上表将代码量指标按照代码/空白/注释进行了分类,也在一定程度上反应了项目的代码风格。Sentry 是本次统计中代码量最多的项目,然而从表中可以看到,项目中的注释和其他项目相比,少得有点不成比例,说明 Sentry 的作者非常不注重注释。
同学们一定发现了,我在列表中除了代码行相关的指标之外还增加了几个其他内容,这也是我个人比较感兴趣的方面。
***个指标是每个文件的平均代码行数。按照模块化的观点,单个文件中堆砌太多内容显然是不合理的,这通常意味着耦合太多、难于理解和修改。然而到底多少算是合适,并没有一个明确的标准。我希望通过这些项目的分析,了解一下开源作者们在实践中做出的选择。
统计的结果分布比较平均,从 100~600行/文件的都存在,并不存在明显的集中点。有趣的是,头两名(Pandas, NumPy)有着紧密的联系,都是和数学统计相关的。这可能是因为数学库的特点比较纯粹而单一,不像其他类库那样容易划分。末尾的项目(Pillow, youtube-dl, Odoo, Scrapy)可以从侧面印证这种猜想:它们都是面向特定领域的,所以更加容易模块化。
第二个指标是注释和代码的比例,这个问题也有着类似的情况。注释并非越详尽越好,但总是需要一定量的注释来解释 Why 的问题。注释太少,说明项目的作者没有给后来的维护人员留下足够的线索,可能会造成维护上的问题。另一方面,我们考察的全部是开源项目,没有公司考核或者 KPI 的约束,所以我们可以放心的相信不会存在作者故意多写注释的问题。前面提到的 Sentry 毫无争议的因为注释太少排到了***,这未必说明这个项目很差,但至少是一个信号,说明该项目在维护方面可能是存在问题的。而对于那些作者愿意投入精力来写注释的项目(Ansible, NumPy, Fabric, Salt 等),足以反映作者在项目上投入了相当大的心力,这是一个好的信号,说明这些项目是值得信赖的。
有一点是出乎我意料的,那就是作为所有项目之母的 CPython 排名比较靠后,按照道理这个基础项目应该有更多的注释才对。不过再想一想又觉得可以理解,因为 CPython 有单独发布的、非常详尽的文档,这是其他大多数项目都没有的,那么代码中的注释少一些也是情有可原的。
***一项统计是关于文件类型的。Python 项目中绝大多数应该是 Python 代码,这点没有什么疑问,但同时我也想看看除了 Python 代码之外,一个项目还包括哪些主要文件。C/HTML/Javascipt 的上榜是毫不意外的,但有一种文件我事先没有想到,那就是 .PO(开源项目常用的语言资源文件)。对于 Django 和 Django-CMS 这两个项目, PO 代码数量甚至比 Python 代码还要多。大概看了一下,Django 支持 90 种以上的语言,这也无怪乎语言文件的数量如此之多了。这个结果也可以提醒我们,有些同学——不仅是程序员,也包括大多数经验不足的老板、客户、产品经理等——会下意识的认为程序开发无非是写代码,对于代码之外的其他工作,在估算的时候往往只拍脑袋式的定下一个极短的时间。但对于实际的项目来说,代码仅仅是其中的一部分,“其他工作”有时候——应该说是经常——会占用你大部分的的时间和精力。这些工作往往并不有趣,但对于项目来说又是必不可少的组成部分,希望同学们予以足够的重视。