[Flutter] Linter選定と、厳しめにするメリットとは??
今回、Flutter(Dart)のプロジェクトでLinterの調査を行い、厳しめのルールを適用した経験をもとに、学びを共有しようと思います。特に、これからLinterを強化しようと考えている方のイメージ構築に役立てばいいなとおもいます!
こんな人におすすめ
・デフォルトのLinterしか使ったことがない。
・Linterの種類が多すぎて選定に迷っている。
・Linterを強めたらどうなるのか、効果や実際の経験を知りたい。
Linter Packages
Flutter のプロジェクトを作成すると デフォルトで flutter_lintsが適用されています。
デフォルトのLinter以外にも、プロジェクトのニーズに合ったLinterパッケージを選定することが可能です。
そのため、まずはどのようなLinterパッケージが存在するのかを知ることが重要です。以下のリンクを参考に、Linterパッケージを見てみると面白いです。
Linter rules
Dartで使用できるLintルールの一覧は、以下のリンクで確認できます。
どんな基準で選んだのか
すべてのLinterを持ってくるという選択肢もありでしたが、少々冗長に感じられたため、OSSで用いらているようなパッケージで、厳しいものという条件で探しました。
結論、very_good_analysis
を用いることにしました。
理由
- Pub Likesが多くの開発者に支持されている。
- GitHubが、継続的にメンテナンスされているため、信頼性が高く、最新のDartやFlutterの更新にも対応している。
- 採用されてるルールが全Linterルールの8割以上をカバーしており、広範なコーディングスタイルに対応できる。
なぜ厳しいものから選んだかというと、好みに合わなければ、その設定を個別で省いていけばいいからです。
厳しめ → 徐々に緩める って感じの方針です。
結論。厳しめにしたらどうなったか?
既にある程度進行しているプロジェクトに厳しめのLintルールを適用すると、Linterから大量の警告が出ることになります。しかし、Linterを使ってコードの品質をチェックする習慣がつくと、コードの統一感が増し、バグも減り、プロジェクト全体の品質が大幅に向上します。
それに加えて、厳しいLint設定でも、VSCodeのsettings.json
やeditorconfig
を活用することで、自動化されたフォーマットや修正が可能になり、コーディング作業も効率化されます。これらのツールの設定をしっかり行うことが、厳しめのLint設定を実装する上で必須です。
導入後のイメージ
全部を紹介するのは、数が多すぎるので、数個をピックアップします。
『こんな感じで警告がでて修正していくんだろうな。。。』
とイメージしていただければ幸いです。
⭐️バグの予測が可能になる
unawaited_futures
Future を待たずに処理を続行すると予期しない動作になる可能性があるため、await を忘れずに使用することを推奨します。
before
FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
after
await FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);
use_build_context_synchronously
このLintルールは、非同期処理中にBuildContextを使用する際、ウィジェットがアンマウントされている可能性がある場合に警告を出します。非同期処理で時間がかかっている間に画面が変更されると、contextが不安定になり、アプリがクラッシュする原因となることがあります。このルールは、そのようなケースを防ぐために、BuildContextを安全に使用するよう促します。
before
onPressed: () async {
await Future<void>.delayed(const Duration(seconds: 1));
Navigator.of(context).pop();
},
after
onPressed: () async {
await Future<void>.delayed(const Duration(seconds: 1));
if (context.mounted) { ← 追加
Navigator.of(context).pop();
}
},
cancel_subscriptions
例えば、以下の定義があった場合、disposeされるような設定がないとメモリリークを引き起こします。
StreamSubscription<int>? _subscription;
以下を追加すると警告が消えます。
@override
void dispose() {
// ウィジェットが破棄されるときに購読をキャンセルする
_subscription?.cancel();
super.dispose();
}
⭐️チームで一貫したコーディングスタイルになる
eol_at_end_of_file
ファイルの末尾に改行を追加することを推奨します。これにより、POSIX標準に準拠した形式になります。
こちらは、editorconfigや vscodeのsetting.jsonの設定を導入するといいかと思います。
prefer_const_constructors
定数コンストラクタが使用できる場合、それを使用することを推奨します。コンストラクタに const を追加することでパフォーマンスが向上します。
before
final _patrolTesterConfig = PatrolTesterConfig();
after
const _patrolTesterConfig = PatrolTesterConfig();
always_put_required_named_parameters_first
必須の名前付きパラメータを常に他の任意のパラメータよりも先に置くことを推奨します。これにより、コードの読みやすさや保守性が向上します。
before
void exampleFunction({
String? optionalParam,
required String requiredParam}) {
}
after
void exampleFunction({
required String requiredParam,
String? optionalParam}){
}
気に入らないLintルールは外そう
実際に使っていき、いくつかは合わないなと感じたので以下のように、linterの設定が適用されないようにしました。
include: package:very_good_analysis/analysis_options.yaml
analyzer:
errors:
invalid_annotation_target: ignore
exclude:
- "**/*.freezed.dart"
- "**/*.g.dart"
- "**/*.mocks.dart" ....
linter:
rules:
public_member_api_docs: false
no_default_cases: false
one_member_abstracts: false
.....
public_member_api_docs
抽象クラスやパブリックメンバーを定義したときに、///
を使ってドキュメントコメントを書くことを強制する警告です。
こちらのルールは、外す人が多いのではないかと感じています。
no_default_cases
このルールは、switch 文で default ケースを避け、すべての可能なケースを明示的に列挙することを推奨するものです。
しかし、switch文に default ケースを追加する方が好ましい場合があり、個人的な好みでこのルールは無効にしています。
※ これらのルールは、プロジェクトやチームの方針に合わせてカスタマイズし、柔軟に適用することが重要です。チーム全体の合意を得ながら、オリジナルのLint設定を調整していきます。
部分的にLinterの設定を無効化する
特定の行だけでLinterの警告を無効化するには、ignore コメントを使います。例えば、print 文の使用を許可する場合、以下のように設定します。
// ignore: avoid_print
print("This is a debug message");
このように、ignore を使うことで、特定のコードに対してLintの警告を無効化し、柔軟に対応できます。
ここでこの警告はいらないなってときに、活用しましょう。
vscodeのsetting.jsonを活用する
不要インポートを削除してくれたり、フォーマットや簡単な修正を行なってくれます。
こちらは、vscodeを使っているなら開発効率がぐんと伸びます。
"editor.codeActionsOnSave": {
"quickfix.insertSemicolon": "always",
"source.organizeImports": "always",
"source.addMissingImports": "always",
"source.fixAll": "always"
}
"editor.formatOnSave": true,
"editor.formatOnType": true,
"editor.formatOnPaste": true,
"editor.rulers": [
80
],
flutter analyze
を実行する
PR提出時に GitHub Actionsで PR時に flutter analyze
を実行し、その結果を Danger でPRにコメントするようにしています。
これにより、Linterのエラーを簡単に確認できる仕組みを整えています。
例えば、コード内で一箇所だけ const を抜かしてみた場合、以下の警告が出ます。
$ flutter analyze
Analyzing melos_starter...
info • Use 'const' with the constructor to improve performance ...
1 issue found. (ran in 3.6s)
この結果を、GitHubのPRに自動的にコメントとして投稿します。
これにより、手間をかけずにLinterエラーを確認でき、レビュー作業がスムーズになります。
詳しい設定方法は、こちらの記事が参考になりましたので、ご紹介します。
最後に
やはり、コーディングルールが統一されていると、書き方が統一されて品質が向上します。
その結果、警告に注意を払うようになり、コードの見た目がよくなっていきます。
個人的には、厳しめが好みですが、プロジェクトのメンバーと相談してみんなが書きやすいルールにしていこうと考えました!
Discussion