目次

Effective Dart: ドキュメント

目次 keyboard_arrow_down keyboard_arrow_up
more_horiz

コードが分かりやすいと思っていても、自分がどれほど頭の中のコンテキストに頼っているか気づかないことはよくあることです。あなたのコードに初めて触れる人、そして忘れっぽい未来のあなたでさえ、そのコンテキストを持っていないでしょう。簡潔で正確なコメントは、書くのに数秒しかかかりませんが、それらの人々の時間を何時間も節約することができます。

コードは自己文書化されるべきであり、すべてのコメントが役に立つわけではないことは誰もが知っています。しかし、現実は、私たちのほとんどは書くべきコメントの数ほど書いていないということです。それは運動のようなものです。技術的にはやりすぎることはできますが、やりなさすぎることのほうが多いでしょう。もっと頑張ってみましょう。

コメント

#

以下のヒントは、生成されたドキュメントに含めたくないコメントに適用されます。

コメントは文章のようにフォーマットする

#
良い例dart
// Not if anything comes before it.
if (_chunks.isNotEmpty) return false;

大文字と小文字が区別される識別子でない限り、最初の単語は大文字にします。ピリオド(または「!」または「?」)で終わります。これはすべてのコメントに当てはまります。ドキュメントコメント、インラインのもの、TODOでさえもです。たとえそれが文の断片であってもです。

ドキュメントにブロックコメントを使用しない

#
良い例dart
void greet(String name) {
  // Assume we have a valid name.
  print('Hi, $name!');
}
悪い例dart
void greet(String name) {
  /* Assume we have a valid name. */
  print('Hi, $name!');
}

ブロックコメント(/* ... */)を使用してコードのセクションを一時的にコメントアウトできますが、他のすべてのコメントは//を使用する必要があります。

ドキュメントコメント

#

ドキュメントコメントは、dart docがそれらを解析し、美しいドキュメントページを生成するため、特に便利です。ドキュメントコメントとは、宣言の前に表示され、dart docが探す特別な///構文を使用するコメントのことです。

メンバーと型のドキュメントには`///`ドキュメントコメントを使用する

#

リンタールール: slash_for_doc_comments

通常のコメントの代わりにドキュメントコメントを使用すると、dart docがそれを見つけてドキュメントを生成できます。

良い例dart
/// The number of characters in this chunk when unsplit.
int get length => ...
悪い例dart
// The number of characters in this chunk when unsplit.
int get length => ...

歴史的な理由から、`dart doc`はドキュメントコメントの2つの構文をサポートしています。`///`(「C#スタイル」)と`/** ... */`(「JavaDocスタイル」)です。`///`の方がコンパクトなので、こちらを推奨します。`/**`と`*/`は、複数行のドキュメントコメントに2つのコンテンツのない行を追加します。`///`構文は、ドキュメントコメントに`*`を使用してリスト項目をマークする箇条書きリストが含まれている場合など、状況によっては読みやすくなります。

まだJavaDocスタイルを使用しているコードに出くわした場合は、クリーンアップすることを検討してください。

パブリックAPIのドキュメントコメントを作成することを推奨する

#

リンタールール:package_api_docspublic_member_api_docs

すべてのライブラリ、トップレベル変数、型、およびメンバーを文書化する必要はありませんが、ほとんどのものを文書化する必要があります。

ライブラリレベルのドキュメントコメントの作成を検討する

#

クラスがプログラム構成の唯一の単位であるJavaのような言語とは異なり、Dartでは、ライブラリ自体はユーザーが直接操作し、インポートし、考えるエンティティです。そのため、`library`ディレクティブは、読者にライブラリ内で提供される主要な概念と機能を紹介するドキュメントを配置するのに最適な場所です。以下を含めることを検討してください。

  • ライブラリの目的の単文要約。
  • ライブラリ全体で使用される用語の説明。
  • APIの使い方を順を追って説明する、いくつかの完全なコードサンプル。
  • 最も重要または最も一般的に使用されるクラスと関数へのリンク。
  • ライブラリが関係するドメインの外部リファレンスへのリンク。

ライブラリを文書化するには、`library`ディレクティブと、ファイルの先頭にある可能性のあるアノテーションの前にドキュメントコメントを配置します。

良い例dart
/// A really great test library.
@TestOn('browser')
library;

プライベートAPIのドキュメントコメントの作成を検討する

#

ドキュメントコメントは、ライブラリのパブリックAPIの外部の利用者だけのものではありません。ライブラリの他の部分から呼び出されるプライベートメンバーを理解するのにも役立ちます。

ドキュメントコメントは、単一の要約文で始める

#

ドキュメントコメントは、ピリオドで終わる簡潔でユーザー中心の説明から始めます。多くの場合、文の断片で十分です。読者が自分の向きを定め、読み続けるか、問題の解決策を他の場所で探すかを判断するのに十分なコンテキストを提供します。

良い例dart
/// Deletes the file at [path] from the file system.
void delete(String path) {
  ...
}
悪い例dart
/// 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) {
  ...
}

ドキュメントコメントの最初の文は、独自の段落に分割する

#

最初の文の後に空行を追加して、独自の段落に分割します。複数の説明文が役立つ場合は、残りを後の段落に配置します。

これは、ドキュメントを要約する簡潔な最初の文を書くのに役立ちます。また、`dart doc`のようなツールは、最初の段落をクラスとメンバーのリストのような場所で短い要約として使用します。

良い例dart
/// 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) {
  ...
}
悪い例dart
/// 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) {
  ...
}

周囲のコンテキストとの冗長性を避ける

#

クラスのドキュメントコメントを読む人は、クラスの名前、実装するインターフェースなどを明確に理解できます。メンバーのドキュメントを読む場合、シグネチャはそこにあり、囲んでいるクラスは明白です。ドキュメントコメントでこれらを詳しく説明する必要はありません。代わりに、読者が*まだ知らない*ことを説明することに焦点を当ててください。

良い例dart
class RadioButtonWidget extends Widget {
  /// Sets the tooltip to [lines], which should have been word wrapped using
  /// the current font.
  void tooltip(List<String> lines) {
    ...
  }
}
悪い例dart
class RadioButtonWidget extends Widget {
  /// Sets the tooltip for this radio button widget to the list of strings in
  /// [lines].
  void tooltip(List<String> lines) {
    ...
  }
}

宣言自体から推測できない興味深い内容が本当にない場合は、ドキュメントコメントを省略してください。何も言わない方が、読者の時間を無駄にして既に知っていることを伝えるよりもましです。

関数またはメソッドのコメントは、三人称動詞で始めることを推奨する

#

ドキュメントコメントは、コードが*何をするか*に焦点を当てるべきです。

良い例dart
/// Returns `true` if every element satisfies the [predicate].
bool all(bool predicate(T element)) => ...

/// Starts the stopwatch if not already running.
void start() {
  ...
}

ブール値でない変数またはプロパティのコメントは、名詞句で始めることを推奨する

#

ドキュメントコメントは、プロパティが*何であるか*を強調する必要があります。これは、計算やその他の作業を行うゲッターにも当てはまります。呼び出し元が関心を持っているのは、その作業の*結果*であり、作業自体ではありません。

良い例dart
/// The current day of the week, where `0` is Sunday.
int weekday;

/// The number of checked buttons on the page.
int get checkedCount => ...

ブール値の変数またはプロパティのコメントは、「Whether」の後に名詞または動名詞句を続けることを推奨する

#

ドキュメントコメントは、この変数が表す状態を明確にする必要があります。これは、計算やその他の作業を行うゲッターにも当てはまります。呼び出し元が関心を持っているのは、その作業の*結果*であり、作業自体ではありません。

良い例dart
/// 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 => ...

プロパティのゲッターとセッターの両方にドキュメントを作成しない

#

プロパティにゲッターとセッターの両方がある場合は、どちらか一方のみにドキュメントコメントを作成してください。`dart doc`はゲッターとセッターを単一のフィールドとして扱います。ゲッターとセッターの両方にドキュメントコメントがある場合、`dart doc`はセッターのドキュメントコメントを破棄します。

良い例dart
/// 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) => ...
悪い例dart
/// 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) => ...

ライブラリまたは型のコメントは、名詞句で始めることを推奨する

#

クラスのドキュメントコメントは、多くの場合、プログラムの中で最も重要なドキュメントです。これらは型の不変条件を記述し、使用する用語を確立し、クラスのメンバーの他のドキュメントコメントにコンテキストを提供します。ここで少し余分な努力をすることで、他のすべてのメンバーのドキュメント化が容易になります。

良い例dart
/// A chunk of non-breaking output text terminated by a hard or soft newline.
///
/// ...
class Chunk { ... }

ドキュメントコメントにコードサンプルを含めることを検討する

#
良い例dart
/// Returns the lesser of two numbers.
///
/// ```dart
/// min(5, 3) == 3
/// ```
num min(num a, num b) => ...

人間は例から一般化するのが得意なので、1つのコードサンプルだけでもAPIの学習が容易になります。

ドキュメントコメントでは、角かっこを使用してスコープ内の識別子を参照する

#

リンタールール: comment_references

変数、メソッド、型名などを角括弧で囲むと、`dart doc`はその名前を検索し、関連するAPIドキュメントにリンクします。括弧は省略可能ですが、メソッドまたはコンストラクタを参照している場合に明確になります。

良い例dart
/// Throws a [StateError] if ...
/// similar to [anotherMethod()], but ...

特定のクラスのメンバーにリンクするには、クラス名とメンバー名をドットで区切って使用します。

良い例dart
/// Similar to [Duration.inDays], but handles fractional days.

ドット構文は、名前付きコンストラクタを参照するためにも使用できます。名前のないコンストラクタの場合は、クラス名の後に`.new`を使用します。

良い例dart
/// To create a point, call [Point.new] or use [Point.polar] to ...

パラメータ、戻り値、および例外の説明には、散文を使用する

#

他の言語では、メソッドのパラメータと戻り値を記述するために、冗長なタグとセクションを使用します。

悪い例dart
/// 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) => ...

Dartの慣例では、それをメソッドの説明に統合し、角括弧を使用してパラメータを強調表示します。

良い例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) => ...

ドキュメントコメントは、メタデータアノテーションの前に配置する

#
良い例dart
/// A button that can be flipped on and off.
@Component(selector: 'toggle')
class ToggleComponent {}
悪い例dart
@Component(selector: 'toggle')
/// A button that can be flipped on and off.
class ToggleComponent {}

Markdown

#

ドキュメントコメントでは、ほとんどのMarkdownフォーマットを使用することができ、`dart doc`はmarkdownパッケージを使用してそれに応じて処理します。

Markdownを紹介するガイドは既にたくさんあります。それが普遍的に普及している理由は、私たちがMarkdownを選んだ理由です。サポートされている内容を理解するための簡単な例を次に示します。

dart
/// 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 wrong

Markdownの過剰な使用を避ける

#

疑問がある場合は、フォーマットを少なくしてください。フォーマットは、コンテンツを置き換えるためではなく、明確にするために存在します。重要なのは言葉です。

フォーマットにHTMLを使用しない

#

表のようなものにはまれに役立つ場合がありますが、ほとんどの場合、Markdownで表現するには複雑すぎる場合は、表現しない方がよいでしょう。

コードブロックには、バックティックフェンスを推奨する

#

Markdownには、コードブロックを示す2つの方法があります。各行のコードを4つのスペースでインデントするか、3つのバックティックの「フェンス」行のペアで囲みます。前者の構文は、インデントが既に意味を持つMarkdownリスト内や、コードブロック自体にインデントされたコードが含まれている場合に使用すると、不安定になります。

バックティック構文は、これらのインデントの問題を回避し、コードの言語を示すことができ、インラインコードにバックティックを使用することと一貫性があります。

良い例dart
/// You can use [CodeBlockExample] like this:
///
/// ```dart
/// var example = CodeBlockExample();
/// print(example.isItGreat); // "Yes."
/// ```
悪い例dart
/// You can use [CodeBlockExample] like this:
///
///     var example = CodeBlockExample();
///     print(example.isItGreat); // "Yes."

文章

#

私たちは自分自身をプログラマーだと考えていますが、ソースファイルのほとんどの文字は、主に人間が読むことを目的としています。英語は、同僚の頭脳を修正するためにコードを書く言語です。他のプログラミング言語と同様に、習熟度を向上させるための努力をする価値があります。

このセクションでは、ドキュメントのガイドラインをいくつか示します。テクニカルライティングのベストプラクティス全般については、テクニカルライティングスタイルなどの記事から学ぶことができます。

簡潔さを心がける

#

明確かつ正確に、しかし簡潔に記述してください。

明白でない限り、略語や頭文字の使用を避ける

#

多くの人は、「すなわち」、「例えば」、「その他」の意味を知りません。あなたの分野の誰もが知っていると思っている頭字語は、あなたが思っているほど広く知られていないかもしれません。

メンバーのインスタンスを参照するには、「the」ではなく「this」を使用することを推奨する

#

クラスのメンバーを文書化する場合、メンバーが呼び出されているオブジェクトを参照する必要があることがよくあります。「the」を使用すると、あいまいになる可能性があります。

dart
class Box {
  /// The value this wraps.
  Object? _value;

  /// True if this box contains a value.
  bool get hasValue => _value != null;
}