Dartのlintルールに「discarded_futures」「unawaited_futures」というものがある。これらは元々、Futureをawaitしなかったことによる意図しないバグを防ぐ目的のルールで、意図的にFutureを捨てていることをunawaited関数でラップして明示するか、大人しくawaitするかのどちらかに強制できる。
しかし、Flutter側の設計に目を向けると、少数のユースケースのためにFutureを戻り値に設定している関数が大量に存在する。その一例がNavigator.push。このルールに従おうとすると、画面遷移のための関数呼び出しの大半をunawaitedでラップする必要がある。バグを防ぐためのlintが、大量のコードノイズを発生させてしまう。そこで、2025年頃に「@awaitNotRequired」アノテーションがmetaパッケージに追加され、これがついている関数の戻り値のFutureは捨てても怒られなくなった。現在のFlutterプロジェクトではこれらの関数にこのアノテーションを付ける作業が行われている。しかし、これではawaitすべきユースケースとすべきでないユースケースが区別できず、苦肉の策感は否めない。
私が思うに、それぞれのユースケースで関数を分けるべきだったと思う。例えば、voidを返すNavigator.push、Futureを返すNavigator.pushReturningというように。そうすれば、静的解析に余計な負荷をかけずに済むし、awaitすべき関数とそうでない関数を簡単に区別できる。
ただこれは大規模API変更になるので、今更受け入れられるかは微妙なところ。シグネチャーも二重で定義が必要になり、ボイラープレートが増える。今までの慣習や記事が古くなる。結構影響はデカい。探してもメソッド分割に関する議論は全く見当たらなかったが、Issueを出すかはかなり悩むところ。すでに追加されてしまった@awaitNotRequiredとの兼ね合いも(分割の方針を取るとこのアノテーションの存在意義が行方不明に)。
ということを、私のプロジェクトにこの2つのlintルールを追加してみて思ったところ。lintの方向性は正しいのにその周辺がクソなので、このプロジェクトでは結局元に戻そうと思う。