Newer
Older
RobotCar / docs / 01_GUIDE / GUIDE_04_コーディング規則.txt
========================================================================
Python コーディング規則 (Python Coding Style Guide)
========================================================================

1. 基本方針 (Basic Policy)
------------------------------------------------------------------------
PEP 8 を基本とし,チーム内での一貫性を最優先とする.
本規則に明記されていない事項は PEP 8 に従う.
※ 書式・記述スタイルの基準は `GUIDE_01_ドキュメント作成ガイド.txt` を参照する.


2. フォーマット (Formatting)
------------------------------------------------------------------------

2-1. インデント
    ・半角スペース4つを使用する.タブ文字は使用しない.
    ・継続行は,開き括弧に揃えるか,ハンギングインデント(スペース4つ追加)とする.
    ・例:

        # 開き括弧に揃える
        result = some_function(arg_one, arg_two,
                               arg_three, arg_four)

        # ハンギングインデント
        result = some_function(
            arg_one, arg_two,
            arg_three, arg_four,
        )

2-2. 1行の最大文字数
    ・79文字を上限とする(PEP 8 準拠).
    ・文字列やコメントが長くなる場合は,括弧による暗黙の行継続を優先する.
    ・バックスラッシュ `\` による行継続は極力避ける.

2-3. 空行
    ・トップレベルの関数・クラス定義の間: 2行空ける.
    ・クラス内のメソッド定義の間: 1行空ける.
    ・関数内の論理的なまとまりの区切り: 1行空ける(使いすぎに注意).

2-4. 文字コード
    ・UTF-8 を使用する.
    ・エンコーディング宣言(`# -*- coding: utf-8 -*-`)は Python 3 では不要.


3. 命名規則 (Naming Conventions)
------------------------------------------------------------------------

3-1. 一覧

    ■ 変数・関数・メソッド・引数
    ・スタイル: snake_case
    ・例: `motor_speed`,`calc_distance`,`handle_input`

    ■ 定数
    ・スタイル: UPPER_SNAKE_CASE
    ・例: `MAX_SPEED`,`DEFAULT_PORT`,`PIN_MOTOR_LEFT`

    ■ クラス
    ・スタイル: PascalCase
    ・例: `MotorController`,`SensorReader`,`UltrasonicSensor`

    ■ モジュール(ファイル名)
    ・スタイル: snake_case
    ・例: `motor_controller.py`,`sensor_reader.py`

    ■ パッケージ(ディレクトリ名)
    ・スタイル: 全て小文字,アンダースコアなし(短い名前を推奨)
    ・例: `drivers`,`utils`,`config`

    ■ プライベート
    ・先頭にアンダースコア1つを付与する.
    ・例: `_internal_value`,`_calc_raw_data`

3-2. 命名の原則
    ・意味のある名前を付け,略語は最小限にする.
        - NG: `d`,`tmp`,`val`,`calc`(単体で使用)
        - OK: `distance`,`temperature`,`motor_value`
    ・ループカウンタ等,スコープが極めて狭い場合のみ `i`,`j`,`x`,`y` を許容する.
    ・bool 型の変数は `is_`,`has_`,`can_` 等の接頭辞を付ける.
        - 例: `is_connected`,`has_obstacle`,`can_move`


4. import の規則 (Import Rules)
------------------------------------------------------------------------

4-1. 順序
    以下の順序で記述し,グループ間に1行空ける.

    1. 標準ライブラリ(`os`,`sys`,`time` 等)
    2. サードパーティライブラリ(`RPi.GPIO`,`numpy` 等)
    3. プロジェクト内モジュール

    ・例:

        import os
        import sys
        import time

        import RPi.GPIO as GPIO

        from drivers.motor import MotorController
        from sensors.ultrasonic import UltrasonicSensor

4-2. スタイル
    ・1行に1モジュールを記述する.
        - NG: `import os, sys`
        - OK: `import os` と `import sys` を別行に記述
    ・`from ... import *` は禁止する(名前空間の汚染を防ぐ).
    ・`from ... import` で複数の名前を取り込む場合は括弧でまとめる.

        from sensors.ultrasonic import (
            UltrasonicSensor,
            TRIGGER_PIN,
            ECHO_PIN,
        )


5. 型ヒント (Type Hints)
------------------------------------------------------------------------

5-1. 方針
    ・関数の引数と返り値には型ヒントを付与する.
    ・ローカル変数への型ヒントは,型が自明でない場合のみ付与する.

5-2. 書式
    ・Python 3.10 以降の記法(`X | None`,`list[int]`)を使用する.
    ・例:

        def calc_distance(speed: float, duration: float) -> float:
            return speed * duration

        def find_obstacle(sensors: list[UltrasonicSensor]) -> int | None:
            ...


6. コーディングルール (Coding Rules)
------------------------------------------------------------------------

6-1. 比較
    ・`None` との比較は `is` / `is not` を使用する.
        - NG: `if value == None:`
        - OK: `if value is None:`
    ・bool 値との比較は暗黙的に行う.
        - NG: `if is_active == True:`
        - OK: `if is_active:`

6-2. 文字列
    ・引用符はダブルクォート `"` で統一する.
    ・文字列の組み立てには f-string を使用する.
        - NG: `"Speed: " + str(speed)`
        - OK: `f"Speed: {speed}"`

6-3. 例外処理
    ・裸の `except:` は禁止する.必ず例外クラスを指定する.
        - NG: `except:`
        - OK: `except ValueError:`
    ・`except Exception` も極力避け,具体的な例外を捕捉する.

6-4. with 文
    ・ファイル操作や GPIO のクリーンアップなど,リソース管理には `with` 文を使用する.
    ・例:

        with open("config.json", "r") as f:
            config = json.load(f)

6-5. マジックナンバーの禁止
    ・意味のある数値は定数として定義する.
        - NG: `time.sleep(0.5)`
        - OK:
            SENSOR_INTERVAL_SEC = 0.5
            time.sleep(SENSOR_INTERVAL_SEC)


7. ファイル構成 (File Structure)
------------------------------------------------------------------------
1つの Python ファイル内は,以下の順序で記述する.

    1. ファイルドキュメント(docstring)
    2. import 文
    3. 定数定義
    4. クラス定義 / 関数定義
    5. `if __name__ == "__main__":` ブロック(必要な場合のみ)

・例:

    """
    motor_controller
    モーターの制御を担当するモジュール
    """

    import time

    import RPi.GPIO as GPIO

    from config.pins import PIN_MOTOR_LEFT, PIN_MOTOR_RIGHT

    MAX_SPEED = 100
    DEFAULT_SPEED = 50


    class MotorController:
        """左右のモーターを制御するクラス"""

        def __init__(self, left_pin: int, right_pin: int) -> None:
            ...

        def forward(self, speed: int = DEFAULT_SPEED) -> None:
            ...


    if __name__ == "__main__":
        controller = MotorController(PIN_MOTOR_LEFT, PIN_MOTOR_RIGHT)
        controller.forward()


8. ツール設定 (Tooling)
------------------------------------------------------------------------
コードの品質を自動で維持するため,以下のツールの導入を推奨する.

■ フォーマッター
・black: コードの自動整形に使用する.
    - 1行の最大文字数は 79 に設定する.

■ リンター
・flake8 または ruff: スタイル違反や潜在的なバグを検出する.

■ 型チェッカー
・mypy: 型ヒントの整合性を静的に検証する.

※ ツールの具体的な設定や導入手順は `ENV_` カテゴリのドキュメントに記載する.