向 Trunk 提交 Podspec 后,文档服务 CocoaDocs 会为 Pod 生成一系列指标。您可以在 metrics.cocoapods.org/api/v1/pods/[Pod] 上查看任何 Pod 的这些指标。这些指标用于生成各种质量修饰符,最终转化为一个称为质量指标的数字。
本文档是 可读编程 的一种形式,位于 CocoaDocs-API 中。因此,它包含为了生成各个分数而运行的实际 Ruby 代码。此外,Swift 看起来像 Ruby - 所以您可以阅读它 ;)。
质量指标的目的是突出显示积极指标,并淡化消极指标。完全不应用任何修饰符的 Pod 是非常有可能的。这意味着指标保持在默认数字 50。这是一个相当合理的评分。
我们对修饰符的心态的一个很好的例子是考虑一个大部分代码都是 Swift 的 Pod。它会得到提升,而 Objective-C 的代码则不会被修改。这并不是为了减少 Objective-C 的积分,而是为了突出显示目前一个 Swift 库代表了前瞻性的最佳实践。
最后,在我们开始之前。这些指标并不是一成不变的,自发布以来它们一直在不断发展,未来也将继续发展。我们欢迎反馈,最好在 问题 中提出 - 以便进行讨论。
流行度指标
一个非常受欢迎的库很可能是一个维护良好的库。我们根据各个指标的价值高低对不同的指标进行加权,而不仅仅是使用星级作为核心指标。
Modifier.new("Very Popular", "The popularity of a project is a useful way of discovering if it is useful, and well maintained.", 30, { |...|
value = stats[:contributors].to_i * 90 + stats[:subscribers].to_i * 20 + stats[:forks].to_i * 10 + stats[:stargazers].to_i
value > 9000
}),
但是,并非每个想法都需要足够大才能保证如此高的指标。大量参与本身就有用。
Modifier.new("Popular", "A popular library means there can be a community to help improve and maintain a project.", 10, { |...|
value = stats[:contributors].to_i * 90 + stats[:subscribers].to_i * 20 + stats[:forks].to_i * 10 + stats[:stargazers].to_i
value > 1500
}),
Swift 包管理器
我们希望鼓励对 Apple 的 Swift 包管理器的支持,社区统一会更好。有关更多信息,请参阅我们的 常见问题解答。这目前检查是否存在 Package.swift
,一旦 SPM 开发速度放缓,我们可能会过渡到测试它是否支持最新版本。
Modifier.new("Supports Swift Package Manager", "Supports Apple's official package manager for Swift.", 15, { |...|
cd_stats[:spm_support]
}),
自述文件评分
README 得分基于一种算法,该算法会查看捆绑 README 的多样性。你可以在此处的 clayallsopp.github.io/readme-score 上针对任何 URL 运行该算法。README 是你的库的首页,它可以提供 API 概览或展示库可以做什么。
听起来可能很奇怪,如果你提供一个二进制 CocoaPod,那么将你的 README.md 嵌入到 zip 中是值得的。这意味着 CocoaPods 可以使用它来生成你的 Pod 页面。我们从项目的根目录中查找两个目录的 README{,.md,.markdown}
。
注意:这些修饰符仍在不断变化,因为我们希望考虑 Podspec 的 documentation_url
。
Modifier.new("Great README", "A well written README gives a lot of context for the library, providing enough information to get started. ", 5, { |...|
cd_stats[:readme_complexity].to_i > 75
}),
Modifier.new("Minimal README", "The README is an overview for a library's API. Providing a minimal README means that it can be hard to understand what the library does.", -5, { |...|
cd_stats[:readme_complexity].to_i < 40
}),
Modifier.new("Empty README", "The README is the front page of a library. To have this applied you may have a very empty README.", -8, { |...|
cd_stats[:readme_complexity].to_i < 25 && spec.documentation_url == nil
}),
CHANGELOG
拥有 CHANGELOG 意味着人们可以更轻松地比较旧版本,作为质量指标,这通常表明一个更成熟的库,维护者会小心地展示更改。我们从项目的根目录中查找两个目录的 CHANGELOG{,.md,.markdown}
。
Modifier.new("Has a CHANGELOG", "CHANGELOGs make it easy to see the differences between versions of your library.", 8, { |...|
cd_stats[:rendered_changelog_url] != nil
}),
语言选择
Swift 正在发生。我们希望积极区别对待使用 Swift 编写库的人。
Modifier.new("Built in Swift", "Swift is where things are heading.", 5, { |...|
cd_stats[:dominant_language] == "Swift"
}),
Objective-C++ 库可能难以与 Swift 集成,并且可能需要与大多数项目习惯不同的编程范例。
Modifier.new("Built in Objective-C++", "Usage of Objective-C++ makes it difficult for others to contribute.", -5, { |...|
cd_stats[:dominant_language] == "Objective-C++"
}),
许可问题
GPL 是一个合法的许可证,可用于你的代码。但是,它与将 App 放到 App Store 上不兼容,而大多数人最终都会这样做。为了防止这种情况,我们从 GPL 库中扣分。
Modifier.new("Uses GPL", "There are legal issues around distributing GPL'd code in App Store environments.", -20, { |...|
cd_stats[:license_short_name] =~ /GPL/i || false
}),
还有很多库使用 WTFPL,这是一个旨在不成为许可证的许可证。它被 OSI(一个开源许可机构)拒绝,因为它与不包含许可证没有什么不同。如果你想这样做,请使用公共领域许可证。
Modifier.new("Uses WTFPL", "WTFPL was denied as an OSI approved license. Thus it is not classed as code license.", -5, { |...|
cd_stats[:license_short_name] == "WTFPL"
}),
代码调用
测试库很重要。当你有一个人们依赖的库时,能够验证你期望的工作是否有效会提高质量。
Modifier.new("Has Tests", "Testing a library shows that the developers care about long term quality on a project as internalized logic is made explicit via testing.", 4, { |...|
cd_stats[:total_test_expectations].to_i > 10
}),
Modifier.new("Test Expectations / Line of Code", "Having more code covered by tests is great.", 10, { |...|
lines = cd_stats[:total_lines_of_code].to_f
expectations = cd_stats[:total_test_expectations].to_f
if lines != 0
0.045 < (expectations / lines)
else
false
end
}),
CocoaPods 使得创建具有多个文件的库变得容易,我们希望鼓励采用更小、更可组合的库。
Modifier.new("Lines of Code / File", "Smaller, more composeable classes tend to be easier to understand.", -8, { |...|
files = cd_stats[:total_files].to_i
if files != 0
(cd_stats[:total_lines_of_code].to_f / cd_stats[:total_files].to_f) > 250
else
false
end
}),
所有权
CocoaPods Specs Repo 未经整理,对于较大的 SDK,人们会创建非官方 Pod。我们需要一种方法来声明此 Pod 来自库的作者,因此,我们验证了帐户。这些对 Google、Facebook、Amazon 和 Dropbox 等规模的公司很有用。我们非常谨慎地应用此方法,并已逐个联系公司。
Modifier.new("Verified Owner", "When a pod comes from a large company with an official account.", 20, { |...|
owners.find { |owner| owner.owner.is_verified } != nil
}),
维护
我们希望鼓励人们使用其库发布语义版本。对于尚未达到 1.0.0 的库,很难知道会发生什么,因为那里没有社会契约。这是因为在 v1.0.0 之前,库作者不会做出向后兼容性的承诺。
Modifier.new("Post-1.0.0", "Has a Semantic Version that is above 1.0.0", 5, { |...|
Pod::Version.new("1.0.0") <= Pod::Version.new(spec.version)
}),
当需要弃用库时,我们应该在搜索结果中反映这一点。
Modifier.new("Is Deprecated", "Latest Podspec is declared to be deprecated", -20, { |...|
spec.deprecated || spec.deprecated_in_favor_of || false
}),
其他 - GitHub 特定
这是一个实验,用于确定项目是否已废弃。问题可以用作待办事项列表,但保留 50 多个未打开的问题感觉有点不妥。项目更有可能已结束。
Modifier.new("Lots of open issues", "A project with a lot of open issues is generally abandoned. If it is a popular library, then it is usually offset by the popularity modifiers.", -8, { |...|
stats[:open_issues].to_i > 50
})