【社内勉強会③】Linter, Formatterについて

# Linterとは
Linterは、ソースコードを解析して、潜在的なバグの検出や、規定されたルール[^1]に沿ってコードが書かれているかをチェックする静的解析ツールの1つです。

***

# Formatterとは
Formatterは、コードのスタイルをチェックし、規定されたルール[^1]に基づいてコードを整形するツールです。

***

# Linter、Formatterを利用するメリット

**1. コードの品質向上**
Linterは、潜在的なバグや不適切なコーディングスタイルを検出し、それらを修正することでコードの品質を向上させます。

**2. 一貫性のあるコーディングスタイル**
Formatterは、一貫性のあるコーディングスタイルを強制します。
それにより開発者間でのコードスタイルのばらつきがなくなり、コードの可読性と保守性が向上します。

**3. 自動化と効率化**
LinterとFormatterは自動化可能なため、CI/CDパイプライン等の開発サイクルの中に組み込む事で、開発者が手動でスタイルチェックやバグ検出を行う必要がなくなります。これにより、開発者はより重要なタスクに集中することができます。

***

# PythonのLinter、Formatterツール

## Linter

### Pylint
Pythonファイルに対して、PEP8[^2]に準拠しているか様々なチェックを行います。例えば、変数名や関数名の命名規則やコードのフォーマット、未使用の変数やインポート文などが含まれます。

***

### pycodestyle(旧pep8)
PythonのコードがPEP8[^2]に準拠しているかをチェックするためのlinterです。

### pyflakes
pycodestyleとは違い、コードスタイルについては一切チェックせず、未使用のimport文や変数などの、pycodestyleには検出できない論理的なエラーのみを検出します。ソースファイルを解析し、さまざまなエラーを検出します。ソースファイルをインポートせずに解析するため、副作用のあるモジュールでも安全に使用できます。

### mccabe
循環的複雑度（Cyclomatic Complexity）というソフトウェア測定法を開発したThomas McCabeが名前の由来です。循環的複雑度は、ソフトウェアの複雑さを測定するための指標であり、プログラムの制御フローグラフ上で取りうる経路数の下限を示します。この値が大きいほど、テストケースが多く必要になります。
デフォルトではオフになっています。

### ★Flake8
上記の3つのlintツールをまとめたラッパーです。

***

## Formatter

### autopep8
PEP8コーディングスタイルに準拠したPythonのコードフォーマッターです。VSCodeのデフォルトのFormatterでもあります。特徴としては、--aggressiveオプションの数によって強さが変わることです。

### yapf
Googleが開発したオープンソースのFormatterです。カスタマイズ性が高く、多くの項目を設定できます。例えば、コードスタイルをpycodestyleやgoogleスタイルに変更することが可能です。

### ★black
他のフォーマッターよりも制限が厳しく、設定できるオプションがかなり少ないですが、設定に頭を悩まされる必要がなく、細かいスタイルまで統一してくれます。

### ★isort
import文をアルファベット順に並べ替えたり、セクションやタイプ別に自動的に分けたりするツールです。

***

# VSCodeでLinter、Formatterを利用する
ここでは、Linterとして**flake8**を、Formatterとして**black**を使用することを前提としています。

1. Flake8、black、isortをインポート
```bash
pip install flake8 black isort
```

***

2. 拡張機能をインストールする
- Python
![Python](https://storage.googleapis.com/zenn-user-upload/d0a4e886e6f1-20231026.png)

- Flake8
![Flake8](https://storage.googleapis.com/zenn-user-upload/5f968c5a5039-20231026.png)

- black
![black](https://storage.googleapis.com/zenn-user-upload/52ffe52ee821-20231026.png)

- isort
![isort](https://storage.googleapis.com/zenn-user-upload/b0f5f4fc7a5d-20231026.png)

***

3. プロジェクトルートフォルダに`.vscode`フォルダを作成し、その中に以下の`settings.json`を配置します。
```json:settings.json
{
    "[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        },
    },
    "python.linting.lintOnSave": true,
    "python.linting.flake8Enabled": true,
    "python.linting.flake8Args": [
        "--max-line-length=88",
        "--extend-ignore=E203,W503",
    ],
    "isort.args": [
        "--profile",
        "black"
    ],
    "flake8.args": [
        "--max-line-length=88",
        "--extend-ignore=E203,W503",
    ],
}
```

***

デフォルトのフォーマッターとして**black**を設定し、保存時に自動的にフォーマットしたり、import文を整理するように設定しています。
```json
"[python]": {
        "editor.defaultFormatter": "ms-python.black-formatter",
        "editor.formatOnSave": true,
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        },
},
```

***

Pythonファイルを保存するたびに自動的にLintを実行するように設定しています。
また、Flake8を有効にし、Flake8の引数を設定しています。ここでは、blackと競合しないよう、行の最大長を88に設定し、E203とW503を無視するように設定しています。
```json
"python.linting.lintOnSave": true,
    "python.linting.flake8Enabled": true,
    "python.linting.flake8Args": [
        "--max-line-length=88",
        "--extend-ignore=E203,W503",
    ],
```

***

isortの引数を設定しています。ここでは、blackプロファイルを使用するように設定しています。
```json
"isort.args": [
	"--profile",
        "black"
],
```

***

Flake8の引数を設定しています。ここでも、blackと競合しないよう、行の最大長を88に設定し、E203とW503を無視するように設定しています。
```json
"flake8.args": [
        "--max-line-length=88",
        "--extend-ignore=E203,W503",
],
```

***

[^1]:コードを記述する際のルールは「コーディング規約」としてまとめられていることが一般的です
[^2]:https://peps.python.org/pep-0008/