区块链开发框架后端【免费下载链接】substrateSubstrate: The platform for blockchain innovators项目地址https://gitcode.com/gh_mirrors/su/substrate点击查看免费下载本文基于 Substrate 仓库中的 文档指南系统讲解 Substrate/FRAME 项目中该写什么文档、怎么写文档的完整规范从外部 API crate 的 rustdoc 编写原则、///与//的区分、intra-doc 链接与 proc-macro 的坑到 Pallet crate 的lib.rs模板、dispatchable、存储项、错误与事件文档模板。读完并对照仓库中的范例 pallet-fast-unstake 后你能够为 Substrate/FRAME 代码库贡献出符合 house style、可被 CONTRIBUTING 规则 与docs-auditCode Owner 审查通过的文档。适用范围哪些 crate 需要重点写文档该指南开篇即明确了边界它只聚焦于 Substrate 中与其外部 API 相关的 crate。这类 crate 的清单由 CODEOWNERS 给出——搜索其中被自动指派给名为docs-audit的团队paritytech/docs-audit的条目即可。从当前仓库的 CODEOWNERS 实际内容看纳入docs-audit范围的包括docs/CODEOWNERS#L38-L46/primitives/runtime、/primitives/arithmetic第 39-40 行primitives/core、primitives/io标注为后续加入整个/frame/目录第 45 行同时指派给paritytech/frame-coders/frame/nfts/、/frame/uniques/、/frame/contracts/以及 NPoS/staking 系列election-provider-multi-phase、election-provider-support、elections-phragmen、nomination-pools、staking、primitives/npos-elections。这些 crate 的共性是它们被外部开发者高频使用因此需要更充分的文档尤其是最关注 FRAME 开发的 crate。指南同时说明本文所有通用规则对 pallet crate 与非 pallet crate 均适用pallet 部分只是在其之上的增量约束。这套规范并非孤立存在docs/CONTRIBUTING.md 的第 6 条贡献规则明确要求贡献者遵循house documenting style即本指南docs/README.adoc 中也有一节关于文档注释的传统说明///注释、//!模块注释、Panics/Errors/Safety/Examples特殊章节、documentation as tests 等见 docs/README.adoc#L480-L508与本指南互为印证。非 Pallet crate写什么对docs-audit覆盖范围内的所有非 pallet crate判断该写什么使用如下过滤器原文逐条位于 CODEOWNERS 中指派给docs-audit的 crate 内所有pub项必须写文档。非pub的项不会出现在 rust-docs 中不属于对外接口。有些项pub只是为了被另一个内部 crate 使用且可以预见不会被其他任何人使用——这些不要求写得很充分是否补全由作者自行判断。提醒只要 trait 本身是 public 的其内部所有trait项按定义就是 public 的同样需要文档。所有公开模块mod都应有合理的模块级文档//!。///与//的本质区别Rust Docs vs. Code Comments指南特别强调不要混淆两类注释以///开头的是对外 rust-doc以//开头的内容不会出现在 rust-docs 中。原文给出的示范代码/// Computes the square root of the input, returning Ok(_) if successful. /// /// # Errors /// ... /// // Details about the complexity, how you implemented this, and some quirks that // are NOT relevant to the external interface, so it starts with //. // This can also be moved inside the function. pub fn sqrt(x: u32) - Resultu32, () { todo!(); }即面向外部接口的行为描述用///复杂度、内部实现方式、与外部接口无关的怪癖用//并且可以挪进函数体内部。这条规则在 Pallet 部分会被再次用到存储项的 hasher 选择必须用//写。非 Pallet crate怎么写指南推荐的资料来源是官方 rustdoc 写作指南doc.rust-lang.org 的 how-to-write-documentation、Rust Book 第一版的 documentation 章节以及 Guillaume Gomez 的 rustdoc 写作经验博客原文链接见 docs/DOCUMENTATION_GUIDELINES.md。其核心要求归纳如下首句摘要规则任何被文档项的开头必须是一句话说明该条目是什么其余内容放在一个空行之后。原因是rustdoc 显示在模块内所有函数列表等表格中时使用的摘录excerpt正是第一个换行之前的全部文本。首段过长会让模块文档表格极难阅读因此首句务必短小精炼。特殊章节Special Sectionsrustdoc 支持# Panics、# Safety、# Errors、# Examples等特殊章节。指南指出在 runtime 相关代码中基本不需要考虑 panic 与 safety——我们的代码从不unsafe几乎从不 panic因此重点是# Examples与可选的# Errors。尽可能使用# Examples# Examples是演示 API 行为的最佳方式还附带免费测试覆盖。额外收益rust-doc 中的任何代码块会被当作集成测试integration test而非单元测试来执行用不同于单元测试的方式测试你的 crate。因此它既是文档更多的胜利也是测试覆盖更多的胜利。可选的# Errors章节仅在返回Result且Error变体过于复杂时才需要。Intra-doc 链接尽可能把文档中对其他项的引用写成正确链接避免some_func这种纯代码引用改用[some_func]这种 intra-rustdoc 链接语法细节参见官方 rustdoc 的 Linking to items by name 文档与 RFC 1946。一个设计层面的警告原文以脚注形式说明当你发现自己为了讲清某个 API 而需要链接过多外部项时这更像 API 设计问题而非文档问题——说明该 API 本身可能设计得不太对。例如 frame/support 中的大多数胶水 traitfootnote帮助两个 pallet 互相通信的 trait在设计时就不应做关于特定实现 pallet 的强假设文档同样不应如此。TLDR 清单指南给出的五条可机械执行的规则原文编号 0-4在心理上以#![deny(missing_docs)]为目标即便编译器没有强制它 。从一个清晰、简洁的单句开始如有需要空行之后再展开更多上下文。在合理范围内尽量使用示例。尽量使用链接。思考上下文如果你在文档化一个本不应显式依赖某些主题的 trait 时却在大量解释这些外部主题说明你的设计大概率有问题。关于第 0 条可以在仓库中得到印证当前仓库并未全局强制该 lint但已有部分 crate 自行开启了它例如 frame/glutton/src/lib.rs 与 frame/nicks/src/lib.rs 均在文件顶部使用#![deny(missing_docs)]——这正是指南鼓励的心理默认值在部分代码中落地为编译器强制的形态。Proc-Macro 的特殊考量文档化 proc macro 时有额外注意点doc 链接在 proc macro crate内部看似正常但这些 macro 被 re-export 到项目其他位置后链接往往失效例外指向其他 proc macro的链接只要它们同样被 re-export就能正常工作常常需要在同名 proc macro 与函数之间消歧义可用macromy_macro_name语法的链接来解决。其他准则以代码为文档、格式即表达指南在五条核心规则之外补充了两条不一定在所有情况下成立、但值得遵守的注记。Document Through Code用代码本身做文档代码应命名得当、组织良好使其本身成为文档的一种形式但在 Polkadot/Substrate 项目的复杂度下这还不够——示例、错误与 panic 无法仅靠命名良好的代码来传达。原文的北极星north star是自我说明self-documenting的代码同时恰好又有良好的文档并布满示例。书面文档应当补充代码而不是复述代码。反例/// Sends request and handles the response. trait SendRequestAndHandleResponse { }这里的文档没有提供任何命名良好的 trait 之外的增量信息纯属冗余。Formatting Matters格式很重要指南用同一组事实的两种写法做对比。糟糕的写法——一坨无结构的流水账/// This function works with input u32 x and multiplies it by two. If /// we optimize the other variant of it, we would be able to achieve more /// efficiency but I have to think about it. Probably can panic if the input /// overflows u32. fn multiply_by_2(x: u32) - u32 { .. }规范的写法——首句摘要 特殊章节 内部注释分离/// Multiplies an input of type [u32] by two. /// /// # Panics /// /// Panics if the input overflows. /// /// # Complexity /// /// Is implemented using some algorithm that yields complexity of O(1). // More efficiency can be achieved if we improve this via such and such. fn multiply_by_2(x: u32) - u32 { .. }两者传达的事实大致相同但后者因为格式整洁而更容易跟随。对可以预见会被大量查看与使用的 trait 和类型尤其要写整洁版本。行宽硬约束注释必须按 100 字符折行由仓库根目录的 rustfmt.toml 定义不能多也不能少。多的部分由rustfmt与 CI 强制但如果你出于某种原因折在 59 字符CI 会照样通过而观感很差。rustfmt.toml#L11-L12 中comment_width 100与wrap_comments true正是这一约束的落地配置。指南还建议使用 VS Code 的 rewrap 插件之类的工具来正确折行。Pallet cratelib.rs顶层文档模板上述通用规则同时适用于 pallet 与非 pallet crate。对crate 本身就是一个 pallet的部分指南以 pallet-fast-unstake 为遵循本指南的范例并给出lib.rs顶层文档模板原文完整模板如下//! # Pallet Name //! //! single-liner about the pallet. //! //! ## Overview //! //! should be high-level details that are relevant to the most broad audience //! //! The audience here is potentially non-coders who just want to know what this pallet does, not how it does it //! //! potentially a few paragraphs, focus on what external folks should know about the pallet //! //! ### Example //! //! Your pallet must have a few tests that cover important user journeys. Use https://crates.io/crates/docify to reuse these as examples. //! //! ## Pallet API //! //! Reminder: inside the [pallet] module, a template that leads the reader to the relevant items is auto-generated. There is no need to repeat things like See Config trait for ..., which are generated inside [pallet] here anyways. You can use the below line as-is: //! //! See the [pallet] module for more information about the interfaces this pallet exposes, including its configuration trait, dispatchables, storage items, events and errors. //! //! The audience of this is those who want to know how this pallet works, to the extent of being able to build something on top of it, like a DApp or another pallet //! //! This section can most often be left as-is. //! //! ## Low Level / Implementation Details //! //! The format of this section is up to you, but we suggest the Design-oriented approach that follows //! //! The audience of this would be your future self, or anyone who wants to gain a deep understanding of how the pallet works so that they can eventually propose optimizations to it //! //! ### Design Goals (optional) //! //! Describe your goals with the pallet design. //! //! ### Design (optional) //! //! Describe how youve reached those goals. This should describe the storage layout of your pallet and what was your approach in designing it that way. //! //! ### Terminology (optional) //! //! Optionally, explain any non-obvious terminology here. You can link to it if you want to use the terminology further up模板中 H3 及以下的细节留给了开发者自由裁量例如可放可不放### Terminology或将其并入## Overview。但从最高层解释到最底层解释的递进流向必须遵守经验法则是模板中的 H2##可视为严格规则H3###及以下灵活。各节的受众定位模板内注释的要点## Overview面向可能不懂代码、只想知道 pallet 做什么的人## Pallet API一节通常原样保留即可——因为[pallet]模块内部会自动生成引导读者找到 Config/dispatchables/storage/events/errors 的模板不必重复See Config trait for ...之类的话## Low Level / Implementation Details面向未来的你自己或想要深入理解并可能提出优化的读者。fast-unstake模板在仓库中的落地对照pallet-fast-unstake 的模块级文档frame/fast-unstake/src/lib.rs#L26-L111几乎逐行对应该模板# Fast Unstake Pallet标题后紧跟单句摘要A pallet to allow participants of the staking system ... to unstake quicker...## Overview用数段面向大众的白话解释了未暴露not exposed的名额持有者可以更快 unbond这一机制并引用了 [StakingInterface::is_exposed_in_era]、[Config::Deposit] 等 intra-doc 链接### Example一节用docify把 tests.rs 中两条关键用户旅程测试直接嵌入文档#![doc docify::embed!(src/tests.rs, successful_multi_queue)]与exposed_nominator_cannot_unstakeframe/fast-unstake/src/lib.rs#L71-L77。docify作为 dev-dependency 声明在该 crate 的 Cargo.tomldocify 0.2.1这正是模板中用 docify 把测试复用为文档示例的做法## Pallet API一字不差地使用模板给定的那句话See the [pallet] module for more information about the interfaces this pallet exposes, including its configuration trait, dispatchables, storage items, events and errors.frame/fast-unstake/src/lib.rs#L79-L82## Low Level / Implementation Details以设计取向解释on_idle队列实现、权重测量必须正确的原因、[ErasToCheckPerBlock] 取值过大的后果、以及出错时 pallet 通过InternalError事件自我熔断的行为——受众正是模板定义的未来的你自己。可选的 Polkadot/Substrate 徽标头指南还给出一个可选的开场用于展示 Polkadot 与 Substrate 的关系在 fast-unstake 中同样原样出现见 frame/fast-unstake/src/lib.rs#L18-L24//! Made with *Substrate*, for *Polkadot*. //! //! [![github]](https://github.com/paritytech/substrate/frame/fast-unstake) - //! [![polkadot]](https://polkadot.network) //! //! [polkadot]: https://img.shields.io/badge/polkadot-E6007A?stylefor-the-badgelogopolkadotlogoColorwhite //! [github]: https://img.shields.io/badge/github-8da0cb?stylefor-the-badgelabelColor555555logogithubPallet crateDispatchable 文档模板对每个 dispatchable#[pallet::call]内的fn使用如下模板原文完整保留/// One-liner explaining what the dispatchable does /// /// ## Dispatch Origin /// /// The dispatch origin of this call must be details (e.g. Root, Signed, Unsigned) /// /// ## Details /// /// All other details, namely any errors that could occur within this dispatch and the events this dispatch could emit /// /// ## Errors (optional) /// /// If an extensive list of errors can be returned, list them individually instead of mentioning them in the section above /// /// ## Events (optional) /// /// Events are akin to the return type of dispatchables, optionally mention them pub fn name_of_dispatchable(origin: OriginForT, ...) - DispatchResult {}关键意识这些文档会成为对应 dispatchable 的metadata的一部分可能被钱包与浏览器explorer直接展示给终端用户因此措辞要面向最终使用者而非仅面向开发者。仓库范例 register_fast_unstake 严格遵循该结构/// Register oneself for fast-unstake. /// /// ## Dispatch Origin /// /// The dispatch origin of this call must be *signed* by whoever is permitted to call /// unbond funds by the staking system. See [Config::Staking]. /// /// ## Details /// /// The stash associated with the origin must have no ongoing unlocking chunks. If /// successful, this will fully unbond and chill the stash. ... /// /// ## Events /// /// Some events from the staking and currency system might be emitted. #[pallet::call_index(0)] #[pallet::weight(T as Config::WeightInfo::register_fast_unstake())] pub fn register_fast_unstake(origin: OriginForT) - DispatchResult { ... }其中 Dispatch Origin 明确写出*signed*及权限来源链接到 [Config::Staking]Details 覆盖成功/失败两条路径对账户状态的影响——这正是模板要求的所有其他细节尤其是可能出现的错误与可能发出的事件。Pallet crate存储项文档要点对存储项指南给出三条hasher 选择必须用私有代码注释记录。如果使用了 map 类类型始终把 hasher 的选择原因以//注释写出例如// Hasher X chosen because ...。回扣前文这是对外部人员不相关的内部决策所以必须用//而非///。fast-unstake 的Queue存储项就是标准示范frame/fast-unstake/src/lib.rs#L218-L223/// The map of all accounts wishing to be unstaked. /// /// Keeps track of AccountId wishing to unstake and its corresponding deposit. // Hasher: Twox safe since AccountId is a secure hash. #[pallet::storage] pub type QueueT: Config CountedStorageMap_, Twox64Concat, T::AccountId, BalanceOfT;对外语义用///该 map 追踪想退出的账户及其押金hasher 安全性论证用//——两类注释的分工一目了然。考虑解释存储的加密经济学为使用存储而收取押金deposit的机制。fast-unstake 的Config::Deposit文档frame/fast-unstake/src/lib.rs#L182-L185即说明了为在失败退出时能 slash 它来覆盖资源成本而收取押金。若使用了#[pallet::unbounded]或#[pallet::without_storage_info]考虑解释为什么该存储项无界是安全的。Pallet crateErrors 与 Events 文档要点与 dispatchable 同理这些文档会成为对应 event/error 的 metadata 的一部分可能被钱包与浏览器使用。因此对error解释错误为什么发生以及可以采取什么措施避免它。fast-unstake 的Error枚举frame/fast-unstake/src/lib.rs#L255-L272逐变体给出原因例如NotController附带This means that the given account is not bonded.——不仅说明是什么还说明含义对event逐变体说明触发场景。fast-unstake 的Event枚举frame/fast-unstake/src/lib.rs#L237-L253中BatchFinished甚至补充了后续行为契约This is always follows by a number ofUnstakedorSlashedevents, marking the end of the batch.。总结一份可执行的检查清单综合原文档与仓库证据提交 Substrate/FRAME 文档前可以这样自检检查项依据crate 是否在 CODEOWNERS 的docs-audit范围内pub项与公开模块//!是否全部有文档文档什么要写一节CODEOWNERS L38-L46每个文档项首句是否为单句摘要后续内容是否隔空行展开How to Document? 节对外行为是否用///内部决策如 hasher 选择、复杂度说明是否用//Rust Docs vs. Code Comments 节Queue 存储项是否尽量提供# Examples可借docify复用测试返回复杂Result时是否补# ErrorsHow to Document? 节fast-unstake 示例交叉引用是否使用[intra-doc]链接proc macro 间是否注意 re-export 失效与macro消歧义Proc-Macros 节文档是否补充而非复述代码注释是否按 100 字符折行Formatting Matters 节rustfmt.tomlPallet 的lib.rs是否遵循# Name / ## Overview / ## Pallet API / ## Low Level递进模板## Pallet API是否使用规定句式模板节fast-unstake 全文对照dispatchable 是否按## Dispatch Origin / ## Details / ## Errors / ## Events模板书写并意识到会进入 metadataDispatchables 节register_fast_unstake存储项 hasher、押金经济学、unbounded 安全性是否分别用//、///、///说明Storage Items 节心理上是否按#![deny(missing_docs)]的标准要求自己部分 crate 如 glutton、nicks 已实际启用TLDR 第 0 条这套规范的整体取向可以用原文的北极星来收束写出自我说明的代码同时恰好又有良好文档并布满示例。它既约束 rustdoc 的形态首句、章节、链接、格式也借文档反向约束 API 设计本身——当文档被迫大量引用外部概念时问题往往出在设计而不是笔上。赞分享区块链开发框架后端【免费下载链接】substrateSubstrate: The platform for blockchain innovators项目地址https://gitcode.com/gh_mirrors/su/substrate点击查看免费下载相关推荐Agent Substrate 仓库 AGENTS.md 编写与维护实践面向 AI 代理的渐进式项目文档规范Agent Substrate 仓库 AGENTS.md 编写与维护实践面向 AI 代理的渐进式项目文档规范 本文讲解 Agent Substrate 仓库内人工智能AI AgentAgent 沙箱云原生容器运行时零信任UFold常见问题解答从安装到预测的15个关键问题解决指南UFold常见问题解答从安装到预测的15个关键问题解决指南 UFold是一款基于深度学习的RNA二级结构预测工具通过类图像序列表示和U Net架构实现快速准Ghost-Downloader-3文档规范API文档编写Ghost Downloader 3文档规范API文档编写 还在为API文档编写而头疼吗本文为你提供Ghost Downloader 3项目的API文档编写桌面应用网络上一篇Bevy游戏存档系统终极指南轻松实现进度保存与加载下一篇PyPTO SIMD API 编程指南Tile 数据搬运、向量计算与 Cube 矩阵乘全景解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
