Dart/Flutter の静的解析強化のススメ

プロジェクトには analysis_options.yaml を常に配置して静的解析を厳しくすることを強くお勧め

mono 
Flutter 🇯🇵
12 min readOct 8, 2019

--

TL;DR

特にFlutterアプリの場合は、手っ取り早く強め(Flutter推奨 + α)に静的解析強化したいときには以下がお勧めです。

1. インストール

pedantic_mono パッケージをインストール。

dev_dependencies:
pedantic_mono: any

2. analysis_options.yamlの配置

https://github.com/mono0926/pedantic_mono/blob/master/example/analysis_options.yaml をプロジェクトのルートに置く。

analysis_options.yaml とは

それでは、以下もう少し詳しく補足していきます。

Dart/Flutterプロジェクトでは、analysis_options.yamlを設定することでその記述内容に応じて静的解析をかけてくれるようになります。

静的解析により問題が見つかった場合、Android Studio・Visual Studio Codeではそれぞれ次のように出力されます。

Android Studio での出力例
Visual Studio Codeでの出力例

そもそも静的解析とは?

Dartはデフォルトだと、最低限の型チェックのみで型の扱いが比較的緩めです。また、書き方の揺れも厳しく指摘されることはありません。

一方、静的解析のルールを指定して厳しめにしていくと以下のような状態に寄せていくことができます。

  • 事前の型チェックが厳密になる
  • 統一的なコーディングスタイルが強制される
  • ベターな振る舞いとなるようなコードに誘導される( const 指定など)

厳しめにすると人によっては煩わしく感じられるかもしれませんが、僕は基本的には厳しめが好みです。ルールによってはコード量が少しだけ増えることもありますが、それ以上に堅牢なコードとなるメリットの方が遥かに大きいと感じているからです。また、特にそういったトレードオフなどもなくメリットだけ享受できるルールが大半だとも思います。

Lintルールはこちらに一覧されています。

Dart/Flutterの新規プロジェクトを作ったら、まず初めにプロジェクトルートに適切なルール定義をした analysis_options.yaml を置いて静的解析を厳しくするのが良いと思っています。

これまでこの設定を端折ってしまった時には、厳しく設定した analysis_options.yaml があればコーディング中に気付けたであろうミスの発見が実行時にまで遅れたり、場合によってはエラーログなども出てくれずなかなか原因が分からずハマることさえありました。こういう不毛な時間は極力避けたいものです。

途中から導入したり厳しくすると無駄な作業を強いられる

けっこうありがちですが、途中から導入したり厳しくすると一気に大量の警告やエラーが発生してその対応に多くの時間が必要になります。あるいは、その大量の指摘に怯んで本来設定したいルールを追加できず、水面下でコードの状態がどんどん悪化していくのを見て見ぬふりしながら開発せざるを得なくなるかもしれません。

初めから導入してきちんと守ると、大きなコストをかけずにコードの状態を常に健全に保つことができます。

analysis_options.yaml が活用されてないことが散見される問題の解決

個人的には、最近はプロジェクト作成後、常にanalysis_options.yamlを設置するのが習慣化していますが、特にFlutter歴がまだ短い開発者のプロジェクトだとそれが無かったりかなり緩いルールだったりすることが散見されて気になっていました。

主に、以下の理由によるものだと思います。

  • そもそも、analysis_options.yaml の存在を知らない
  • 知っていてもうっかり忘れたり設置が手間だったりでサボってしまう
  • どういうルール定義にすれば良いのか分からない

設置の簡単なpedantic_monoパッケージを作成

この課題の解決のため、pedantic_mono パッケージをインストールして1ファイルコピペするだけで設置できるように整えました。その手順が冒頭のTL;DRに書いた内容です。個人的にもサンプルなどでよく新規プロジェクトを作るので、常に一貫したルールを手間なく追加できるようにしたいという意図もありました。

pedantic_monoパッケージには、公式のpedantic最新ルール + Flutterサンプルリポジトリなどのルールで設定されているものはすべて取り入れてある

自分の好みを押し付けることはなるべく避けたく、基本的にはFlutterプロジェクトとして標準とされているであろうスタイルに寄せるべきだと考えています。特に緩くする方向の調整は原則しない方が良いと思っています。

Flutter公式サンプルのanalysis_options.yaml がスタンダードなものとして真似るのに適しているというのが今の自分の考えです。

内容的にも、strong-modeで暗黙的な振る舞いが禁止されたけっこう厳しめのものとなっていて、つまらないコーディングミスを防ぐのに良いルールで自分好みでもあります。

また、Flutterアプリのためのルールとしては、通常のDartプロジェクトやFlutterフレームワークなどが必ずしも適しているわけではなく、Flutterアプリのプロジェクトに付随するルールが最適だと考えています。このため、Flutterフレームワーク付随のものではなくflutter/samples で指定されているルールには全て従うように設定しました。

さらに errors の項目については、以下も参考にして、missing_required_parammissing_returnwarning 扱いにする調整もしました。

左: デフォルト | 右: 調整後

@required にしている引数漏れの指摘がデフォルトが hintレベルでさりげないために見落としがちという声をたまに聞いてましたが、warningに引き上げた後では右のように見やすく気付きやすくなります。errorにすることもできますが、そうするとコード変更途中に動かせなくなって取り回ししにくいのでwarningくらいがちょうど良いと思います。

このような感じに、プロジェクトごとに良い塩梅に取り入れるルールを調整していくのが一般的だと思いますが、その調整した結果を簡単に使い回せると複数プロジェクトへの導入・追従が楽になるため、今回 pedantic_monoとしてパッケージ化しました。

細かいルールをたくさん追加してさらに厳しく改変してある

自分の好みを押し付けることはなるべく避けたく、基本的にはFlutterプロジェクトとして標準とされているであろうスタイルに寄せるべきだと考えています。

こう書いたものの、pedantic_mono は flutter/samples などで指定されたルールにはすべて従った上でさらにルールをたくさん追加してしまっています。自分がこれまでGitHubなどで読んできたソースや過去携わったいくつかのプロジェクト経験から、Flutterアプリプロジェクトとして比較的広く受け入れられているルールの範疇であるとは思っていますが、もし合わないものがあれば pedantic_mono を使わずに自分なりに納得できるものを選択するのが良いと思います。pedantic_monoは個人的にはお勧めしたい設定になっているものの、本記事の主旨は以下であり、パッケージ自体の布教は特に目的としていません。

  • 厳しめの analysis_options.yaml の布教
  • ルールをパッケージ化すると統一的に使い回せて便利

一応、 analysis_options.yaml の中身を以下のようにパッケージ推奨のものから変えると、https://github.com/flutter/samples/blob/master/animations/analysis_options.yaml に沿ったルールになって、従うべきLintルールを減らすことも可能な作りにもなっています。

# パッケージのREADMEに記載のデフォルトはこちらの厳しいルール
# include: package:pedantic_mono/analysis_options.yaml
# こちらの指定に変えると、従うべきLintルールが減る
include: package:pedantic_mono/analysis_options_flutter_samples.yaml

まとめると、やり方自体は以下のいずれでも良いですが、そのプロジェクトに適切なanalysis_options.yamlを設定することを強くお勧めします。

  • 簡単に済ませるなら、pedantic_mono パッケージ利用 (特に強めに縛るのが好きな人にはお勧め)
  • pedantic + 好みの追加ルール
  • pedantic 使わずにゼロから好みのルールを設定

providerパッケージなどの作者の Remi Rousselet さんが以下の記事のStep 2以降で同様のことが書かれていて、この併読もお勧めです。

include したルール群の中に採用したくないルールがあった時に、それだけ無効化する書き方も紹介されてい流ので、例えば pedantic_mono パッケージを採用しつつも一部無効化したい時に参考になります。

Explicitly disable only the rules we do not want

[追記 2020/08] 他の類似パッケージの紹介

最近知りましたが、同時期にこれらの類似パッケージが登場していました。最もしっくり来るもの + アレンジして使うのが良いと思います。個人的には、 pedantic_mono を自分のしっくり来るものとして最新Lintルールを早めに取り入れながら育てていくつもりです。

--

--