Style-guide-for-Flutter-repo の話。
ふと CONTRIBUTING.md を読んでたら見つけたのでメモ。
全部書くと長いので、個人的に厳選したものだけを簡潔に意訳してます。1
Flutter リポジトリの Style Guide
Getters feel faster than methods
プロパティのゲッターは効率的であるべき という話。
例えば、キャッシュしたり、オーダーに気を遣ったりしよう。
単純な処理じゃない場合はメソッドにしよう。
Web の話で言えば、document.forms
より document.getForms()
と書かれていてほしい。
Avoid complecting (braiding multiple concepts together)
各 API はそれぞれで完結しているべき という話。
だから、例えば Widget の child の型を見てどうこうするのは良くないよね。
Avoid APIs that encourage bad practices
良くない習慣を助長する API はやめよう という話。
コストの高い処理をするのであれば、それが API で表されているのがあるべき姿。
例えば Future や Stream を返そう。
Avoid exposing API oceans
大雑把に API を公開しちゃダメだよ という話。
例えば、 dart:ui
が Path.fromSVG()
を公開しないのは、Dart で直接実行するのと速度的には差がほぼないから。
そういうのを不用意に公開しないことで、保守,ドキュメント,テストなどの負担を減らせる。
Writing prompts for good documentation
良いドキュメントを残す時の観点はこういうのがあるよね という話。
[例1]
プロパティや引数の型について、議論すべき正常範囲外のケースがないかを検討しよう。 ex) null, 無限, NaN, 空
[例2]
クラスのメンバーについて、相互の影響について考えよう。例えば、他のある値が null の時だけ〇〇になる みたいなことはないか。
[例3]
ライフサイクルに気をつけよう。例えば、誰かが所有しているオブジェクトがあったとして、その dispose()
は誰が責任を持って呼ぶのか。
Provide sample code
サンプルコードあると嬉しいよね という話。
適切なフォーマットでサンプルを書く。
/// {@tool sample}
/// An infinite list of children:
///
/// ```dart
/// ListView.builder(
/// padding: EdgeInsets.all(8.0),
/// itemExtent: 20.0,
/// itemBuilder: (BuildContext context, int index) {
/// return Text('entry $index');
/// },
/// )
/// ```
/// {@end-tool}
class ListView { // ...
Use ///
for public-quality private documentation
public な API のコメントは必ず ///
だよね という話。
品質が十分でない private な API にだけ //
を使おう。
Dartdoc-specific requirements
Dartdoc に従ってドキュメント書こう という話。
/// Creates a foobar, which allows a baz to quux the bar.
///
/// The [bar] argument must not be null.
///
/// The `baz` argument must be greater than zero.
Foo({ this.bar, int baz }) : assert(bar != null), assert(baz > 0);
Use asserts liberally to enforce contracts and invariants
assert()
はデバッグモードでだけ有効なんだから、必要と感じたらどんどん入れていこう という話。
Prefer specialized functions, methods and constructors
読み手に意味を直接的に伝えられるメソッドを使おう という話。2
// BAD:
const EdgeInsets.TRBL(0.0, 8.0, 0.0, 8.0);
// GOOD:
const EdgeInsets.symmetric(horizontal: 8.0);
Have good hygiene when using temporary directories
一時ディレクトリはちゃんと管理しよう という話。
flutter_
で始まり、ピリオドで終わる一意の名前を付けよう(その後に自動生成されたランダムな文字列を続ける)。
あと、不要になったディレクトリはちゃんと綺麗に片付けること!
テストでは tryToDelete
を使おう。3
Perform dirty checks in setters
セッターで Dirty チェックをしよう という話。
Dirty チェックというのは、変更された値がアプリの他の箇所と同期されているかをチェックすること。
例えば、セットのタイミングで Dirty であることをマーキングしておくにはこんな感じで書く。
TheType get theProperty => _theProperty;
TheType _theProperty;
void set theProperty(TheType value) {
assert(value != null);
if (_theProperty == value)
return;
_theProperty = value;
markNeedsWhatever(); // the method to mark the object dirty
}
Common boilerplates for operator ==
and hashCode
operator ==
と hashCode
をオーバーライドする時はこう書こう という話。
@override
bool operator ==(Object other) {
if (other.runtimeType != runtimeType)
return false;
final Foo typedOther = other;
return typedOther.bar == bar
&& typedOther.baz == baz
&& typedOther.quux == quux;
}
@override
int get hashCode => hashValues(bar, baz, quux);
オブジェクトがたくさんプロパティを持つなら、operator ==
を頭に置くことも検討しよう。
Override toString
toString
をオーバーライドしてデバッグに使うよりも、Diagnosticable
を使おう という話。
devtools や IDEでの調査も捗る。
Prefer naming the argument to a setter value
特に理由がない限りセッターの引数は value
にしよう という話。
おわりに
driver test まわりの挙動に色々疑問があってソース追いかけていたのに、いつの間にか Style Guilde 読んでた...
-
中には
analysis_options.yaml
に書いておけばいいだけのものもあるので設定大事。 ↩ -
それっぽいメソッドが生えてないかドキュメントを逐次確認するのが大切ってことですね。 ↩
-
例えばこんな感じにね! flutter_tools/test/integration/flutter_run_test.dart#L29 ↩