Pythonの可読性を上げていくためのツールや手法
循環的複雑度 (Cyclomatic complexity)
循環的複雑度(サイクロマティック複雑度)とは、ソフトウェア測定法の一つであり、コードがどれぐらい複雑であるかをメソッド単位で数値にして表す指標。
基本的には分岐やループ処理が増えるに従い数値が増えていく。
複雑度が高ければ、コードは複雑でメンテナンスがしづらく、ユニットテストがしづらくなる。
Lizard
個人的には一番多機能でわかりやすく使いやすいツール。
$ pip install lizard
- 1-10 : シンプルで理解しやすく、テストも容易
- 11-20 : 若干複雑なコード
- 21-40 : 複雑なコードであり、完全に理解してテストを作成するのが困難
- 41以上 : 保守困難でありバグが確実に存在する
lizardの使い方の詳細は以下になる
Radon
radonというツールでも循環的複雑度を出すことができる。
$ radon cc -s ".\*.py"
Xenon
xenonというツールもある
認知的複雑度 (Cognitive Complexity)
人間にとっての理解のしづらさを元に複雑度を算出するが、算出方法の詳細は不明。
pythonではflake8-cognitive-complexity
というツールがある。
$ pip install flake8-cognitive-complexity
詳細は以下に書いてある
保守容易性指数(Maintainability Index)
名前の通り、保守のしやすさを指す指標。
100を最大値として、100に近いほど保守がしやすいということを表す。
radon
で計測することが可能になる。
詳細は以下になる。
具体的な算出方法などに関してはこちらに載っていた。
ハルステッド複雑度 (Halstead Complexity)
以下の3種類の指標が定義されている
- Volume : ボリューム
- Difficulty : 難易度
- Effort : 努力
今の所、pythonで使用できそうなツールは見つからない。
詳細は以下に書かれていた。
英語版のwikipediaしかなかった
flake8-expression-complexity
基準は不明だが、表現の複雑さを測定して警告を投げてくれるflake8拡張機能。
$ pip install flake8-expression-complexity
凝集度 (Cohesion)
あるコードがどれだけそのクラスの責任分担に集中しているかを示す尺度。
$ pip install cohesion
使い方
$ cohesion --files example.py --verbose
凝集度の解説はこちらになる。
CKメトリクス
- wmc
- lcom
- noc
- dit
- cbo
- rfc
WMC(Weighted Methods per Class)
計測対象クラスの重み付きメソッド数
LCOM(Lack of Cohesion of Methods)
計測対象クラスの凝集性の欠如
NOC(Number of Children)
計測対象クラスのサブクラス数
DIT(Depth of Inheritance Tree)
計測対象クラスの継承の深さ
CBO(Coupling Between Object Classes)
計測対象クラスに関係しているクラス数
RFC(Response for Class)
計測対象クラスに関係しているメッセージ数
flake8の拡張機能
flake8-bugbear
バグになりそうなコードを検知する
$ pip install flake8-bugbear
flake8-builtins
使用している変数や関数名が、組み込みオブジェクトの名前と被っていないかどうかをチェックする。
$ pip install flake8-builtins
flake8-eradicate
コメントアウトされているコードを見つけて警告する拡張機能
$ pip install flake8-eradicate
pep8-naming
変数や関数の命名がPEP8に準拠しているかどうかをチェックしてくれる
$ pip install pep8-naming
pep8-naming
変数や関数の命名がPEP8に準拠しているかどうかをチェックしてくれる
$ pip install pep8-naming
flake8-django
$ pip install flake8-django
Djangoを使ったコードのためにlinter
flake8-pytest-style
pytestに関するコードスタイルをチェックしてくれる
$ pip install flake8-pytest-style
flake8-isort
Pythonコードでのファイルのインポート順が以下にに準拠しているかをチェックできるFlake8のプラグイン。
$ pip install flake8-isort
出力されるエラーコードの一覧はこちらで確認できる。
flake8-quotes
Pythonコードでクォーテーションの利用がPEP 8
に従っているかチェックできるFlake8のプラグインです。
blackとの競合だけが心配。
$ pip install flake8-quotes
flake8-print
flake8-print
は、PythonコードのPrintステートメントをチェックできるFlake8のプラグイン。
print()
の不必要な使用をチェックしたい場合などに便利です。
$ pip install flake8-print
flake8-annotations
flake8-annotations
は、Pythonコードで関数が PEP 3107 -- Function Annotations と PEP 484 -- Type Hints に準拠しているかチェックできるFlake8のプラグインです。
関数アノテーション(引数の指定など)
が正しく行われているかをチェックしたい場合などに便利。
$ pip install flake8-annotations
出力されるエラーコードの一覧は flake8-annotations - Warnings で確認できます。
flake8-mypy
mypyによるPythonコードの静的な型チェックができるFlake8のプラグイン。
関数アノテーション(型の一致など)
が正しく行われているかをチェックしたい場合などに便利です。
$ pip install flake8-mypy
出力されるエラーコードの一覧はflake8-mypy - List of warnings で確認できます。
flake8-docstrings
Flake8にpydocstyleのルールを追加するプラグイン
pip install pydocstyle
したあとにflake8を呼び出すと、flake8に、pydocstyleのルールが追加される。
$ pip install flake8-docstrings
pycodestyle
Pythonコードのスタイルガイドを定めた文書であるPEP 8にコードが準拠しているかをチェックできるツール。
Flake8に既定のプラグインとして含まれています。かつてはpep8という名称だった。
$ pip install pycodestyle
pyflakes
pyflakes
は、Pythonコードの論理的なエラーをチェックできるツールです。
Flake8に既定のプラグインとして含まれている。
ソースを解析して、import
したけど使っていないモジュール、未使用の変数などを検出する。
pycodestyleとは違い、コードのスタイルについては分析せず、高速さに重点を置く。
Pylintよりも高速。
正しいコードを過ってエラーと報告しないように細心の注意
が払われており、解析はファイル単位で行われるので、import
で読み込むファイルにまたいだ解析はできない。
もっと詳しい分析が必要な場合は、Flake8
を使用する。
$ pip install pyflakes
hacking
Flake8
にOpenstack社のルール
を追加するプラグイン。
pip install hacking
したあとにflake8を呼び出すと、flake8にOpenstack
社が独自に追加したルールが追加される。
H
で始まる行が、flake8に追加された検出された項目になる。
$ pip install hacking
フォーマットツール
Flake8プラグインはコードチェックまでは行ってエラー箇所の判定
まではできますが、エラー箇所の自動修正
まで行いたい場合は別途"コードフォーマットツール"を使う必要がある。
isort
isortは、Pythonインポートをアルファベット順に並び替えるツールです。
$ pip install isort
isort
を実行してみる。
$ isort test_isort.py
Fixing /home/ec2-user/environment/test_isort.py
autopep8
autopep8
は、PEP 8スタイルガイドに準拠するようにPythonコードを自動的にフォーマットするツール。
$ pip install autopep8
--in-place
オプションを付けてautopep8を実行すると、ファイルのコードが実際にフォーマットされる。
$ autopep8 --in-place test_pycodestyle.py
autoflake
autoflake
は、未使用のインポート
や変数
をPythonコードから削除するツール。
$ pip install autoflake
リンター
静的コード解析ツールは、プログラムを実行せずに(=静的に)その内容を解析するツール。
同種のツールはリンター (linter) とも呼ばれる。
pylint
Pythonコードの静的解析を行うツールです。
flake8
では報告されなかった、変数名の規則違反や、意味のないコードを見つけてくれる。
最終行にこのコードの得点が表示される。
負の点数になることもあります。
$ pip install pylint
設定可能な項目が非常に多いため、以下のコマンドで設定ファイルを生成し、必要な項目を個別に設定する。
$ pylint --generate-rcfile > .pylintrc
pylint
には大量のチェック項目のリストが以下にある。
--rcfile
オプションで設定ファイルを指定することができる。
$ pylint --rcfile .pylintrc test_pylint.py
pylintにはプラグインもいくつかあり、Djangoのプラグインもある。
$ pip install pylint-django
--load-plugins
オプションでプラグインを読み込むことができる。
$ pylint --load-plugins=pylint_django test_pylint.py
以下にも詳しく書かれている。
pydocstyle
PEP 257で規定されているdocstring
(moduleや関数の最初に記される、"""と"""
で囲まれたコメントのこと)の書き方に違反する箇所を見つけてくれる。
以前までは "pep257" というツール名だったが、pydocstyle
に改名された。
docstringに関するエラーのみを指摘してくれる。
$ pip install pydocstyle
pyupgrade
Python の古い記述を新しい記述に更新してくれる。
$ pip install pyupgrade
以下はpre-commit
を使用している場合の設定方法です。
repos:
- repo: https://github.com/asottile/pyupgrade
rev: v3.9.0
hooks:
- id: pyupgrade
その他
cSpell
スペルチェックをしてくれるツールであり、日本人としてはかなりありがたいツールになるはずです。使用するには、npmが必要になります。
Pythonだけでなく、あらゆるプログラミング言語に対応しています。
$ npm install -g cspell
以下のように設定ファイルを作成します。
{
// Version of the setting file. Always 0.1
"version": "0.2",
// language - current active spelling language
"language": "en",
// words - list of words to be always considered correct
"words": [],
"ignoreWords": [],
// flagWords - list of words to be always considered incorrect
// This is useful for offensive words and common spelling errors.
// For example "hte" should be "the"
"flagWords": [
// "hte"
],
"allowCompoundWords": true,
"ignorePaths": []
}
$ cspell lint -c ./cspell.json "**/**.py"