VS Code コーディング規約を快適に守る

# 規約とツールでコードの品質を上げる
コーディング規約をチームで共有するとコードの可読性が上がる。
たとえば[**PEP8**](https://pep8-ja.readthedocs.io/ja/latest/)はPython標準ライブラリ用のコーディング規約で
1行の文字数を79文字以下とするなどその内容は多岐にわたる。

コーディング規約は学習・運用コストがかかるためLinter・Formatterなどのツールを有効活用したい。
以下、[Visual Studio Code（VS Code）](https://code.visualstudio.com/)用のお勧めの規約・ツールを導入する手順を示す。

## 概要
Linterツール [flake8](https://pypi.org/project/flake8/)、Formatterツール [autopep8](https://pypi.org/project/autopep8/)、
docstring支援の拡張機能[autoDocstring](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring)をインストールし、下の設定を行う。
前提としてMicrosoft公式の拡張機能[Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)は導入済みとする。

```json:setting.json抜粋
    "files.autoSave": "afterDelay",
    "files.autoSaveDelay": 1000,
    "python.linting.lintOnSave": true,
    "python.linting.pylintEnabled": false,
    "python.linting.pep8Enabled": false,
    "python.linting.flake8Enabled": true,
    "python.linting.flake8Args": [
        "--ignore=W293, W504",
        "--max-line-length=150",
        "--max-complexity=20"
    ],
    "python.formatting.provider": "autopep8",
    "python.formatting.autopep8Args": [
        "--aggressive", "--aggressive",
    ],
    "autoDocstring.docstringFormat": "google",
```

## Linter
Linterはコードを静的に解析し、コーディング規約に則っているかチェックするツール。
拡張機能[Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)導入済みならば標準で使える。
![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/191981/5cce4819-acde-e4f4-430f-4351e1def901.gif)
Linterを有効にすればコーディング規約違反のエラー・警告を表示してくれる。

### 導入方法
PEP8に加えて、論理エラーの検出も行う[flake8](https://pypi.org/project/flake8/)をインストール。
（論理エラーは「不要なimport」など）

```shell
pip install flake8 
```

ユーザー設定JSON（%AppData%\Code\User\settings.json）に下から取捨選択して追記する。

標準のpylintをオフにし、PEP8をオン。

```json
    "python.linting.pylintEnabled": false,
    "python.linting.flake8Enabled": true,    
```

1秒ごとに自動保存して、その度に構文チェック。

```json
    "files.autoSave": "afterDelay",
    "files.autoSaveDelay": 1000,
    "python.linting.lintOnSave": true,
```

空行に空白が含まれるとWarningになるW293は、エディタの自動インデントが引っかかるのでオフ。
+などのオペレータの後で改行するとWarningになるW504もオフ。

```json
    "python.linting.flake8Args": [
        "--ignore=W293, W504",
    ],
```

1行の最大文字数はデフォルト80文字（PEP8準拠）。
画面サイズなどにもよるためチームで相談して適宜設定する。

```json
    "python.linting.flake8Args": [
        "--max-line-length=150",
    ],
```

#### エラーの種別

- E\*\*\*: pep8の規約違反
    - 100系 ... インデント（indentation）
    - 200系 ... 空白（whitespace）
    - 300系 ... 空行（blank lines）
    - 400系 ... インポート（imports）
    - 500系 ... 行の長さ（line length）
    - 600系 ... 廃止予定（deprecation）
    - 700系 ... 文（statements）
    - 900系 ... 文法違反（syntax errors）
- W\*\*\*: pep8の警告
- F\*\*\*: PyFlakesの論理違反・警告

参考：[PythonソースがPEP8スタイルガイドに準じているかをpycodestyleで検査](https://arakan-pgm-ai.hatenablog.com/entry/2018/11/12/090000)

#### 循環的複雑度
循環的複雑度(Cyclomatic complexity)は分岐の多さを表す指標である。
具体的にはifやfor, switch caseの数+1。大きいほど可読性が下がり、テストケースが増える。
一般には25を越えると本人しか読めないコードになる。

flake8には関数ごとに循環的複雑度を警告するオプションがある。

```json
    "python.linting.flake8Args": [
        "--max-complexity=20"
    ],
```

### 使用方法
上の設定なら自動保存され、自動的にLinterが走る。
警告の抑制や変更を行う場合はチームで共有すること。

## Formatter
Formatterはコーディング規約に従うように整形（format）するツール。
拡張機能[Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)導入済みならば標準で使える。
![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/191981/c4a79837-d6ef-6d15-4637-4669e1c807c2.gif)

### 導入方法
[autopep8](https://pypi.org/project/autopep8/)をインストール。

```shell
pip install autopep8
```

ユーザー設定JSON（%AppData%\Code\User\settings.json）で下になっているのをチェック。

```json
    "python.formatting.provider": "autopep8",
```

標準では空白を調整するフォーマッティングしかしないが、setting.jsonに下を追記すると
`a == None` を `a is None` に書き換えるような、より積極的なフォーマッティングを行う。

```json
    "python.formatting.autopep8Args": [
        "--aggressive", "--aggressive",
    ],
```

上の設定はaggressiveを2回指定し、aggressiveレベル2にしている。

### 使用方法
選択範囲を右クリックして`選択範囲のフォーマット`など。

## docstring
関数などの説明をするdocstringのスタイルもプロジェクトで揃える必要があり
[autoDocstring](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring)というVS Codeの拡張機能をいれると運用しやすい。
参照に関しては、拡張機能[Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)導入済みなら標準でツールチップ表示してくれる。

```py:Googleスタイルのdocstring
def func(arg1, arg2):
    """Summary line.

    Extended description of function.

    Args:
        arg1 (int): Description of arg1

    Returns:
        bool: Description of return value
    """
    return True
```

### 導入方法
拡張機能[autoDocstring](https://marketplace.visualstudio.com/items?itemName=njpwerner.autodocstring)をインストール。

メニューの`ファイル` > `基本設定`  >  `設定` から `autoDocstring`で絞り込んで、
`Auto Docstring: Docstring Format`を`google`に変更。
![3785db13-7a1a-4aa4-a07b-d9d61baa7c5f-960x260r.png](https://qiita-image-store.s3.amazonaws.com/0/191981/78e139c2-bb31-1798-7606-d2f9a517160a.png)

### 使用方法
下のどれかの操作でdocstring生成。`tab`キーで次の項目に移る。

- `Ctrl + Shift + 2`キー
- `"""`を入力して`Enter`キー
- 右クリックして`Generate Docstring`

![demo.gif](https://qiita-image-store.s3.amazonaws.com/0/191981/b3e69908-99ba-e56a-da7f-e47c515d69fe.gif)

## その他
### 命名規則
Linterは命名規則をチェックしない。
言語的にも制約はないが、標準ライブラリとの整合性を考えるなら統一することが望ましい。
PEP8の命名規則はsnake_case、PascalCase、SNAKE_CASEの3種類である。

|対象|規則|備考|
|:---|:---|:---|
|パッケージ|snake_case | アンダースコアなしを推奨  |
|モジュール|snake_case | アンダースコアなしを推奨 |
|クラス    |PascalCase| |
|例外      |PascalCase | |
|クラス変数|PascalCase | |
|メソッド  |snake_case | 内部メソッドは頭にアンダースコア |
|引数      |snake_case | 予約語と被るときは末尾にアンダースコア |
|変数      |snake_case | 内部変数は頭にアンダースコア |
|定数      |SNAKE_CASE | |