Hacker News 中文摘要

RSS订阅

开源维护者说“不”指南 -- An open-source maintainer's guide to saying “no”

文章摘要

维护开源项目时,拒绝用户提出的好想法是必要的,尽管这些想法设计良好且有用。项目成功不在于功能数量,而在于其愿景的一致性和与用户心智模型的契合。作为维护者,首要任务是确立并坚持这一心智模型,拒绝与之不符的功能,以免破坏项目的核心价值。

文章总结

开源维护者如何说“不”

维护开源项目最困难的部分之一,就是对一些看似不错的功能需求说“不”。用户提出的新功能可能设计精良、实用且没有明显的技术缺陷,但维护者仍然需要拒绝。对用户来说,这可能会令人困惑;但对维护者而言,这是一种必要的管理行为。

作为PrefectFastMCP的创建者和维护者,以及Apache Airflow的贡献者,我深刻体会到,项目的成功不在于功能的多少,而在于其愿景的一致性和与用户的共鸣。正如Prefect的CTO Chris White所言:

“当软件的抽象与用户的心智模型一致时,用户才会选择它。”

开源维护者的首要任务是建立这种心智模型,并始终如一地构建与之相符的软件。一个表面上实用但与项目精神不符的功能,可能会带来威胁,而非增强。

这种威胁有多种形式。最明显的是那些完全超出项目范围的功能,例如为CLI工具添加GUI的请求——这种想法可能更适合另一个项目。更微妙的是那些解决某个用户特定问题,却为其他用户增加复杂性和维护负担的功能。最隐蔽且最具腐蚀性的,是那些与项目模式不符的API,它们会破坏现有模式,给未来用户带来认知失调。

随着项目规模的扩大,维护者如何捍卫项目的灵魂?首先,不仅要记录项目的工作原理,还要阐明其存在的目的。清晰的开发者指南和项目宗旨是维护者的第一道防线。它们明确了项目的哲学,设定了预期,从而吸引更多与项目愿景一致的贡献者。他们的贡献反过来又强化和细化了这一愿景,进一步证明了项目的世界观。

在LLM(大语言模型)时代,这项工作变得更加困难。过去,编写代码是一项高成本、高投入的活动,贡献者通常会在动手前进行讨论。如今,LLM使得代码变得廉价,用户可能会直接提交未经讨论的PR。这些代码可能写得很好,也能“运行”,但它们缺乏对项目哲学的理解,仅仅是为了满足用户的需求,而非维护项目的愿景。

这并不意味着所有未经请求的贡献都不受欢迎。有些PR可能完美地修复了bug或添加了小巧而贴心的功能,这些贡献是值得鼓励的。然而,近年来,未经请求的PR更可能成为高投入审查的对象,而非高质量的贡献。

在FastMCP中,我们尝试通过要求每个PR都附带一个issue来引导这种行为,但结果却适得其反。更有效的方式是明确表示,我们不确定框架是否应该承担某些用户需求的责任。如果贡献者能说服我们,那对所有人都有益。但正如我之前所说,证明的责任在于贡献者,而非项目。

另一个微妙的拒绝理由是,维护者可能不愿意长期维护某些代码。在开源项目中,PR的合并意味着责任的转移。如果它引入了bug、混淆或不一致性,甚至引发了更多的功能需求,维护者通常会成为最终的负责人。在FastMCP中,我们引入了contrib模块来解决这个问题。该模块包含一些可能不适合核心项目的功能,并由其作者独立维护,不保证与未来版本的兼容性。

我观察到自己在行为上的变化。在Prefect的早期,我们尽力在15分钟内回复用户问题。如今,如果用户没有表现出基本的参与度,我可能会以低投入的方式回应。面对LLM生成的大段文字和清晰直接的问题,我每次都会选择后者。

这种深思熟虑的管理方式,是区分普通项目和伟大项目的关键。我们曾经称之为“社区”,我希望它不会消失。作为开源维护者,你应该对每一个参与项目的人心怀感激。你的责任是确保今天的“不”能引导贡献者走向明天的“是”。

当这种深思熟虑得到充分应用时,它将为所有用户带来更好的体验,使软件的抽象与普遍的心智模型一致。这种管理方式值得我们去捍卫。

两周前,我在纽约参加了MCP委员会的会议,目睹了团队如何巧妙地应对类似的问题。MCP是一个年轻的协议,它在AI堆栈中的地位更多是由兴奋而非成熟推动的。因此,它面临着同时做更多、做更少以及介于两者之间的压力。一个软弱或敷衍的委员会可能会被这种压力压垮,批准任何看似合理的功能以安抚最响亮的声音。然而,我所看到的恰恰相反。最重要的是,团队愿意辩论,并将每个提案与协议的宗旨进行对比。他们对MCP的目的有着深刻的尊重:它应该做什么,更重要的是,它不应该做什么。我特别欣赏David在领导委员会时的坚定态度:“这是个好主意。但它属于协议的责任范围吗?”

这种坚持是技术成熟过程中必要且艰难的工作。我离开纽约时对团队和MCP本身更加有信心,因为每个人不仅在构建协议,还在作为其深思熟虑的守护者。看到这种管理方式在开源中继续发扬光大,我充满期待。

评论总结

  1. 关于开源项目维护者拒绝功能请求的合理性

    • 评论1和评论5指出,即使功能设计良好且有用,维护者仍可能拒绝,因为项目需要保持通用性,避免为特定用例优化。
      • 引用1: "A user proposes a new feature. It’s well-designed, useful, and has no obvious technical flaws. And yet, the answer is 'no.'"
      • 引用5: "Some folks were not happy about it, and Godwin’s Law was invoked on my ass, multiple times."
    • 评论10和评论12强调,维护者没有义务满足所有用户需求,用户应减少对开源项目的过度期待。
      • 引用10: "Maintainers really do need to say no more often, and teach users to be way less entitled."
      • 引用12: "Maintainers owe users absolutely nothing."
  2. 关于LLM生成代码的影响

    • 评论1和评论11批评LLM生成的代码质量差,且未经充分测试,增加了维护者的负担。
      • 引用1: "But since this is about an MCP tool, almost reads like LLM generated and the image above definitely is … maybe you’re part of the problem!"
      • 引用11: "My pet peeve is people who use LLMs to generate code, never check whether it works, and then submit a PR."
    • 评论2认为,LLM无法生成符合项目哲学的高质量代码,代码的“昂贵”性并未改变。
      • 引用2: "Good code, that reflects, or even evolves, a project’s philosophy - is 'expensive'. LLMs can’t write it."
  3. 关于开源项目的功能扩展与维护

    • 评论4和评论13主张,项目应避免无意义的功能扩展,专注于核心功能和修复。
      • 引用4: "More OS projects need to be willing to stop adding features and just focus on the occasional bugfix or security update."
      • 引用13: "Just the other day I got flak for saying no to accepting another version of a tooltip that had a different icon."
    • 评论6建议通过鼓励分叉来解决功能请求问题,让贡献者自行承担维护责任。
      • 引用6: "encourage published forks. This allows the contributor to shoulder the burden of packaging and support."
  4. 关于代码讨论与决策的重要性

    • 评论3和评论7强调,在编写代码之前进行充分讨论和决策是必要的,以避免资源浪费。
      • 引用3: "Discussion about a feature or a bug is done before writing any code."
      • 引用7: "In writing, you must kill all your darlings."
    • 评论14指出,维护者有权拒绝不符合标准的PR,尤其是缺乏测试和文档的代码。
      • 引用14: "I don’t accept pull-requests on my very modest open source project."

总结:开源项目维护者在面对功能请求时需要权衡项目的通用性和特定需求,拒绝不合理请求是常见的做法。LLM生成的代码质量参差不齐,增加了维护负担。项目应避免无意义的功能扩展,鼓励分叉和充分讨论是解决功能请求的有效方式。