Effective Dartを読んでみた②
Effective Dart: Style
前回の続きを書いていこうと思う。
単語のように2文字以上の頭字語や略語は大文字にする。
大文字の頭字語は読みにくく、複数の頭字語が隣接していると曖昧な名前になってしまいます。たとえば、HTTPSFTPで始まる名前があった場合、それがHTTPS FTPを指しているのか、HTTP SFTPを指しているのかを見分ける方法はありません。
これを避けるため、頭字語や略語は通常の単語と同じように大文字で表記します。
例外があります: IO (input/output) のような2文字の頭字語は完全に大文字にします: IO。一方、ID(identification)のような2文字の略語は、通常の単語と同様に大文字で表記される: Id。
未使用のコールバック・パラメータには _ や __ などを使用することを推奨します。
コールバック関数の型シグネチャではパラメータが必要なのに、コールバックの実装ではそのパラメータを使用しないことがあります。この場合、未使用のパラメータに _ という名前をつけるのが一般的です。関数に複数の未使用パラメータがある場合は、名前の衝突を避けるために追加のアンダースコアを使用します: や ___ などです。
Riverpodのコードでも_
つけるのあったりしますね。_ =>
ここは、AsyncLoadingって本来書くのですが省略できます。
見本
Future<Configuration> configurations(ConfigurationsRef ref) async {
final uri = Uri.parse('configs.json');
final rawJson = await File.fromUri(uri).readAsString();
return Configuration.fromJson(json.decode(rawJson));
}
class Example extends ConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final configs = ref.watch(configurationsProvider);
// Use pattern matching to safely handle loading/error states
return switch (configs) {
AsyncData(:final value) => Text('data: ${value.host}'),
AsyncError(:final error) => Text('error: $error'),
_ => const CircularProgressIndicator(),
};
}
}
このガイドラインは、匿名かつローカルな関数のみを対象としています。これらの関数は通常、未使用のパラメータが何を表しているかが明らかなコンテキストですぐに使用されます。対照的に、トップレベル関数やメソッド宣言はそのようなコンテキストを持たないので、たとえ使用されなくても、各パラメータが何のためにあるのかが明確になるようにパラメータ名を付けなければなりません。
プライベートでない識別子には先頭のアンダースコアを使用しないでください。
Dartでは、メンバやトップレベルの宣言をプライベートであることを示すために、識別子の先頭のアンダースコアを使用します。これにより、ユーザは先頭のアンダースコアからこれらの宣言を連想するようになります。ユーザは"_"を見て "private "と思うのです。
ローカル変数、パラメータ、ローカル関数、ライブラリ接頭辞には「プライベート」という概念はありません。これらの名前がアンダースコアで始まっていると、読み手に混乱したシグナルを送ることになる。これを避けるには、これらの名前に先頭のアンダースコアを使わないことです。
接頭辞を使わない
ハンガリー記法やその他のスキームはBCPLの時代に生まれました。Dartは宣言の型、スコープ、ミュータビリティ、その他のプロパティを知ることができるので、識別子名にそれらのプロパティをエンコードする理由はありません。
明示的にライブラリ名を指定しない
ライブラリディレクティブに名前を付けることは技術的には可能ですが、レガシーな機能であるため推奨されません。
Dart は各ライブラリに対して、パスとファイル名に基づいて一意なタグを生成します。ライブラリに名前を付けると、この生成されたURIが上書きされます。URIがないと、ツールが問題のメインライブラリファイルを見つけるのが難しくなります。
順序
ファイルの前文を整理整頓するために、私たちはディレクティブを記述する順番を定めています。各「セクション」は空行で区切られなければなりません。
directives_ordering という一つのルールが、全ての順番のガイドラインを扱います。
dart:インポートを他のインポートの前に置く
リンタールール: directives_ordering
パッケージ:インポートを相対インポートの前に置く
すべてのインポートの後に、別のセクションでエクスポートを指定する。
リンタールール: directives_ordering
セクションをアルファベット順に並べ替える
フォーマット
多くの言語と同様、Dartは空白を無視する。しかし、人間はそうではありません。一貫した空白のスタイルを持つことで、人間の読者がコンパイラと同じようにコードを見ることができるようになります。
dart フォーマットを使用してコードをフォーマットする
フォーマットは面倒な作業で、特にリファクタリングの際には時間がかかります。幸い、その心配はありません。私たちはdart formatという洗練された自動コード整形ツールを提供しています。dartフォーマットが適用するルールについてはドキュメントがありますが、Dartの公式な空白処理ルールはdartフォーマットが生成するものです。
残りの書式設定ガイドラインは、dart formatが修正できない部分のためのものです。
フォーマッタが使いやすいようにコードを変更することを考える
フォーマッタは、あなたがどんなコードを投げつけても、できる限りのことはしますが、奇跡を起こすことはできません。コードが特に長い識別子を持っていたり、式が深くネストしていたり、さまざまな種類の演算子が混在していたりすると、フォーマットされた出力はやはり読みにくいかもしれません。
そのような場合は、コードを再編成するか単純化してください。ローカル変数名を短くしたり、式を新しいローカル変数に格納したりすることを検討してください。つまり、手作業でコードをフォーマットしているときと同じように、読みやすいように修正するのです。dartのフォーマットは、美しいコードを作るために、時には反復的に協力し合うパートナーシップのようなものだと考えてください。
80文字以上の行を避ける
リンター・ルール: lines_longer_than_80_chars
読みやすさの研究によると、長い行のテキストは読みにくい。これが、新聞や雑誌が複数段のテキストを使う理由です。
もし本当に80文字より長い行が必要だと感じたら、私たちの経験では、あなたのコードが冗長すぎる可能性があり、もう少しコンパクトにすることができます。その主な原因は、たいていVeryLongCamelCaseClassNamesです。その型名の各単語は、私に何か重要なことを伝えたり、名前の衝突を防いだりしているだろうか?もしそうでなければ、省略することを検討しよう。
dartフォーマットは、この99%はあなたのためにやってくれますが、最後の1%はあなた自身であることに注意してください。長い文字列リテラルを80カラムに収まるように分割することはできないので、手動で行う必要がある。
例外: URIやファイルパスがコメントや文字列の中にある場合(通常はインポートやエクスポートの中)、その行が80文字以上になったとしても、全体を残すことができます。これにより、パスのためにソースファイルを検索することが容易になります。
例外: 複数行の文字列は、改行が文字列内部で重要であり、行をより短いものに分割するとプログラムが変更される可能性があるため、80文字より長い行を含むことができます。
すべてのフロー制御文に中括弧を使用する
リンター・ルール: curly_braces_in_flow_control_structures
そうすることで、elseのぶら下がり問題を避けることができます。
例外: else句のないif文があり、if文全体が1行に収まる場合は、中括弧を省略することができます:
本文が次の行に折り返されている場合は、中括弧を使う:
まとめ
公式のEffective Dart: Styleの解説はこれで終わりです。仕事でimport
の書き方とか、普段見る_
と__
をつけて省略する理由や大文字で名前をつけるルールについて解説しました。
まあ、現場によっては文法のルールとかは他の言語をやってた人がその時の言語のルールを使ったりすることがあったり、元々ITじゃない会社だとマジックナンバーみたいな名前つけるので、ここまで徹底してる会社はソフトウェア作ってる大きい会社だけですね。
Discussion