代码注释是开发过程中必不可少的一个过程,那么,我们在进行Flutter开发时,怎么去进行文档注释呢?
这篇文章的主旨就是Flutter所使用的dart语言注释学习。
Dart支持单行注释, 多行注释和文档注释
1.单行注释
单行注释以//开头, Dart编译器会忽略//和行尾之间的所有内容
say() {
// TODO: say something
print('Hello dart!');
}
2.多行注释
多行注释以 /* 开头,以 / 结尾, Dart编译器忽略 / 和 */ 之间的所有内容(除非注释是文档注释), 多行注释可以嵌套
sayWhat(String what) {
/*
* Say something
* */
print(what);
}
3.文档注释
文档注释是以 ///或 /** 开头的多行或单行注释, 在连续行上使用 /// 与多行文档注释具有相同的效果。
在文档注释中,Dart编译器忽略所有文本,除非它括在括号中。 使用括号,您可以引用类,方法,字段,顶级变量,函数和参数。 括号中的名称在已记录的程序元素的词法范围内得到解析。
/// Dart class
///
/// TODO: Say hello to dart
class Dart {
/// Say hello to dart
say() {
// TODO: say something
print('Hello dart!');
}
/// Say something to dart
/// The string [what] is what you want to say.
sayWhat(String what) {
/*
* Say something
* */
print(what);
}
}
Windows10+Flutter环境下我们使用dart sdk的文档生成工具来生成文档(dartdoc的Github地址),dartdoc.bat位于
XXX\dart-sdk\bin
从Flutter项目的根目录运行dartdoc, 文档目录会根据flutter项目的目录的lib下进行生成
我们可以看到生成的文档放在了目录
项目目录\doc\api
用浏览器打开自定义类的注解为
4.高效Dart注释
- 注释
- 文档注释
- Markdown
- 写注释
在编写代码时, 很容易认为自己的代码已经写得很清楚,但是没有意识到已经依赖脑海中的上下文,如果另一个人接手你的代码的话,或者代码写完一段时间后再回顾的话,一段简明扼要的注释是非常重要的,可以节省大量时间,因此下面这里有一些提高dart开发的注释窍门。
-
注释
注释句子化
避免使用块注释
-
文档注释
使用 /// 注释成员和类型
优先为public的接口编写注释
考虑写一个库级别的文档注释
考虑为private的接口编写文档注释
文档开头尽量用单句总结
分离文档注释的第一句到自己的段落中
避免与周围上下文冗余
优先使用第三人称动词注释函数或方法
优先使用名词短语注释变量, getter或setter
优先使用名词短语注释库或者类型
考虑使用代码示例注释
尽量在文档注释中使用方括号来引用范围内标识符
尽量简约地注释参数, 返回值和异常
尽量在元数据注释之前加上文档注释
-
Markdown
避免过度使用markdown避免使用HTML进行格式化
优先使用反括号来隔开代码块
-
写注释
简短优先避免使用缩写词和缩写词
首选使用“this”而不是“the”来引用成员实例
注释
以下提示适用于你不希望包含在生成的文档中的注释
注释句子化
// Not if there is nothing before it.
if (_chunks.isEmpty) return false;
针对英文:第一个字母需大写,除非它是区分大小写的标识符, 且需要使用句号,或者!或者?结束句子,所有注释都需如此:文档注释,内联内容,甚至是TODO。
中文: 尽量用一句简明扼要的话注释
避免使用块注释
greet(name) {
// Assume we have a valid name.
print('Hi, $name!');
}
下面为不推荐示范:
greet(name) {
/* Assume we have a valid name. */
print('Hi, $name!');
}
推荐使用(/ * ... * /)注释代码,其他文字注释应该使用//
文档注释
文档注释特别方便,因为dartdoc命令可以解析并生成好看的文档页。文档注释是任何出现在声明之前的注释,dartdoc会查找使用 /// 标记的注释
使用 /// 注释成员和类型
Linter规则:slash_for_doc_comments
使用文档注释 /// 而不是常规的注释使执行dartdoc命令时能找到注释并生成文档,一般在方法和类名上注释
/// The number of characters in this chunk when unsplit.
int get length => ...
下面为不推荐示范
// The number of characters in this chunk when unsplit.
int get length => ...
由于历史原因,dartdoc支持doc comments的两种语法:///(“C#style”)和/ ** ... * /(“JavaDoc style”),我们更喜欢///,因为它更紧凑。 / 和 /将两条无内容行添加到多行文档注释中。 在某些情况下,///语法也更容易阅读,例如当doc注释包含使用标记列表项的项目符号列表时。
如果您偶然发现仍使用JavaDoc样式的代码,请考虑清理它。
优先为public的接口编写注释
Linter 规则: package_api_docs, public_member_api_docs
不必记录每个库,顶级变量,类型和成员,但应该注释其中的大多数。
考虑写一个库级别的文档注释
与Java这样的语言不同,类是程序组织中的唯一单元,但是在Dart中,库本身就是用户直接使用,导入和思考的实体。 这使得库指令成为文档注释的好地方,可以向读者介绍其中提供的主要概念和功能。 考虑包括:
- 关于库用途的单句摘要。
- 整个库使用的术语解释。
- 一些使用API完成的完整代码示例。
- 链接到(即库中使用的)最重要或最常用的类和函数。
- 链接到(即库中使用的)库所关注的域上的外部引用。
你可以通过在文件开头的库指令上方放置doc注释来记录库。 如果库没有库指令,您可以添加一个只是挂起文档注释。
考虑为private的接口编写文档注释
Doc comments aren’t just for external consumers of your library’s public API. They can also be helpful for understanding private members that are called from other parts of the library.
文档注释不仅适用于库的公共API, 同样有助于理解从库的其他部分调用的私有成员。
文档开头尽量用单句总结
开始以句号结尾的简短的,以用户为中心的注释文档。 句子片段通常就足够了,为读者提供足够的上下文来定位自己,并决定是否应该继续阅读或寻找解决问题的方法。
/// Deletes the file at [path] from the file system.
void delete(String path) {
...
}
下面为不推荐示范:
/// Depending on the state of the file system and the user's permissions,
/// certain operations may or may not be possible. If there is no file at
/// [path] or it can't be accessed, this function throws either [IOError]
/// or [PermissionError], respectively. Otherwise, this deletes the file.
void delete(String path) {
...
}
简而言之就是尽量简明扼要
分离文档注释的第一句到自己的段落中
在第一句之后添加一个空行,将其拆分为自己的段落。 如果多于一句解释是有用的,请将其余部分放在后面的段落中。
这有助于您编写一个简短的第一句话来总结文档。 此外,像Dartdoc这样的工具使用第一段作为类和列表列表等地方的简短摘要。
/// Deletes the file at [path].
///
/// Throws an [IOError] if the file could not be found. Throws a
/// [PermissionError] if the file is present but could not be deleted.
void delete(String path) {
...
}
下面为不推荐示范:
/// Deletes the file at [path]. Throws an [IOError] if the file could not
/// be found. Throws a [PermissionError] if the file is present but could
/// not be deleted.
void delete(String path) {
...
}
简而言之即第一行说明该方法或类的主要功能,然后空一行,在进行详细描述或者参数等解释
避免与周围上下文冗余
读者可以从文档注释中清楚地看到类的名称,它实现的接口等。当读到成员的文档注释时,签名就在那里,而封闭的类是显而易见的。 这些都不需要在文档注释中拼写出来。 相反,专注于解释读者不知道的内容。
class RadioButtonWidget extends Widget {
/// Sets the tooltip to [lines], which should have been word wrapped using
/// the current font.
void tooltip(List<String> lines) {
...
}
}
下面为不推荐示范:
class RadioButtonWidget extends Widget {
/// Sets the tooltip for this radio button widget to the list of strings in
/// [lines].
void tooltip(List<String> lines) {
...
}
}
上面第一段注释清除地说明了该函数的使用目的,而下面不推荐的示例,则与上下文冗余了,"for this radio button widget"。
优先使用第三人称动词注释函数或方法
文档注释应该关注代码的作用
/// Returns `true` if every element satisfies the [predicate].
bool all(bool predicate(T element)) => ...
/// Starts the stopwatch if not already running.
void start() {
...
}
优先使用名词短语注释变量, getter或setter
文档注释应该强调属性是什么, 即使对于可能进行计算或其他工作的也是如此。 读者应该关心的是这段代码的结果,而不是代码本身。
/// The current day of the week, where `0` is Sunday.
int weekday;
/// The number of checked buttons on the page.
int get checkedCount => ...
优先使用名词短语注释库或者类型
类的文档注释通常是程序中最重要的部分,它们描述了类型的不变性,建立了它使用的术语,并为类的成员提供了其他文档注释的上下文,在这里做一点额外的努力可以让其他成员更容易记录
/// A chunk of non-breaking output text terminated by a hard or soft newline.
///
/// ...
class Chunk { ... }
简而言之就是多用专业术语,让注释看起来高大上
考虑使用代码示例注释
/// Returns the lesser of two numbers.
///
/// ```dart
/// min(5, 3) == 3
/// ```
num min(num a, num b) => ...
人类非常善于从示例中进行概括,因此即使是单个代码示例也可以使API更容易学习
尽量在文档注释中使用方括号来引用范围内标识符。
Linter规则: comment_references
如果在方括号中包含变量,方法或类型名称等内容,则dartdoc会查找名称并链接到相关的API文档。 括号是可选的,但在引用方法或构造函数时可以使它更清晰
/// Throws a [StateError] if ...
/// similar to [anotherMethod()], but ...
要链接到特定类的成员,请使用以点分隔的类名和成员名:
/// Similar to [Duration.inDays], but handles fractional days.
点语法也可用于引用命名构造函数。 对于未命名的构造函数,在类名后面加上括号:
/// To create a point, call [Point()] or use [Point.polar()] to ...
尽量简约地注释参数, 返回值和异常
Dart中的约定是将其集成到方法的描述中,并使用方括号突出显示参数:
/// Defines a flag.
///
/// Throws an [ArgumentError] if there is already an option named [name] or
/// there is already an option using abbreviation [abbr]. Returns the new flag.
Flag addFlag(String name, String abbr) => ...
下面为不推荐示范:
其他语言使用详细标记和部分来描述方法的参数和返回值。
/// Defines a flag with the given name and abbreviation.
///
/// @param name The name of the flag.
/// @param abbr The abbreviation for the flag.
/// @returns The new flag.
/// @throws ArgumentError If there is already an option with
/// the given name or abbreviation.
Flag addFlag(String name, String abbr) => ...
好吧,作为一个常年使用java开发的中国Androider, 我更偏向于使用第二种方式
尽量在元数据注释之前加上文档注释
/// A button that can be flipped on and off.
@Component(selector: 'toggle')
class ToggleComponent {}
下面为不推荐示范:
@Component(selector: 'toggle')
/// A button that can be flipped on and off.
class ToggleComponent {}
这里我不说话,让你自己看
Markdown
你可以在文档注释中使用大多数markdown格式,dartdoc将使用markdown包相应地处理它。
下面为一个使用示例
/// This is a paragraph of regular text.
///
/// This sentence has *two* _emphasized_ words (italics) and **two**
/// __strong__ ones (bold).
///
/// A blank line creates a separate paragraph. It has some `inline code`
/// delimited using backticks.
///
/// * Unordered lists.
/// * Look like ASCII bullet lists.
/// * You can also use `-` or `+`.
///
/// 1. Numbered lists.
/// 2. Are, well, numbered.
/// 1. But the values don't matter.
///
/// * You can nest lists too.
/// * They must be indented at least 4 spaces.
/// * (Well, 5 including the space after `///`.)
///
/// Code blocks are fenced in triple backticks:
///
/// ```
/// this.code
/// .will
/// .retain(its, formatting);
/// ```
///
/// The code language (for syntax highlighting) defaults to Dart. You can
/// specify it by putting the name of the language after the opening backticks:
///
/// ```html
/// <h1>HTML is magical!</h1>
/// ```
///
/// Links can be:
///
/// * http://www.just-a-bare-url.com
/// * [with the URL inline](http://google.com)
/// * [or separated out][ref link]
///
/// [ref link]: http://google.com
///
/// # A Header
///
/// ## A subheader
///
/// ### A subsubheader
///
/// #### If you need this many levels of headers, you're doing it wrong
可以看到使用了很多markdown语法注释
避免过度使用markdown
如有疑问,请格式化。 存在格式化以阐明您的内容,而不是替换它。 words很重要
避免使用HTML进行格式化
在极少数情况下使用它可能很有用,例如表格,但在几乎所有情况下,如果它在Markdown中过于复杂,你最好不要表达它。
优先使用反括号来隔开代码块
Markdown有两种表示代码块的方法:在每行上压缩代码四个空格,或者用反引号code
表示。 当在缩进已经有意义的Markdown列表或代码块本身包含缩进代码的内容中使用时,前一种语法很脆弱,意思就是使用markdown注释时,前面已经使用了缩进,但是现在再使用缩进表示代码的话,会显得不好阅读
反引号语法避免了那些缩进问题,让您指出代码的语言,并且与使用内联代码的反引号一致。
/// You can use [CodeBlockExample] like this:
///
/// ```
/// var example = CodeBlockExample();
/// print(example.isItGreat); // "Yes."
/// ```
下面为不推荐示范:
/// You can use [CodeBlockExample] like this:
///
/// var example = CodeBlockExample();
/// print(example.isItGreat); // "Yes."
这里总结一下什么情况使用markdown注释比较好:
1.注释类时,该类功能需要目录说明
2.示例代码比较多的时候
3.需要列表说明功能的时候
写注释
在开始写注释的时候,无论我们使用的是中文还是英文,我觉得都得有一个写注释的习惯,因为这关系到以后的个人代码回顾,和别人阅读你的代码的时候的难易程度。
简短优先
要清晰准确,但也要简洁。
避免使用缩写词和缩写词
对于英文来说:许多人不知道“ie”,“eg”和“et al”是什么意思,你确信你所在领域的每个人都知道这个首字母缩略词可能并不像你想象的那么广为人知
对于中文来说:个人觉得缩写词应该会用得比较少
首选使用“this”而不是“the”来引用成员实例
记录类的成员时,通常需要返回调用该成员的对象,使用“the”可能含糊不清
class Box {
/// The value this wraps.
var _value;
/// True if this box contains a value.
bool get hasValue => _value != null;
}
Dart语言之旅:https://www.dartlang.org/guides/language/language-tour#comments