Flutter學習之Dart語言註釋

代碼註釋是開發過程中必不可少的一個過程,那麼,我們在進行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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章