Julia 用户喜欢认为他们喜欢的编程语言易于使用,因此它可以促进良好的编程实践,例如编写文档、测试代码和使用持续集成 (CI)。但是……这是真的吗?为了尝试回答这个问题并获得更多关于 Julia 生态系统的见解,我们开发了一个名为 PackageAnalyzer.jl
的包,并在为期 2 个月的 JuliaCon 2021 之前使用它对 通用 注册表中的包进行了调查。在这篇文章中,我们总结了我们在 JuliaCon 2021 演讲 中提出的主要发现,我们建议观看以获取更多详细信息。
我们发现,截至 2021 年 1 月 7 日,通用注册表中的 5166 个包在其 src
目录中总共有 8,015,887 行 Julia 代码,在整个包目录中(包括文档和测试)总共有 11,777,430 行 Julia 代码。请注意,由于我们用于计算代码行数的软件 Tokei 中存在一个错误,因此这些数字包括文档字符串。
下图显示了按代码行数划分的包的分布,采用半对数刻度:我们可以观察到包遵循对数正态分布,中位数为 507 行。
我们还使用了 WordCloud.jl
来根据行数和代码创建通用注册表中包的词云。
下表显示了注册表中 14 个最大的包,按其 src
目录中的代码行数排序。我们应该注意,许多这些包的源代码是从它们包装的外部库或 Web 服务的 API 自动生成的。
名称 | src 中的 Julia 代码行数 |
---|---|
AWSSDK | 264,115 |
AWS | 225,723 |
Hecke | 130,560 |
TensorFlow | 115,544 |
OrdinaryDiffEq | 92,308 |
GSL | 69,761 |
DSGE | 58,835 |
ClimateMachine | 58,281 |
Kuber | 54,331 |
MathOptInterface | 51,297 |
Azure | 44,766 |
Nemo | 41,377 |
NIDAQ | 40,913 |
GlobalSensitivityAnalysis | 40,719 |
此图表显示了包的 src
目录中存在的文件中使用的语言的分布:可能很容易猜到最流行的语言是 Julia 本身,而且比例非常大,其次是 Javascript、JSON 和 Fortran。但是请注意,这些数字并未捕获使用所谓的 JLL 包 包装二进制库的包,因为它们会自动下载这些库的预构建副本,而无需提供其源代码。
虽然通用注册表中超过 96% 的包都获得了 开源计划 (OSI) 批准的许可证,但大约 200 个包似乎根本没有任何许可证,而 20 个包的许可证未被自动检测为 OSI 批准的许可证。
Julia 的公共包注册表长期以来一直要求使用 OSI 批准的许可证(可追溯到 2015 年 10 月),但此要求在 一段时间内未在通用注册表自述文件中记录,并且仅 从去年 3 月开始自动执行。现在,任何新的包或已注册包的新版本必须具有自动检测到的 OSI 批准的许可证才能获得自动批准,才能合并到通用中。自从引入此自动检查以来,具有 OSI 批准许可证的包的比例一直在稳步增长。
MIT“Expat”许可证是 Julia 生态系统中迄今为止最受欢迎的许可证,这可能是因为它是由 Julia 本身的源代码采用的许可证。其他流行的许可证包括 GPL(v3 或 v3 及更高版本)、Apache 2.0 和 3 条款 BSD。
如果您想让其他人使用您的包,您可能需要对其进行文档记录!这通常以自述文件中的某些段落或使用 Julia 用户可用的工具(例如 Documenter.jl
)编写的专用手册的形式出现。通用中约 88% 的包在其自述文件中至少有 20 行或具有适当的文档。
下图显示了代码库中文档百分比的分布,方法是计算 docs
目录中的代码行数与 docs
和 src
目录中代码行数总和的比率。不到 50% 的包在其存储库中具有基于 Documenter.jl
的文档。这是否意味着超过一半的 Julia 包没有文档?不一定:非常简单的包的作者可能会认为 README
足以描述其包的使用情况。这也可能与大多数包相对较短(包括文档字符串在内不超过约 500 行代码)的事实相关。此外,在某些情况下,文档的源代码可能托管在不同的存储库中,这里不会计算在内。
测试是另一种重要的编程实践:它可以确保代码按预期运行,并且由后续更改重新引入的错误不会再次发生。Julia 带有 Test
标准库。Julia 带有内置的单元测试框架这一事实可能会鼓励用户测试其包:通用注册表中超过 96% 的包都具有 test/runtests.jl
文件,这是使用 Julia 的包管理器运行测试的入口点。如果我们只考虑 test
目录中至少有 10 行代码的包,以确保我们排除了没有实际测试的简单自动生成文件,则该比例下降到 89%。在下图中,“10% 测试”和“20% 测试”的百分比表示 test
中的 Julia 代码行数与 src
和 test
中的 Julia 代码行数之和的比率。
与我们上面针对文档看到的类似,下图显示了代码库中测试百分比的分布,作为 tests
目录中代码行数与 tests
和 src
目录中代码行数总和的比率。我们可以观察到测试水平相当高:57% 的包至少有 20% 的代码作为测试,而 8% 的包的测试行数超过源代码行数。
Julia 用户似乎喜欢 持续集成 (CI)!生态系统中惊人的 95% 的包都已设置为使用任何持续集成服务,其中 GitHub Action 是最流行的服务(80%),其次是 Travis(42%)和 AppVeyor(13%)。
我们可以看看 CI 服务的流行度随时间推移的变化:一个共同的趋势是 GitHub Actions 正在取代 Travis 和 Appveyor,后者曾经是 Julia 用户在最流行的操作系统(Linux、macOS、Windows)上测试其包的主要选择。Travis 的下降趋势在去年加剧,当时对其条件的更改使此服务不太适合开源项目使用。
截至 2021 年 6 月 27 日,至少有 4931 名不同的用户为托管在 GitHub 上的 Julia 包做出了贡献,比两个月前增加了约 250 名。请注意,这些数字是保守的,因为它们不包括 GitHub API 识别为匿名的贡献者(例如,因为他们使用未在任何 GitHub 帐户中注册的电子邮件地址提交了更改),也不包括对托管在其他网站(如 GitLab)上的包的任何贡献。
对 Julia 包贡献者数量的分布表明,绝大多数包只有少数贡献者,每个包的中位数为 2 个贡献者。只有约 11% 的包拥有超过 10 个贡献者,约 1% 的包拥有超过 40 个贡献者。
了解 Julia 用户有多大可能为多个包做出贡献也很有趣:52% 的用户为单个包做出了贡献,略低于 10% 的用户为至少 10 个不同的包做出了贡献,而 26 个超级活跃的人为超过 100 个包做出了贡献。
最后,我们查看了用户提交了多少个 Git 提交:Julia 包开发人员社区中有一半的人至少提交了 10 次,21% 的人至少提交了 100 次,而 51 人提交了超过 2500 次。
以下是我们的主要发现
大多数包确实遵循良好的编程实践(文档、测试、持续集成)!特别是
具有**任何测试**的包比例很高(**96%**),并且**至少 10% 的代码作为测试**(**76%**)
几乎所有包都已设置**持续集成**(**95%**)
文档并不那么流行;只有**49% 的包在存储库中具有文档**
大多数包要么有**自述文件要么有文档**(**88% 至少有 20 行**其中之一或两者)
2021 年 3 月,通用注册表开始强制要求存在**OSI 批准的许可证**才能注册新包或新版本:从那时起,具有许可证的包的比例稳步增长(**97%**)。执行规则有效!
中位数包有**507 行代码**,并且分布看起来是**对数正态**的
至少有**4931 名 Julia 用户**为注册的包做出了贡献
大多数包由**一到最多两位开发人员开发**:较低的 巴士因素!
GitHub 上**42%**的包的存储库是**组织的一部分**,这一事实表明存在强大的协作文化,因此多人可以对其进行写入访问,而不仅仅是其作者,从而降低了包被完全放弃的风险
**583 个包至少有 10 个贡献者**,而只有**11 个包**拥有**超过 100 个**贡献者
**470 名用户**为至少**10 个不同的包**做出了贡献,并且**26 人**在至少**100 个不同的包**中提交了代码
我们想强调一些注意事项
在我们的分析中,我们没有计算超过 700 个已注册的 JLL 包,因为它们是小的自动生成包,不代表 Julia 社区的活动和实践
我们没有衡量“质量”,例如文档或测试的质量,因为很难合理地定义它,因此我们只计算了行数,并查看了不同的分布。有人可能会建议使用 代码覆盖率 进行测试,但这无法静态完成(您需要运行测试),而且它也不一定是好的指标:代码行覆盖率没有考虑不同的代码路径
同样,我们没有检查持续集成服务是否真的在运行。但是,GitHub Actions 是最常用的 CI 服务,并且在 GitHub 存储库中默认启用。如此多的人决定添加 CI 设置仍然非常了不起,这表明他们意识到了这种可能性:如果您将 95% 的带有 CI 设置的 Julia 包与 Jamie Quinn 的此分析 的结果进行比较,他发现只有大约 20% 的在开放源代码软件期刊上发表的软件似乎设置了一些 CI 服务,那么差异是惊人的。
如果您认为收集生态系统的任何其他指标会很有趣,请通过在 PackageAnalyzer.jl
存储库中打开问题等方式与我们联系。