文档指南¶ ↑
本指南讨论了在 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 会温和地通知您。)
如果想将与 ASCII 不兼容的字符放入 C 编码的类、模块或方法的文档中,有一些解决方法,包括使用新文件 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.
呈现为
Class
变量可能很棘手。
此外,当所讨论的单词是指当前文档时(例如,类 Float
的文档中的 Float),确实抑制自动链接。
在这种情况下,您可以考虑强制名称为等宽字体,这将抑制自动链接,并强调该单词是一个类名
A +Float+ object represents ....
呈现为
一个
Float
对象表示……
对于非常少数、非常经常讨论的类,您可能会考虑完全避免使用大写的类名。例如,对于某些数组的提及,您可以简单地写小写的 array。
而不是
For an empty Array, ....
呈现为
对于空的
Array
,....
您可以写
For an empty array, ....
呈现为
对于空数组,....
这种更随意的用法避免了自动链接和分散注意力的字体更改,并且不太可能引起混淆。
此原则可以特别适用于
-
一个数组。
-
一个整数。
-
一个哈希。
-
一个字符串。
但是,它应该仅在引用该类的实例时应用,而绝不在引用类本身时应用。
显式链接¶ ↑
在编写显式链接时,请遵循以下准则。
rdoc-ref
方案¶ ↑
对于以下情况,使用 rdoc-ref
方案
-
核心文档中指向其他核心文档的链接。
-
核心文档中指向标准库包中文档的链接。
-
标准库包中指向同一标准库包中其他文档的链接。
请参阅链接中的“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) 表格,使用特殊格式设置文本
类和模块的文档编写¶ ↑
类或模块文档的总体结构应为:
-
概要
-
常见用法,附带示例
-
“此处内容”摘要(可选)
概要¶ ↑
概要是对类或模块的功能及其读者可能需要使用它的原因的简短描述。避免在概要中包含详细信息。
常见用法¶ ↑
展示类或模块的常见用法。根据类或模块的不同,此部分的长度和复杂性可能会有很大差异。
“此处内容”摘要¶ ↑
类或模块的文档可以包含一个“此处内容”部分。
指南
-
该部分的标题是
此处内容
。 -
考虑列出父类和任何包含的模块;如果存在,请考虑链接到它们的“此处内容”部分,使用链接。
-
左侧窗格目录中提到的所有方法都应列出(包括从另一个类扩展的任何方法)。
-
还可以列出属性(未包含在目录中)。
-
将方法显示为一个或多个项目符号列表中的条目
-
每个条目以方法名称开头,后跟冒号和简短描述。
-
如果该方法有别名,请在冒号前用括号提及它们(并且不要单独列出别名)。
-
检查呈现的文档以确定 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
-
块
-
如果该方法不接受块,请省略块。
-
如果该方法接受块,则
call-seq
应具有{|args| ... }
,而不是{|args| block }
或{|args| code }
。 -
如果该方法接受块,但在省略块时返回
Enumerator
,则call-seq
应同时显示两种形式:* call-seq: * array.select {|element| ... } -> new_array * array.select -> new_enumerator
返回类型
-
如果该方法可以返回多种不同的类型,请使用“or”分隔这些类型,并在必要时使用逗号。
-
如果该方法可以返回多种类型,请使用
object
。 -
如果该方法返回接收器,请使用
self
。 -
如果该方法返回同一类的对象,请仅当该对象不是
self
时才使用前缀new_
;示例:new_array
。
别名
-
从
call-seq
中省略别名,除非该别名是运算符方法。如果在call-seq
中同时列出常规方法和运算符方法,请在详细信息和示例部分中说明何时建议使用常规方法以及何时建议使用运算符方法。
概要¶ ↑
接下来是概要,是对方法的功能以及您为什么要使用它的简短描述。理想情况下,这是一个句子,但对于更复杂的方法,可能需要一整段。
对于 Array#count
,概要是:
返回指定元素的计数。
这很好,因为它简短且具有描述性。避免在概要中记录过多内容,为了读者的利益,请坚持最重要的信息。
简短示例¶ ↑
对于文档很长的方法,请考虑添加“简短”段落,其中显示总结方法用法的示例。
该段落可以回答一些用户的问题(而无需他们阅读长篇文档);请参阅 Array#[]
和 Array#[]=
。
详细信息和示例¶ ↑
大多数非平凡的方法都受益于示例,以及超出概要中给出的详细信息。在详细信息和示例部分中,您可以记录方法如何处理不同类型的参数,并提供有关正确用法的示例。在本节中,重点介绍如何正确使用该方法,而不是该方法如何处理不正确的参数或极端情况。
并非方法的每个行为都需要一个示例。如果该方法被记录为返回 self
,则无需提供一个示例来表明返回值与接收器相同。如果该方法被记录为返回 nil
,则无需提供一个示例来表明它返回 nil
。如果详细信息提到对于某种参数类型,将返回一个空数组,则无需提供该示例。
仅当示例为用户提供额外信息时才添加示例,如果示例提供与概要或详细信息中相同的信息,请勿添加示例。示例的目的不是为了证明详细信息所声明的内容。
许多可以采用可选块的方法都会在给出块时调用该块,但如果在未给出块时返回新的 Enumerator
;在这种情况下,请勿提供示例,但要说明事实(使用自动链接的大写 Enumerator
)
* With no block given, returns a new Enumerator.
参数描述(如有必要)¶ ↑
对于需要参数的方法,如果参数不明显且未在详细信息中明确提及或未在示例中隐式显示,则可以提供有关支持的参数类型的详细信息。在讨论参数类型时,即使不太精确,也请使用简单的语言,例如“level 必须是整数”,而不是“level 必须是 Integer-convertible 对象”。绝大多数使用都将使用预期类型,而不是显式转换为预期类型的参数,并且记录差异并不重要。
对于采用块的方法,如果传递的参数类型不明显、未在详细信息中明确提及且未在示例中隐式显示,则记录传递的参数类型会很有用。
如果有多个参数或块参数,请使用带标签的列表。
极端情况和异常¶ ↑
对于方法的极端情况,例如非典型用法,请简要提及行为,但不要提供任何示例。
仅记录不明显的引发异常。例如,如果您之前声明过参数类型必须为整数,则无需记录如果传递了非整数则会引发 TypeError
。除非这是常见情况,否则不要提供引发异常的示例,例如 Hash#fetch
引发 KeyError
。
相关方法(可选)¶ ↑
在某些情况下,记录哪些方法与当前方法相关很有用。例如,Hash#[]
的文档可能会将 Hash#fetch
作为相关方法提及,而 Hash#merge
可能会将 Hash#merge!
作为相关方法提及。
-
考虑哪些方法可能与当前方法相关,如果您认为读者会从中受益,请在方法文档的末尾添加一行,以“Related: ”开头(例如,“Related: fetch.”)。
-
不要列出超过三个相关方法。如果您认为有三个以上的方法相关,请列出您认为最重要的三个。
-
考虑添加:
-
一个短语,表明相关方法与当前方法相似或不同。请参阅
Time#getutc
中的示例。 -
说明相似之处和差异的示例代码。请参阅
Time#ctime
、Time#inspect
、Time#to_s
中的示例。
-
接受多种参数类型的方法¶ ↑
对于接受多种参数类型的方法,在某些情况下,单独记录不同的参数类型会很有用。最好为您讨论的每种情况使用单独的段落。