🐩

Djangoプロジェクトで設定しておくべきこと (4) コード品質チェック

2021/10/04に公開

前回の記事の続きです。

https://zenn.dev/masa0317/articles/06eeb50f2f4d09

今回は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