Djangoプロジェクトで設定しておくべきこと (4) コード品質チェック
前回の記事の続きです。
今回はDjangoプロジェクトのコード品質チェックの仕組みについて説明していきます。
コード品質チェック
皆さんの現場ではどのようにコードの品質をチェックしていますか。
おそらくは
コードレビュー
に頼っている現場が多いのではないでしょうか。
確かにコードレビューはプロダクトの品質を担保する大切な作業ですが、コードレビューの確認内容は
- 仕様が正しく実装されているか
- 適切なアルゴリズムが使われているか
の最小限に留めるべきです。
でないと、コードレビューは多くの時間を消費してしまいます。
スタートアップ企業でよく見られる光景に
読みやすい綺麗なコード
というビジネスに関係のない方向性を間違えたコードレビューをしているケースを見かけます。
しかし、「読みやすい綺麗なコード」のような数字で計測できない指標は、主観的な指摘になりがちで、あまり生産性の良い取り組みとは言えません。
では、客観的にコードの品質を保つにはどうするかというと
仕組みで解決
します。
つまり
- レビューアーの技量に依存させない
- 人間がやるプロセスはできるだけ削る
ようにします。
Djangoであれば以下の仕組みを構築します。
- flake8で文法チェック
- isortでimportの並び順を統一
- mypyで型をチェック
- radonでコードの質をチェック
- xeonでコード評価を取得
- unit testでモジュール単位をテスト
- E2Eテストでアプリ動作テスト
- 上記をgitHubActionで強制チェック
これらの設定は少しきつめにします。
上記のチェックと仕様確認のレビューが通っていれば、そこまで酷い品質のコードが出荷されることはありません。
では、順に各ツールの説明と設定方法を説明していきます。
1-1. flake8
Flake8はコードのスタイルをチェックするツールです。
設定ファイルはプロジェクトルートのsetup.cfgを利用することをおすすめします。
|--setup.cfg
設定は以下のように記載します。
[flake8]
exclude = build, migrations
max-line-length = 100
max-complexity = 10
上記の設定が反映されていることを以下のコマンドで確認します。
flake8
実行できれば成功です。
しかしこのままでは、実装するたびにflake8コマンドを手動で実行する必要があるので、VScodeでコード保存時に自動でflake8が実行されるように設定します。
それには.vscode/setting.jsonに
{
"editor.formatOnSave": true,
"python.linting.flake8Enabled": true
}
を追記します。
これでpythonファイルを保存するとflake8が実行されます。
1-2. isort
isortはインポート文をソートするツールです。
インストールして
isort .
を実行できれば成功です。
こちらもVScodeのコード保存時に自動実行できるように対応します。
.vscode/setting.jsonに以下を追加します。
{
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true
}
}
これでpythonファイルを保存するとisortが実行されます。
1-3. autopep8
autopep8はpythonのコードを自動フォーマットしてくれます。
pythonのコードは、
- autopep8で自動フォーマット
- flake8でチェック
- 手動で修正が必要な箇所の修正
という手順にするのが最も効率的です。
こちらもautopep8をinstallして、VScodeのコード保存時に対応します。
{
"editor.formatOnSave": true,
"python.formatting.autopep8Args": []
}
1-4. Radon
Radonはコードメトリクスを計測するツールです。
インストール後、以下のコマンドを実行します。
radon cc -nb -e "tests/*" .
引数のccは循環的複雑度を計測するように指定しています。
-nbは、複雑さのランクがB以上の結果のみを出力します。
ここではA以外のコードを出力します。
-eは、radonを実行しないフォルダを指定します。
ここでは、テストコードのメトリクスは測定してません。
こちらのツールは、VScodeのコード保存時に対応しません。
理由は、処理に時間がかかるので、保存のたびの実行すると開発効率が低下してしまうからです。
なので、makefileを用意して
metrics:
radon cc -nb -e "tests/*" .
とaliasを記載します。
こうしておけば
make metrics
とターミナルからコマンドを入力すれば複雑度が計測できます。
1-5. Xenon
Xenon(キセノン)はRadonの結果が失敗だった場合にゼロ以外の終了コードを返します。
つまり、
gutHubにpushするたびにgitHuActionでコードメトリクスを測定するために導入します。
こうすることで、プロジェクトメンバーにpythonの初心者がいても、強制的にコードのチェックが行われるので、一定以上の品質を満たしたコード以外はプロダクションコードに含まれなくなります。
実行はターミナルで
xenon --max-absolute A --max-modules A --max-average A .
と実行します。
こちらもRadonと同じく、VScode対応はしないほうが良いと思います。
makefileには
metrics:
radon cc -nb -e "tests/*" .
xenon --max-absolute A --max-modules A --max-average A .
と記載します。
これで
make metrics
とターミナルからコマンドを入力すればradonとxenonで複雑度が計測できます。
1-6. mypy
mypyはPythonで型チェックを行うライブラリです。
pythonの長所の一つとして、型チェック不要な手軽さが挙げられます。
なので、mypyはその長所を消してしまうライブラリともいえます。
なので、
小規模の開発でmypyの導入は不要
です。
中規模から大規模であれば導入する価値があります。
導入する場合は、ライブラリをインストール後、setup.cfgに以下を追記します。
[mypy]
python_version = 3.9
check_untyped_defs = True
disallow_any_generics = True
disallow_untyped_calls = True
disallow_untyped_decorators = True
ignore_errors = False
ignore_missing_imports = True
implicit_reexport = False
strict_optional = True
strict_equality = True
no_implicit_optional = True
warn_unused_ignores = True
warn_redundant_casts = True
warn_unused_configs = True
warn_unreachable = True
warn_no_return = True
plugins = mypy_django_plugin.main
[mypy.plugins.django-stubs]
django_settings_module = mysite.settings.production
[mypy-*.migrations.*]
ignore_errors = True
これで
mypy ${project_folder}/
とターミナルからコマンドを入力すればmypyが実行されます。
mypyはVScodeのコード保存時にも対応した方が良いです。
.vscode/setting.jsonに以下を追加します。
{
"editor.formatOnSave": true,
"python.linting.flake8Enabled": true,
"python.linting.mypyEnabled": true
}
これでpythonファイルを保存するとmypyが自動で実行されます。
まとめ
今回はDjangoコード品質チェックの設定について説明しました。
今回の記事の内容を実行すれば
- [×] flake8で文法チェック
- [×] isortでimportの並び順を統一
- [×] radonでコードの質をチェック
- [×] xeonでコードの質を担保できなければエラーにする
- [×] mypyで型をチェック
の設定ができるはずです。
ただ注意して欲しいのは
「やったほうが良い」はやらない。「やらなきゃいけない」のみやる。
を常に頭に入れておくことです。
プロジェクトを最も効率的にする方法は
- 削ること
- 減らすこと
です。
これはとても難しい仕事です。追加だけなら誰でもできます。
自分のプロジェクトに不要なら、ベストプラクティスでも取り入れる必要はありません。
無駄を最適化しても無駄に変わりはありません。
次の記事では
unit testの設定方法をお話しします。
Discussion