文档指南
本指南讨论了 Ruby 核心和 Ruby 标准库中类、模块和方法的文档编写建议。
生成文档
大多数 Ruby 文档都位于源文件中,并使用 RDoc 格式编写。
某些页面位于 doc 文件夹下,可以是 .rdoc 或 .md 格式,具体取决于文件扩展名。
要在生成目录中的 {build folder}/.ext/html 目录下生成 HTML 文档更改的输出,请在你的生成目录中运行以下命令:
make html
如果你还没有生成目录,请按照 快速入门指南的第 4 步操作。
然后,你可以通过在浏览器中打开 {build folder}/.ext/html/index.html 文件来预览你的更改。
目标
Ruby 文档的目标是在最短的时间内传达最重要和最相关的信息。读者应该能够快速理解目标代码的有用性以及如何使用它。
提供信息太少不好,但提供不重要信息或不必要的示例也不好。请根据用户的需求自行判断。
一般指南
-
请记住,读者可能不精通英语。
-
写简短的陈述句或祈使句。
-
将句子分组到(最好是短的)段落中,每段涵盖一个主题。
-
使用 标题来组织材料。
-
使用 链接引用权威和相关的来源。
-
使用简单的动词时态:一般现在时、一般过去时、一般将来时。
-
使用简单的句子结构,而不是复合句或复杂句。
-
避免
字符
在 C 源文件中只能使用与 US-ASCII 兼容的字符。(如果你使用其他字符,Ruby CI 会友好地提醒你。)
如果你想在 C 语言编写的类、模块或方法的文档中包含 ASCII 不兼容的字符,可以通过新建文件 doc/*.rdoc 来实现。
-
对于类
Foo(定义在文件foo.c中),请创建文件doc/foo.rdoc,声明class Foo; end,并将类文档放在该声明的上方。# Documentation for class Foo goes here. class Foo; end
-
同样,对于模块
Bar(定义在文件bar.c中),请创建文件doc/bar.rdoc,声明module Bar; end,并将模块文档放在该声明的上方。# Documentation for module Bar goes here. module Bar; end
-
对于方法,情况有所不同。像上面那样为方法添加文档会禁用已渲染文档中的“点击切换源代码”功能。
因此,最好使用文件包含功能。
-
保留 C 代码中的
call-seq。 -
使用文件包含(
:include:)来包含 .rdoc 文件中的文本。
示例
/* * call-seq: * each_byte {|byte| ... } -> self * each_byte -> enumerator * * :include: doc/string/each_byte.rdoc * */ -
RDoc
Ruby 使用 RDoc 进行文档编写。有关 RDoc 语法和功能的信息,请参阅 RDoc 标记参考。
irb 的输出
对于代码示例,可以考虑使用交互式 Ruby irb。
对于包含 irb 输出的代码示例,可以考虑在连续的行上对齐 # => ...。对齐有时可以提高可读性。
a = [1, 2, 3] #=> [1, 2, 3] a.shuffle! #=> [2, 3, 1] a #=> [2, 3, 1]
标题
使用 标题来组织类或模块的长篇讨论。
不要在方法或常量的文档中使用正式的标题。
在极少数情况下,当方法或常量文档中需要类似标题的结构时,请使用 粗体文本 作为伪标题。
空行
空行开始新段落。
代码块或列表应以空行开头和结尾。这对于 HTML 输出不是必需的,但有助于 ri 输出。
方法名称
文本中的方法名称
-
对于当前类或模块中的方法,对于单例方法使用双冒号,对于实例方法使用井号:
::bar, baz。 -
否则,包含类或模块名称,并为单例方法使用点,为实例方法使用井号:
Foo.bar,Foo#baz。
嵌入的代码和命令
嵌入在运行文本中的代码或命令(即,不在代码块中)应标记为 等宽字体。
作为简单字符串的代码应包含引号。
自动链接
大多数情况下,类、模块或方法的名称会自动链接。
- Float. - Enumerable. - File.new - File#read.
渲染为
通常,不应禁用 RDoc 的自动链接。例如,我们应该只写普通 *Float*(它会自动链接)。
Returns a Float.
渲染为
返回一个
Float。
但是,当所讨论的词语不指向 Ruby 实体时(例如,某些 *Class* 或 *English* 的用法),请 *禁用* 自动链接。
Class variables can be tricky.
渲染为
类变量可能棘手。
同样,当所讨论的词语指向当前文档时(例如,类 Float 文档中的 *Float*),请 *禁用* 自动链接。
在这种情况下,您可以考虑强制将名称设置为 等宽字体,这会禁用自动链接,并强调该词是一个类名。
A +Float+ object represents ....
渲染为
一个
Float对象表示……
对于一些*非常*频繁讨论的类,您可能考虑完全避免使用大写的类名。例如,对于某些提及数组的地方,您可以只写小写的 *array*。
而不是
For an empty Array, ....
渲染为
对于一个空的
Array,……。
你可能会写
For an empty array, ....
渲染为
对于一个空的数组,……。
这种更随意的用法避免了自动链接和分散注意力的字体变化,并且不太可能引起混淆。
这个原则可以特别有效地应用于:
-
一个数组。
-
一个整数。
-
一个哈希。
-
一个字符串。
但是,这应该*只*用于引用类的*实例*,*绝不*用于引用类本身。
显式链接
编写显式链接时,请遵循以下指南。
rdoc-ref 方案
使用 rdoc-ref 方案用于:
-
核心文档中链接到其他核心文档。
-
核心文档中链接到标准库包中的文档。
-
标准库包中链接到该标准库包中其他文档。
请参阅 [links] 部分的“rdoc-ref 方案”。
基于 URL 的链接
使用完整的基于 URL 的链接用于:
-
标准库文档中链接到核心文档。
-
标准库文档中链接到不同标准库包中的文档。
这样做可以确保即使包文档独立构建(与核心文档分开)时,链接也有效。
链接应指向 docs.ruby-lang.org/en/master/ 中的目标。
对于链接到站外文档,也使用完整的基于 URL 的链接。
变量名
变量名(在 call-seq 中指定)应标记为 等宽字体。
此外,对于临时变量(即,仅在讨论中定义和使用的变量,例如 n),也使用等宽字体文本。
HTML 标签
总的来说,避免使用 HTML 标签(即使在允许使用的格式中),因为 ri(Ruby 交互式参考工具)可能无法正确渲染它们。
表格
特别是,避免使用 HTML 标签(<table> 等)构建表格。
替代方案
-
(仅限 Markdown 格式):使用特殊格式化文本的 Github Flavored Markdown (GFM) 表格。
示例中的语言
文档示例中的符号和字符串
-
英文文档中优先使用英文:
'Hello'。 -
日文文档中优先使用日文:
'こんにちは'。 -
如果需要第二种语言(例如,不同字节大小的字符),英文文档中优先使用日文,日文文档中优先使用英文。
-
仅在必要时使用其他语言示例:请参阅
String#capitalize。
文档化类和模块
类或模块文档的一般结构应为:
-
摘要
-
常见用法,附带示例
-
“包含内容”摘要(可选)
摘要
摘要是对类或模块功能的简短描述,以及读者可能为何要使用它的原因。在摘要中避免细节。
常见用法
展示类或模块的常见用法。根据类或模块的不同,本节的长度和复杂程度可能大不相同。
包含内容摘要
类或模块的文档可能包含“包含内容”部分。
指南
-
部分标题为
What's Here。 -
考虑列出父类和任何包含的模块;如果存在,请考虑[链接]到它们的“包含内容”部分。
-
左侧内容列表中的所有方法都应列出(包括从另一个类扩展的任何方法)。
-
属性(不包含在目录中)也可以列出。
-
将方法显示为一个或多个项目符号列表。
-
每个项目都以方法名称开头,后跟一个冒号和一个简短描述。
-
如果方法有别名,请在冒号前以括号形式提及(不要单独列出别名)。
-
检查渲染的文档,以确定 RDoc 是否已识别方法并链接到它;如果没有,请手动插入一个 链接。
-
-
如果条目很多,请考虑将它们分组到带有标题的子部分中。
-
如果存在许多此类子部分,请考虑在主节标题下方添加一个目录。
文档化方法
通用结构
方法文档的一般结构应为:
-
调用序列(针对 C 语言编写的方法)。
-
摘要(简短描述)。
-
简要示例(可选)
-
详细信息和示例。
-
参数描述(如果需要)。
-
边界情况和异常。
-
相关方法(可选)。
调用序列(针对 C 语言编写的方法)
对于 Ruby 语言编写的方法,RDoc 会自动记录调用序列。
对于 C 语言编写的方法,RDoc 无法确定方法接受什么参数,因此需要使用 RDoc 指令 call-seq: 来记录。
对于单例方法,使用以下形式:
class_name.method_name(method_args) {|block_args| ... } -> return_type
示例
* call-seq:
* Hash.new(default_value = nil) -> new_hash
* Hash.new {|hash, key| ... } -> new_hash
对于实例方法,使用以下形式(省略任何前缀,就像 RDoc 对 Ruby 编写的方法一样):
method_name(method_args) {|block_args| ... } -> return_type
例如,在 Array 中,使用:
* call-seq:
* count -> integer
* count(obj) -> integer
* count {|element| ... } -> integer
* call-seq: * <=> other -> -1, 0, 1, or nil
对于二元运算符风格的方法(例如,Array#&),在 call-seq 中引用 self(而不是,例如,array 或 receiver)。
* call-seq: * self & other_array -> new_array
参数
-
如果方法不接受参数,请省略括号。
-
如果方法接受可选参数:
-
使用
=(带空格的等号)分隔每个参数名及其默认值。 -
如果方法在省略参数或显式提供参数时具有相同的行为,请使用带有可选参数的
call-seq。例如,使用:* call-seq: * respond_to?(symbol, include_all = false) -> true or false
-
如果省略参数或显式提供参数时的行为不同,请使用带有单独行的
call-seq。例如,在Enumerable中,使用:* call-seq: * max -> element * max(n) -> array
-
Block
-
如果方法不接受块,请省略块。
-
如果方法接受块,
call-seq应为{|args| ... },而不是{|args| block }或{|args| code }。 -
如果方法接受块,但在省略块时返回
Enumerator,则call-seq应同时显示这两种形式:* call-seq: * array.select {|element| ... } -> new_array * array.select -> new_enumerator
返回类型
-
如果方法可以返回多种不同类型,请用“或”分隔这些类型,并在必要时用逗号分隔。
-
如果方法可以返回多种类型,请使用
object。 -
如果方法返回接收者,请使用
self。 -
如果方法返回与类相同的对象,仅当对象不是
self时才添加前缀new_;例如:new_array。
别名
-
在
call-seq中省略别名,除非该别名是运算符方法。如果同时列出常规方法和运算符方法,请在详细信息和示例部分解释何时推荐使用常规方法,何时推荐使用运算符方法。
摘要
接下来是摘要,简要描述了该方法的作用以及您为什么想要使用它。理想情况下,这应该是一个句子,但对于更复杂的方法,可能需要一个完整的段落。
对于 Array#count,摘要是:
返回指定元素的计数。
这很好,因为它简短且描述性强。避免在摘要中记录太多内容,坚持记录对读者最有用的信息。
简要示例
对于文档篇幅较长的方法,可以考虑添加一个“简要”部分,其中包含总结方法用法的示例。
该部分可以回答一些用户的问题(而无需他们阅读冗长的文档);请参阅 Array#[] 和 Array#[]=。
详细信息和示例
大多数非简单的示例方法都受益于示例,以及比摘要中提供的更详细的信息。在详细信息和示例部分,您可以记录该方法如何处理不同类型的参数,并提供正确用法的示例。在此部分,请侧重于如何正确使用该方法,而不是它如何处理不正确参数或边界情况。
并非方法的每种行为都需要示例。如果文档说明方法返回 self,则无需提供显示返回值与接收者相同的示例。如果文档说明方法返回 nil,则无需提供显示其返回 nil 的示例。如果详细信息提到对于某种参数类型会返回一个空数组,则无需为此提供示例。
仅当示例提供额外信息时才添加示例,如果示例提供与摘要或详细信息相同的信息,则不要添加。示例的目的不是证明细节的准确性。
许多可以接受可选块的方法会在收到块时调用它,但如果未收到块则返回一个新的 Enumerator;在这种情况下,不要提供示例,但要说明该事实(使用自动链接的大写 Enumerator)。
* With no block given, returns a new Enumerator.
参数描述(如果需要)
对于需要参数的方法,如果参数不明显且未在详细信息中明确提及,或未在示例中隐式显示,您可以提供有关支持的参数类型的信息。在讨论参数类型时,使用简单的语言,即使不太精确,例如“level 必须是整数”,而不是“level 必须是可转换为 Integer 的对象”。大多数使用情况将是预期的类型,而不是可显式转换为预期类型的参数,记录这种区别并不重要。
对于接受块的方法,如果块参数的类型不明显,未在详细信息中明确提及,且未在示例中隐式显示,则记录块参数的类型可能很有用。
如果有一个以上的参数或块参数,请使用 带标签的列表。
边界情况和异常
对于方法的边界情况,例如非典型用法,请简要提及行为,但不要提供任何示例。
仅当异常不明显时才记录抛出的异常。例如,如果你之前已经说明参数类型必须是整数,那么就不需要记录传入非整数时会抛出 TypeError。除非是常见情况,否则不要提供抛出异常的示例,例如 Hash#fetch 抛出 KeyError。
相关方法(可选)
在某些情况下,记录哪些方法与当前方法相关很有用。例如,Hash#[] 的文档可以提及 Hash#fetch 作为相关方法,而 Hash#merge 可以提及 Hash#merge! 作为相关方法。
-
考虑哪些方法可能与当前方法相关,如果你认为读者会从中受益,请在方法文档的末尾添加一行以“Related: ”开头(例如,“Related: fetch.”)。
-
不要列出超过三个相关方法。如果你认为有三个以上的方法相关,请列出你认为最重要的三个。
-
考虑添加:
-
一个短语,说明相关方法与当前方法有何相似或不同。示例请参见
Time#getutc。 -
说明相似性和差异的示例代码。示例请参见
Time#ctime、Time#inspect、Time#to_s。
-
接受多种参数类型的 C 语言编写的方法
对于接受多种参数类型的 C 语言编写的方法,在某些情况下,分别记录不同的参数类型可能很有用。最好为讨论的每种情况使用单独的段落。