.. _mep-0001: ======================= MEP 1 -- MEP 目的和准则 ======================= :编号: 1 :标题: MEP 目的和准则 :作者: The MegEngine Open Source Team :状态: 草稿 :类型: 流程 :创建时间: 2021-06-09 .. note:: 我们正在尝试以 `PEP 1`_ 内容为蓝本撰写、实施该提案,感谢 Python 软件基金会的探索。 什么是 MEP? ----------- MEP 是 MegEngine Enhancement Proposal 的缩写,意为“MegEngine 增强提案”。 每个 MEP 都应该是一份设计文档,负责为 MegEngine 社区提供信息参考,或描述 MegEngine 特性的发展历史。 在标准 MEP 中应提供关于某个特性的简明技术规范,并且介绍实现该特性的基本原理。 我们希望 MEP 能够成为 MegEngine 提出新的重大特性、收集社区对某个问题的意见以及记录已有设计决策的主要机制。 MEP 的作者负责在社区内建立广泛的共识,聆听并记录不同的意见。 当前 MEP 作为 MegEngine 官方文档的一部分,通过 Git 进行版本控制,支持通过 `MEP 修订历史`_ 查看历史版本。 所面向的受众 ~~~~~~~~~~~~ MEP 的典型受众可分为以下几类: * MegEngine 的核心开发人员 * 从社区选举产生的发展改革委员会 * MegEngine 衍生库的开发人员 作为 MegEngine 文档的一部分,文档中的一些页面将引用 MEP 中的内容作为参考(尤其是开发者指南部分), 开发者指南中的内容也有可能发展成为对 MEP 的补充,甚至是新的 MEP. .. note:: * 我们经常会在 MEP 中提到 “MegEngine 发展改革委员会” (MegEngine Development and Reform Commission, 简称 MDRC), 或者 “MegEngine 发改委”、“委员会”。委员会成员的意见将最终决定某个 MEP 是被接受还是拒绝。 * 我们也会在 MEP 中提到 “MegEngine 核心开发者”(MegEngine Core Developer, 简称 MCD) * MEP 编辑(Editor)也是 MEP 发展过程中不可或缺的一个角色。 .. warning:: 当前阶段,MegEngine 社区成员角色选举和分配机制尚未成熟, 请先尝试成为 MegEngine 开发者团体的一员,将来我们会提供额外专门的流程 MEP 以形成规范。 MEP 所用语言 ~~~~~~~~~~~~ 目前要求统一使用中文进行编写,根据用户和开发者的使用语言比例变化,这个决定将来可能会被替代。 MEP 类型 ~~~~~~~~ MEP 可分为三种类型: * **标准追踪类型(Standards Track)。** 此类 MEP 负责描述 MegEngine 中新特性的原理和实现, 也有可能负责在当前版本的 MegEngine 还未提供相应支持之前,描述一个互操作性标准。 * **信息类型(Information)。** 此类 MEP 负责描述与 MegEngine 有关的设计讨论,或为 MegEngine 社区提供信息或指导。 信息类型的 MEP 不会提出一个新特性,因此用户和开发人员可自行选择忽略还是遵循里面的建议。 * **流程类型(Process)。** 此类 MEP 负责描述与 MegEngine 相关的各项流程,或如何对流程(或者里面的事件)进行更改。 流程类型的 MEP 与标准追踪类型有些类似,但又不局限于 MegEngine 本身; 此类 MEP 中可能提出了一个并非针对 MegEngine 源代码库的实现;通常这需要社区达成共识; 与信息类型的 MEP 不同,它们不仅仅是一种建议,社区开发者通常不能随意忽略其中的内容。 样例包括决策流程的步骤、指导与变更,以及开发环境和工具的变更。任何 meta-MEP 也被看作是流程类型 MEP. MEP 工作流 ---------- .. warning:: 单个的 MEP 中需包含有关键的提案或提供新的改进性的想法。 * 小规模的增强或补丁通常不需要 MEP, 可以通过 Issues 或 Pull Request 来进行追踪。 * 一个 MEP 应当关注某一个具体的点;如果 MEP 显得过于分散或宽泛,MEP 编辑将保留拒绝的权利。 * 如果你的 MEP 由于过于宽泛而被拒绝,请考虑将其拆分为多个更加专注的 MEPs. 从一个小的想法开始 ~~~~~~~~~~~~~~~~~~ MEP 的整个流程始于与 MegEngine 有关的灵光一闪。 但一种常见的情况是:用户而非开发者在 GitHub Issue 中提出了某特性需求(Feature Requirement)且为增强(Enhancement)类型, 如果仅描述了需要实现的效果,而实现方案、基本原理、设计规格内容完全由他人补充,则用户不应该纳入 MEP 的作者列表中。 MEP 作者有义务提供更多的细节,而不仅仅是最终的目标。 每个 MEP 必须有一个负责人(即主要作者) —— 要求使用本提案中提到的风格和格式进行 MEP 的编写,引导用户在社区中进行讨论, 并试图围绕这个想法建立社区共识。MEP 的负责人首先要做的是:确定自己的想法是否可形成 MEP. 如果不是很确定,最好的方式是在 MegEngine 官方论坛相关的板块(或任何正式渠道)提前进行交流。 在编写 MEP 之前要求在社区提前交流自己的想法,好处是这可以潜在地节省彼此的时间: * 避免将过多时间花在那些 **肯定会被拒绝的** 事情上,因为它先前已经被讨论过了,但这些相关内容并不一定能在互联网上找到。 所以建议首先向 MegEngine 社区询问你的某个想法是否为原创,这将有所帮助。 * 一个想法可能对作者来说听起来不错,但这并不意味着它适用于大多数使用 MegEngine 的用户和开发者。 你需要确保该想法适用于整个 MegEngine 社区,造福群众,而不仅仅是一家之言。 一旦作者打算向 MegEngine 社区询问某个想法是否有机会被接受,就可以开始着手准备一份 MEP 草案。 作者能借写作去梳理、拓展和反思自己的想法,也能确保投入足够的时间使得 MEP 的格式正确、初始内容质量较高。 .. warning:: MEP 作者有责任在提交 MEP 以供审查之前收集社区对 MEP 的反馈。 如何提交 MEP ~~~~~~~~~~~~ 确定需要提交一份 MEP 草案后,后续的流程会根据 MEP 的作者是否属于 MegEngine 核心开发者而有所不同。 .. note:: * 如果 MEP 的作者本人并不属于 MegEngine 核心开发者,则需要为自己的想法寻找一位担保人。 理想情况下,需要确认一名核心开发者作为 MEP 担保人,但也可以在委员会的批准下选择非核心开发者作为担保人。 担保人的职责是为 MEP 作者提供后续指导,帮助他/她(们)完成 MEP 流程的后勤工作(有点类似于导师),担保人可作为 MEP 的合作者。 每个 MEP 的担保人信息(如果有)应该记录在 MEP 文件头部的 “:担保人:” 字段。 * 如果 MEP 的作者本人即 MegEngine 的核心开发者,则无需寻找担保人。 一旦作者认为 MEP 已经准备好提交,则应该通过 GitHub Pull Request 将提案作为 MEP 草案提交。 草案必须按如下所述以 MEP 风格编写,否则将立即无法通过审核(这个过程中编辑可能会更正一些存在的小错误)。 标准的 MEP 草案提交流程是: #. 作为 MEP 的作者,分叉(Fork) `Documentation 存储库`_, 在 ``source/development/meps/`` 目录中创建一个名为 ``mep-9999.rst`` 的文件, 其中包含你的新 MEP, 并使用 "9999" 作为草案的编号; #. 在 “:类型:” 字段中,根据实际情况填入 “标准追踪”、“信息” 或 “流程”,并在 “:状态:” 字段中填入 “草稿”。 有关的完整信息,请参考 :ref:`mep-header-preamble` #. 推送(Push)到你的 GitHub 分叉并提交一个拉取请求(Pull Request). #. MEP 编辑会审查你的 PR 结构、格式和其它类型的错误。我们要求统一提供 reST 格式的 MEP, 参考 :ref:`restructuredtext` 。 批准 MEP 的标准是: * 听起来很完整,想法必须具有技术意义,但编辑并不考虑它是否有可能被接受。 * 标题准确精炼地描述了内容。 * MEP 的语言(拼写、语法、句子结构等)和代码风格应该正确且一致。 如果 MEP 尚未准备好接受批准,编辑会将其发回给作者进行修订,并附有具体说明。 #. 一旦获得批准,编辑将为你的 MEP 分配一个编号。 .. note:: 一旦审核过程结束且被 MEP 的编辑批准(批准并不意味你的 MEP 已经被接受),所有你的 Pull Request 中的提交将被合并且推送到主分支。 这意味着任何人都可以从 MegEngine 文档中看到你的 MEP 草案,并可以在其它地方的讨论中引用对应的 MEP 编号。 编辑不会无理拒绝 MEP 草案的发布。拒绝 MEP 的通常原因包括重复工作、技术上不健全、没有提供适当的动机或解决向后兼容性问题, 或者不符合 MegEngine 设计理念。在这个阶段也可以选择咨询发展改革委员会,委员会是相关内容是否能作为 MEP 草案发布的最终仲裁者。 .. warning:: MEP 草案被编辑批准并不保证里面没有令人尴尬的错误,正确性是作者和审稿人的责任。 .. warning:: 具有 Documentation 库 ``git push`` 权限的开发人员可以通过创建和提交新的 MEP 并直接声明 MEP 编号, 如果执行上述操作,则执行人必须自己处理通常由 MEP 编辑处理的任务以确保初始版本符合提交 MEP 的预期标准。 我们更加推荐一切按部就班,即开发人员也应该通过 Pull Request 拉取请求来提交 MEP 内容。 但针对新版本中的适应性更改,如果 MEP 作者(或合作开发人员)具有 ``git push`` 权限,则可以直接对旧的 MEP 进行更新。 MEP 流程状态 ~~~~~~~~~~~~ 作者完成 MEP 后,他/她(们)可能会要求 MEP 编辑对风格和一致性进行审查,但最终的草案必须向核心开发者请求内容审查。 为了在特定的情况下加快流程(例如某个 MEP 的更改显然对 MegEngine 有益并准备好被接受,但尚未正式提交审查时), 发展改革委员会也可以启动 MEP 审查,决定接受或拒绝,但需要事先通知 MEP 作者并让他/她(们)有机会进行完善和修改。 接受(或拒绝) MEP 的最终权力机构是委员会。但每当新的 MEP 出现时,任何认为自己有适当经验、 能够对该 MEP 做出最终决定的核心开发人员也可以提议担任该 MEP 的决策人,然后他/她(们)将有权接受(或拒绝)该 MEP. 承担此责任的个人可以随时向委员会寻求更多指导,并且还应考虑其他核心开发人员的建议和观点。 草稿(Draft)状态的 MEP 草案提交后,MEP 状态可能的路径如下: .. image:: ../../_static/images/meps/mep-0001-process_flow.png :alt: MEP process flow diagram :align: center 如果没有志愿者挺身而出成为决策人,那么委员会将与具有相关专业知识的核心开发者接触,以尝试确定愿意担任该 MEP 决策的候选人。 如果找不到合适的候选人,那么 MEP 将被标记为推迟(Deferred)直到有人愿意开始进行相关决策。 已被任命的 MEP 决策人可以选择下台,或被委员会要求下台。在这种情况下,将按照与新 MEP 相同的方式任命新的 MEP 决策人。 如果 MEP 决策人被要求下台,这将推翻之前对 MEP 的任何接受或拒绝决定,并将恢复到草案状态。 要使 MEP 被接受(Accepted),它必须满足某些最低标准: * 它必须包含对增强特性的清晰完整的描述。 * 增强必须意味着改进,而不是一些平凡的变化。 * 实现方案必须是可靠的,阐明清楚了其基本原理和设计规格。 * 最后,提案中的增强特性必须符合 MegEngine 的设计哲学。 .. admonition:: 接受(Accpeted)& 完成(Final) :class: note 一旦标准追踪类型但 MEP 被标记为接受,表明该特性是 MegEngine 所需要的, 则可以考虑进入 :ref:`Git 协作流程 ` 开始进行实现。 当参考实现完成,通过代码审查(Code Review)并合并到 MegEngine 源代码存储库中时,MEP 状态将更改为“完成”(Final)。 * 一个 MEP 也有可能长期处于已被接受的状态,这通常是由于优先级不够高,或者核心开发人员者没有时间和精力去实现它们。 * 已被接受的 MEP 允许存在来自不同开发者的多个竞争实现,但最终只会采纳其中一个作为最终实现。 其它没有被采纳的实现也会在 MEP 中被记录,用作后续可能的追踪。 .. admonition:: 生效(Active) :class: note 对于信息类和流程追踪类的 MEP, 其最终归宿应当是“生效”(Active)。 .. admonition:: 临时(Provisonal) :class: note 为了在承诺 API 的长期稳定性之前收集额外的反馈信息,MEP 也可以标记为“临时”(Provisnal),代表“Provisionally Accepted”, 表示该提案已被接受以包含在参考实现中,但需要额外的用户反馈才能将设计视为完成状态。 在可能的情况下,最好缩小提案的范围以避免出现“临时”状态。 与常规接受的 MEP 不同,即使在某个 MegEngine 版本中合并对应改动之后,临时接受的 MEP 仍可能被拒绝或撤回。 .. admonition:: 延期(Deferred) :class: note 当 MEP 没有取得任何进展时,MEP 作者或编辑可以为其分配“延期”(Deferred)状态。 一旦 MEP 被延期,MEP 编辑可以将其重新分配为草稿状态,等待作者进行后续的补充。 .. admonition:: 拒绝(Rejected) :class: note MEP 也可以被“拒绝”(Rejected),即最终不被接受。 .. admonition:: 撤回(Withdawn) :class: note “撤回”(Withdawn)意味着作者自己已经认为曾经提出的 MEP 实际上是一个坏主意, 或者已经认同了某个竞争提案是更好的选择。 .. warning:: 当 MEP 完成、拒绝或撤回时,需要进行相应的更新。除了更新状态字段之外, 至少应该添加与最终解决方案有关的链接(一个新的 MEP, 或者一个合并的 Pull Request)。 .. warning:: MEP 也可以被不同的 MEP 取代,从而使原始版本过时。 MEP 维护 ~~~~~~~~ 通常,标准追踪 MEP 在达到完成状态后不再修改。一旦 MEP 完成,将成为正式的文档内容。 如果根据实践经验和用户反馈,对处于已接受或临时状态的标准追踪 MEP 进行更改, 则应在 MEP 中注明这些更改,以便 MEP 能够准确描述最终的实现。 信息和流程类型的 MEP 可能会随着时间的推移而更新,以反映开发实践和其他细节的变化。 .. _success-mep-template: MEP 参考模版 ------------ 如果一个标准追踪 MEP 达到了完成状态,其结构与下面提供的模版应当高度相似。 **头部内容** 包含有关 MEP 的元数据,具体细节请参考 :ref:`mep-header-preamble` 。 **简介** 是什么(What)。简短地描述当前 MEP 正在解决的技术问题。 **动机** 为什么(Why)。清楚地解释为什么现有的实现不足以解决问题。 **基本原理** 如何处理(How)。简单介绍解决技术问题的思路、原理和方法。 **设计规范** 即 Specification. 这在 MEP 的初始流程中是最重要的一部分,是对解决方案的最简展示。 通常需要介绍打算引入什么样的接口,执行逻辑如何,可以使用伪代码和图片来作为补充说明。 好的设计规范应该能保证:具有相似编程经验和背景的人能够参照着该规范进行具体的实现。 MEP 决策人可以通过设计规范判断出该提案是否可行,以及是否可被接受。 需要注意的是,设计规范不需要也不应该涉及到代码实现的细节。 **向后兼容性** 所有引入向后不兼容的 MEP 都必须描述这些不兼容部分及其严重性。 解释作者打算如何处理这些不兼容性。没有足够的向后兼容性论文的 MEP 提交可能会被彻底拒绝。 **安全影响** 如果存在与安全相关的问题,则应明确写出,以确保决策者了解这些问题。 **示例** 对于添加新功能或改变旧接口行为的 MEP,提供关于如何教新的和有经验的用户进行使用的说明。 通常这一部分可以被用来作为单元测试的参考,也可以被用于教程或用户指南。 **参考实现** 这一部分不需要事先提供,直到 MEP 变为接受状态。 但必须提供一个被 MegEngine 代码库合并的拉取请求或提交记录作为参考实现,MEP 才能被标记为“完成”状态。 如果存在着多个竞争实现,除了被合并的实现外,其它的实现也应该被列举在此处。 **被拒绝的想法** 在 MEP 的整个讨论中,将提出各种未被接受的想法。那些被拒绝的想法应该与拒绝的原因一起记录下来。 这既有助于记录 MEP 在完成之前背后的思考过程,也有助于防止人们在后续讨论中再次提出相同的被拒绝的想法。 **未解决的问题** 当 MEP 处于草案中时,可能会出现一些值得进一步讨论的想法。 应该记录这些想法,以便人们知道他/她(们)正在考虑但没有具体的解决方案。 **致谢** 如果任何人或机构对 MEP 的讨论和实现提供了实质性的帮助,需要表达感谢。 **版权/许可** 每个新的 MEP 都必须置于公共领域和 CC0-1.0-Universal 的双重许可之下。 每个 MEP 都需要在这里提供一个指向源文件的链接。 .. _mep-header-preamble: MEP 头部内容 ------------ 必须按以下顺序出现,标有 ``*`` 的标题是可选的,所有其他标题都是必需的。 .. code-block:: :编号: :标题: :作者: <包含作者真实姓名的列表,邮件地址可选> * :担保人: <担保人的真实姓名> * :决策人: <决策人的正式姓名> :状态: <草稿 | 生效 | 接受 | 临时 | 推迟 | 拒绝 | 撤回 | 完成 | 已被取代> :类型: <标准追踪 | 信息 | 流程> * :需求: :创建时间: * :更新历史: * :已经代替: * :已被代替: * :实现版本: <版本编号> .. note:: * 如果有多位作者,则每个作者都应该一并写在单行中。 * 个人电子邮件地址将被隐藏,以防止垃圾邮件收集器。 * 担保人记录由谁(核心开发者或委员会指派)发起当前 MEP 流程,如果 MEP 作者之一是核心开发者,则不需要此字段。 * 决策人记录由谁(通常由委员会指派)对最终接受或拒绝 MEP 做出决定。 * MEP 可能有一个“需求”标头,指示此 MEP 所依赖的 MEP 编号。 * MEP 也可能有一个“已被代替”标头,表明此 MEP 已经被后续文档废弃,并填写代替当前文档的 MEP 编号。 * 对应地,比较新的 MEP 必须有一个“已经代替”标头,包含已经过时的 MEP 编号。 * 标准追踪 MEP 通常会有一个“实现版本”标头,表示开始支持该特性的 MegEngine 版本。 报告错误或提交更新 ------------------ 请使用 GitHub Issues 或 Pull Request 进行讨论和维护(带有 ``MEPs`` 标签)确保信息不会丢失。 对 MEP 存储库具有 git push 权限的作者可以通过使用 ``git push`` 或 GitHub PR 接口提交他/她(们)的更改来进行更新。 转让 MEP 所有权 --------------- 偶尔需要将 MEP 的所有权转让给新的负责人。一般来说,最好保留原作者作为转移后的 MEP 的共同作者,但这实际上取决于原作者。 转让所有权的一个很好的理由是,原作者不再有时间或兴趣更新或遵循 MEP 流程,或者已经脱离了“网络”(即无法访问或不回复电子邮件)。 转让所有权的一个差劲的理由是因为作者不同意 MEP 的后续方向。 MEP 流程的一个目标是尝试围绕 MEP 达成共识,如果难以实现,作者始终可以提交竞争性 MEP. 如果你有兴趣获得 MEP 的所有权,也可以通过拉取请求来实现。Fork 存储库,进行所有权修改,并提交拉取请求。 你应该在对拉取请求的评论中同时提及原作者和 @megvii-mge (如果不知道原作者的 GitHub 用户名,请使用电子邮件)。 如果原作者没有及时回复,MEP 编辑将做出单方面的决定(这种决定也能被撤销)。 MEP 编辑职责和工作流程 ---------------------- 对于编辑器中的每个新 MEP, 请执行以下操作: * 确保 MEP 由核心开发者共同撰写,且由核心开发人员或委员会专门为此 MEP 批准的人员作为担保人。 * 阅读 MEP 以检查它是否准备就绪:健全且完整。这些想法必须具有技术意义,即使不太可能被接受。 * 标题应准确描述内容。 * 文件扩展名正确(即 ``.rst`` )。 * 略读 MEP 中语言(拼写、语法、句子结构等)和代码风格的明显缺陷,可以帮助纠正。 如果 MEP 尚未准备好,编辑会将其发回给作者进行修订,并附有具体说明。 如果 reST 格式有问题,请让作者根据 :ref:`restructuredtext` 中的规定修改并重新提交。 一旦 MEP 准备好用于存储库,MEP 编辑将: * 分配一个 MEP 号码(几乎总是下一个可用号码)。 * 检查作者是否正确标记了 MEP 的类型(“标准追踪”、“信息”或“流程”),并将其状态标记为“草稿”。 * 将 MEP 添加到 Documetation 存储库的源分支,确保路径正确。 * 提交并推送全新的(或更新的)MEP. 对现有 MEP 的更新应作为 GitHub 拉取请求进行提交。 许多 MEP 是由对 MegEngine 代码库具有写入权限的开发人员编写和维护的。 MEP 编辑监视 MEP 内容的更改,并更正他/她(们)看到的任何结构、语法、拼写或标记错误。 他/她(们)不会对 MEP 的正确性做出判断,通常负责 MEP 的运营和内容编辑部分。 .. _PEP 1: https://www.python.org/dev/peps/pep-0001/ .. _MEP 修订历史: https://github.com/MegEngine/Documentation/commits/main/source/development/meps .. _Documentation 存储库: https://github.com/MegEngine/Documentation