这篇文章说说用户怎么提出好的 feature request / pull request, 以及维护者如何对待它们.
这里, 我们忽略那种特别简单的 (例如 10 行代码以内可以实现的) request, 只考虑 non-trivial 的 feature request 和 pull request.
首先, 一个残忍的事实是, 开源项目中大多数的 feature requests 不会得到 maintainer 的回应. 理由也很简单: 项目的资源是有限的, 而修 bug, 维护现有 feature 的优先级自然会更高. 当项目有额外的开发资源时, 一般也会优先推进团队自己原有的开发计划 / roadmap, 或优先为项目的赞助方 (如背后的公司) 实现 feature. 路人的 feature request 优先级可以说是最低的, 排在所有这些之后.
下图是 vscode 社区处理 feature request 的流程: (来源)
Vscode 是一个非常注重社区的项目, 因为编辑器必须要有好的生态才能成功. 因此我们才能看到 vscode 把用户的 "upvote" 也考虑在内. 绝大多数项目并没有这最后一步: 和项目 roadmap 不 align 的 feature request, 一般就直接进入 backlog 了.
在这种情况下, 要想提出一个 "好的 feature request", 并得到 maintainer 的重视, 当然不是那么容易. 一个好的 feature request 一般至少要在以下某一点中比较突出:
要做到这些, 有时候确实需要用户对项目有一定的深入了解, 能够把握住项目的 direction. 毕竟想要项目的 developer 改变原定的计划, 自己没两把刷子是不行的.
反过来, 一个 "平凡的 / 不好的 feature request" 可能会有如下特征:
当然, 一个平凡的 feature request 照样值得提出, 虽然它可能会进入 backlog 暂时无人问津, 但是也许在沉寂一段时间之后会引发更有价值的讨论和实现.
Pull request 是社区向项目贡献代码, 因此一般更受 maintainer 欢迎, 但也不全是. 围绕 pull request 的主要矛盾是 可维护性 : 当 maintainer 同意接受一个 PR 时, 就意味着 maintainer 同意负责维护这段别人写的代码, 这对代码的可维护性是有要求的.
因此, 用户应该认识到, maintainer 关注的绝不仅仅是一个 PR 是否 "work", 而是会考虑更多的因素:
Jeff Geerling 的 Why I Close PRs 和 The Burden of an Open Source Maintainer 也介绍了什么样的 PR 是 maintainer 更乐于见到的. 文章写的很好, 且另外提到了一条重要的沟通原则:
Maintainer 应在CONTRIBUTING.md
或 .github/pull_request_template.md
里为 contributor 提供引导, 包括介绍提交 PR 的注意事项, PR 被接收的原则, 项目的 coding style, 如何使用 linter, 如何测试, 如何更新 documentation, 等等. 例如 detectron2 的 contributing.md 和 pull_request_template.md.
开源社区中, 用户会有无数不同的需求. 即使 maintainer 有时间 (大部分 maintainer 没有) 去处理 feature request / pull request, 也会有很多人的需求无法满足.
在这种现实下, 面对没有精力实现 / 维护的 {feature, pull} request, maintainer / contributor 可以采取的一个好的策略是: 通过一些改动让项目变得更 extensible, 使得 feature 可以被用户以扩展 / extensions 的方式独立实现, 而不是在项目中实现.
具体要怎么做到这一点, 是一个系统设计问题, 这篇文章就不跑题多说了. 采用这种方式的好处是:
很多成功的开源项目都是靠着可扩展性创建了优秀的生态.
Tensor
subclass, 自己的 device 等非常夸张的扩展. 最近的torch.fx
也是在给用户实现 graph transformation 扩展的机会.PyTorch 团队会使用 "extension points" 这个词, 指系统中可以由用户实现扩展的部位.Detectron2 也从最初就尽量走这条路, 把 "尽量让所有模块都可扩展 / 可替换" 作为一个设计目标.Facebook 与之相关的 research project 就都以 detectron2 扩展的形式开源. 除此之外也有不少来自社区的优秀扩展, 例如 AdelaiDet, YOLOv7 等.
如果 pull request 并不容易被接受, 那么开发者是不是应该干脆自己 fork 项目, 来实现自己想要的改动呢? 要回答这个问题, 要先想清楚将这些改动开源的目的是什么:
如果只是一个 proof-of-concept, 为了公开的展示这个改动的内容, 那么 fork 是没问题甚至更合适的:
开发者也要意识到, 如果认为自己的工作不只是一个 proof-of-concept/toy, 想要让自己的 fork 真的被人严肃的使用的话, 就不得不自己承担维护的责任. 而维护的负担是很重的, 挑几个点来说:
因此, 虽然一个成功的 pull request 要付出额外的交流, 但它换来的是项目维护者的维护工作. 如果开发者想加入新 feature, 又没有自信能胜任整个项目的维护, 与其另起炉灶, 不如多参与交流, 与维护者讨论一个更可维护的方案 (pull request 或 extension).