Effective Dart: ドキュメンテーション
- コメント
- ドキュメントコメント- DO /// ドキュメントコメントを使用してメンバーや型をドキュメント化する
- PREFER 公開APIのドキュメントコメントを作成する
- CONSIDER ライブラリレベルのドキュメントコメントを作成する
- CONSIDER プライベートAPIのドキュメントコメントを作成する
- DO ドキュメントコメントを単一文の要約で始める
- DO ドキュメントコメントの最初の文を独自の段落に分離する
- AVOID 周囲のコンテキストとの冗長性を避ける
- PREFER 関数またはメソッドのコメントを、その主な目的が副作用である場合は三人称動詞で始める
- PREFER 真偽値以外の変数またはプロパティのコメントを名詞句で始める
- PREFER 真偽値の変数またはプロパティのコメントを "Whether" で始めて、その後に名詞または動名詞句を続ける
- PREFER 関数またはメソッドの主な目的が値の返還である場合は、名詞句または非命令動詞句を使用する
- DON'T プロパティのgetterとsetterの両方にドキュメントを記述しない
- PREFER ライブラリまたは型のコメントを名詞句で始める
- CONSIDER コードサンプルをドキュメントコメントに含める
- DO スコープ内の識別子を参照するために、ドキュメントコメントで角括弧を使用する
- DO prose(散文)を使用して、パラメータ、戻り値、例外を説明する
- DO メタデータアノテーションの前にドキュメントコメントを置く
 
- Markdown
- 記述
コードが今日では明白であると思っていても、すでに頭の中にあるコンテキストにどれだけ依存しているかに気づいていないということはよくあります。あなたのコードに慣れていない人々、さらには忘れっぽい未来のあなた自身でさえ、そのコンテキストを持っていません。簡潔で正確なコメントは、書くのに数秒しかかかりませんが、それらの人々の一人の時間を何時間も節約できます。
コードは自己文書化されるべきであり、すべてのコメントが役立つわけではないことは、私たちは皆知っています。しかし現実は、私たちの大半が十分な量のコメントを書いていないということです。それは運動のようなものです。技術的にはやりすぎの可能性はありますが、やりすぎている可能性よりも、やりすぎている可能性の方がはるかに高いです。少し頑張ってみてください。
コメント
#以下のヒントは、生成されるドキュメントに含まれないコメントに適用されます。
DO フォーマットコメントを文章のように記述する
#// Not if anything comes before it.
if (_chunks.isNotEmpty) return false;最初の単語を大文字にする(ケースセンシティブな識別子でない場合)。ピリオド(または「!」または「?」、おそらく)で終わらせる。これはすべてのコメントに当てはまります。ドキュメントコメント、インラインの記述、TODOコメントでさえも。文の断片であっても同様です。
DON'T ドキュメンテーションのためにブロックコメントを使用しない
#void greet(String name) {
  // Assume we have a valid name.
  print('Hi, $name!');
}void greet(String name) {
  /* Assume we have a valid name. */
  print('Hi, $name!');
}ブロックコメント(/* ... */)を使用してコードの一部を一時的にコメントアウトできますが、それ以外のすべてのコメントでは//を使用してください。
ドキュメントコメント
#ドキュメントコメントは特に便利です。なぜなら、dart docがそれらを解析して、それらから美しいドキュメントページを生成するからです。ドキュメントコメントとは、宣言の前に現れ、dart docが探す特別な///構文を使用するコメントです。
DO /// ドキュメントコメントを使用してメンバーや型をドキュメント化する
#Linterルール: slash_for_doc_comments
通常のコメントの代わりにドキュメントコメントを使用すると、dart docがそれを見つけてドキュメントを生成できるようになります。
/// The number of characters in this chunk when unsplit.
int get length => ...// The number of characters in this chunk when unsplit.
int get length => ...歴史的な理由から、dart docは2つのドキュメントコメント構文をサポートしています。///(「C#スタイル」)と/** ... */(「JavaDocスタイル」)です。私たちは///を好みます。なぜなら、よりコンパクトだからです。/**と*/は、複数行のドキュメントコメントに2行のコンテンツのない行を追加します。///構文は、ドキュメントコメントに*を使用してリスト項目をマークする箇条書きリストが含まれている場合など、一部の状況で読みやすくなります。
まだJavaDocスタイルのコードに出くわした場合は、それをクリーンアップすることを検討してください。
PREFER 公開APIのドキュメントコメントを作成する
#Linterルール: public_member_api_docs
すべてのライブラリ、トップレベル変数、型、メンバーをドキュメント化する必要はありませんが、ほとんどはドキュメント化すべきです。
CONSIDER ライブラリレベルのドキュメントコメントを作成する
#Javaのようなクラスだけがプログラム編成の単位である言語とは異なり、Dartではライブラリ自体がユーザーが直接操作し、インポートし、考えるエンティティです。そのため、libraryディレクティブは、読者に提供される主要な概念と機能を紹介するドキュメントの優れた場所になります。以下を含めることを検討してください。
- ライブラリが何のためのものなのかの単一文の要約。
- ライブラリ全体で使用される用語の説明。
- APIの使用方法を段階的に説明する、いくつかの完全なコードサンプルの例。
- 最も重要または最も一般的に使用されるクラスや関数のリンク。
- ライブラリが関連するドメインの外部参照へのリンク。
ライブラリをドキュメント化するには、ファイルのはじめにあるlibraryディレクティブと、そこに添付される可能性のあるアノテーションの前にドキュメントコメントを配置します。
/// A really great test library.
@TestOn('browser')
library;CONSIDER プライベートAPIのドキュメントコメントを作成する
#ドキュメントコメントは、ライブラリの公開APIの外部コンシューマーのためだけのものではありません。ライブラリの他の部分から呼び出されるプライベートメンバーを理解するのに役立つこともあります。
DO ドキュメントコメントを単一文の要約で始める
#ドキュメントコメントは、短く、ユーザー中心の説明で始め、ピリオドで終わらせます。文の断片で十分な場合が多いです。読者が状況を把握し、さらに読み進めるべきか、または問題の解決策を他の場所で探すべきかを判断するために必要なだけ十分なコンテキストを提供します。
/// 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) {
  ...
}DO ドキュメントコメントの最初の文を独自の段落に分離する
#最初の文の後に空白行を追加して、独自の段落に分離します。1文以上の説明が役立つ場合は、残りを後続の段落に配置します。
これは、ドキュメントを要約する簡潔な最初の文を作成するのに役立ちます。また、dart docのようなツールは、クラスやメンバーのリストなどの場所で最初の段落を短い要約として使用します。
/// 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) {
  ...
}AVOID 周囲のコンテキストとの冗長性を避ける
#クラスのドキュメントコメントの読者は、クラス名、実装しているインターフェースなどを明確に見ることができます。メンバーのドキュメントを読むときは、シグネチャがそこにあり、囲んでいるクラスが明白です。これらすべてをドキュメントコメントで説明する必要はありません。代わりに、読者がすでに知らないことを説明することに焦点を当てます。
class RadioButtonWidget extends Widget {
  /// Sets the tooltip to [lines].
  ///
  /// The lines should be 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) {
    ...
  }
}宣言自体から推測できる以上の興味深いことを言うことが本当にない場合は、ドキュメントコメントを省略してください。読者の時間を無駄にして、すでに知っていることを伝えるよりも、何も言わない方がましです。
PREFER 関数またはメソッドのコメントを、その主な目的が副作用である場合は三人称動詞で始める
#ドキュメントコメントは、コードが*何をするか*に焦点を当てるべきです。
/// Connects to the server and fetches the query results.
Stream<QueryResult> fetchResults(Query query) => ...
/// Starts the stopwatch if not already running.
void start() => ...PREFER 真偽値以外の変数またはプロパティのコメントを名詞句で始める
#ドキュメントコメントは、プロパティが*何であるか*を強調すべきです。これは、計算やその他の作業を行うgetterの場合でも同様です。呼び出し側が気にするのは、その作業の*結果*であり、作業自体ではありません。
/// The current day of the week, where `0` is Sunday.
int weekday;
/// The number of checked buttons on the page.
int get checkedCount => ...PREFER 真偽値の変数またはプロパティのコメントを "Whether" で始めて、その後に名詞または動名詞句を続ける
#ドキュメントコメントは、この変数が表す状態を明確にすべきです。これは、計算やその他の作業を行うgetterの場合でも同様です。呼び出し側が気にするのは、その作業の*結果*であり、作業自体ではありません。
/// Whether the modal is currently displayed to the user.
bool isVisible;
/// Whether the modal should confirm the user's intent on navigation.
bool get shouldConfirm => ...
/// Whether resizing the current browser window will also resize the modal.
bool get canResize => ...PREFER 関数またはメソッドの主な目的が値の返還である場合は、名詞句または非命令動詞句を使用する
#メソッドが構文的にはメソッドでありながら、概念的にはプロパティであり、したがって名詞句または非命令動詞句で名前が付けられている場合、それも同様にドキュメント化されるべきです。構文上のプロパティや変数と同様に、このような真偽値以外の関数には名詞句を、このような真偽値関数には "Whether" で始まる句を使用してください。
/// The [index]th element of this iterable in iteration order.
E elementAt(int index);
/// Whether this iterable contains an element equal to [element].
bool contains(Object? element);DON'T プロパティのgetterとsetterの両方にドキュメントを記述しない
#プロパティにgetterとsetterの両方がある場合は、どちらか一方にのみドキュメントコメントを作成してください。dart docはgetterとsetterを単一のフィールドとして扱います。getterとsetterの両方にドキュメントコメントがある場合、dart docはsetterのドキュメントコメントを破棄します。
/// The pH level of the water in the pool.
///
/// Ranges from 0-14, representing acidic to basic, with 7 being neutral.
int get phLevel => ...
set phLevel(int level) => .../// The depth of the water in the pool, in meters.
int get waterDepth => ...
/// Updates the water depth to a total of [meters] in height.
set waterDepth(int meters) => ...PREFER ライブラリまたは型のコメントを名詞句で始める
#クラスのドキュメントコメントは、プログラムの中で最も重要なドキュメントであることがよくあります。それらは型の不変条件を説明し、使用される用語を確立し、クラスのメンバーの他のドキュメントコメントのコンテキストを提供します。ここで少し余分な労力をかけることで、他のすべてのメンバーのドキュメント作成が簡単になります。
ドキュメントは、型の*インスタンス*を記述すべきです。
/// A chunk of non-breaking output text terminated by a hard or soft newline.
///
/// ...
class Chunk {
   ...
}CONSIDER コードサンプルをドキュメントコメントに含める
#/// The lesser of two numbers.
///
/// ```dart
/// min(5, 3) == 3
/// ```
num min(num a, num b) => ...人間は例から一般化するのが得意なので、たとえ1つのコードサンプルでもAPIの学習が容易になります。
DO スコープ内の識別子を参照するために、ドキュメントコメントで角括弧を使用する
#Linterルール: comment_references
変数、メソッド、または型名のようなものを角括弧で囲むと、dart docは名前を検索して関連するAPIドキュメントにリンクします。括弧はオプションですが、関数またはコンストラクタを参照していることを明確にすることができます。以下の部分的なドキュメントコメントは、これらのコメント参照が役立ついくつかのケースを示しています。
/// Throws a [StateError] if ...
///
/// Similar to [anotherMethod()], but ...特定のクラスのメンバーにリンクするには、クラス名とメンバー名をドットで区切って使用します。
/// Similar to [Duration.inDays], but handles fractional days.ドット構文は、名前付きコンストラクタを参照するためにも使用できます。名前のないコンストラクタの場合は、クラス名の後に.newを使用します。
/// To create a point, call [Point.new] or use [Point.polar] to ...アナライザーとdart docがドキュメントコメントでサポートする参照についてさらに詳しく知るには、ドキュメントコメントの参照を確認してください。
DO prose(散文)を使用して、パラメータ、戻り値、例外を説明する
#他の言語では、メソッドのパラメータと戻り値を説明するために、冗長なタグとセクションを使用しています。
/// 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 abbreviation) => ...Dartの慣習は、それをメソッドの説明に統合し、角括弧を使用してパラメータを強調することです。
パラメータを説明するために「The [parameter]」で始まるセクション、返される値を説明するために「Returns」、例外を説明するために「Throws」を検討してください。エラーは例外と同じようにドキュメント化することも、単に満たされるべき要件として記述し、スローされる正確なエラーをドキュメント化しないこともできます。
/// Defines a flag with the given [name] and [abbreviation].
///
/// The [name] and [abbreviation] strings must not be empty.
///
/// Returns a new flag.
///
/// Throws a [DuplicateFlagException] if there is already an option named
/// [name] or there is already an option using the [abbreviation].
Flag addFlag(String name, String abbreviation) => ...DO メタデータアノテーションの前にドキュメントコメントを置く
#/// 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フォーマットをドキュメントコメントで使用できます。dart docはmarkdownパッケージを使用してそれらを適切に処理します。
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:
///
/// ```dart
/// 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:
///
/// * https://www.just-a-bare-url.com
/// * [with the URL inline](https://google.com)
/// * [or separated out][ref link]
///
/// [ref link]: https://google.com
///
/// # A Header
///
/// ## A subheader
///
/// ### A subsubheader
///
/// #### If you need this many levels of headers, you're doing it wrongAVOID Markdownを過度に使用しない
#迷ったら、フォーマットを少なくしてください。フォーマットはコンテンツを照らすためのものであり、置き換えるためのものではありません。言葉が重要です。
AVOID フォーマットのためにHTMLを使用しない
#テーブルなど、まれなケースで使用すると便利な場合がありますが、ほとんどの場合、Markdownで表現するには複雑すぎる場合は、表現しない方が良いでしょう。
PREFER コードブロックのためにバッククォートフェンスを使用する
#Markdownには、コードブロックを示すための2つの方法があります。各行のコードを4つのスペースでインデントするか、3つのバッククォートの「フェンス」行のペアで囲みます。前者の構文は、インデントがすでに意味を持つMarkdownリスト内にある場合や、コードブロック自体にインデントされたコードが含まれている場合に壊れやすいです。
バッククォート構文は、それらのインデントの問題を回避し、コードの言語を示すことができ、インラインコードにバッククォートを使用することと一貫しています。
/// You can use [CodeBlockExample] like this:
///
/// ```dart
/// var example = CodeBlockExample();
/// print(example.isItGreat); // "Yes."
/// ```/// You can use [CodeBlockExample] like this:
///
///     var example = CodeBlockExample();
///     print(example.isItGreat); // "Yes."記述
#私たちは自分自身をプログラマーと考えていますが、ソースファイルのほとんどの文字は主に人間が読むために意図されています。英語は、同僚の脳を改造するためにコードを書く言語です。あらゆるプログラミング言語と同様に、習熟度を向上させるために努力する価値があります。
このセクションでは、私たちのドキュメントに関するいくつかのガイドラインをリストします。一般的な技術文書作成のベストプラクティスについては、Technical writing styleなどの記事でさらに詳しく学ぶことができます。
PREFER 短さを優先する
#明確かつ正確に、しかし簡潔に記述する。
AVOID 省略形や頭字語は、明白でない限り使用しない
#"i.e."、"e.g."、"et al."の意味を知らない人がたくさんいます。あなたの分野の誰もが知っていると確信しているその頭字語は、あなたが思っているほど広く知られていないかもしれません。
PREFER メンバーのインスタンスを参照するために "the" の代わりに "this" を使用する
#クラスのメンバーをドキュメント化する場合、メンバーが呼び出されているオブジェクトを指し示す必要があることがよくあります。"the" を使用すると曖昧になる可能性があります。"this" の後に修飾子を付けることを優先してください。"this" だけでは曖昧になる可能性もあります。
class Box {
  /// The value this box wraps.
  Object? _value;
  /// Whether this box contains a value.
  bool get hasValue => _value != null;
}