開発ガイド

全モジュール共通の開発・保守ガイドラインです。 新しいモジュールを追加する際も、このガイドラインに従って実装してください。

開発環境セットアップ

必要なツール

  • Python 3.11+

  • pytest (テスト実行)

  • pygame (音声・グラフィック処理)

  • sphinx (ドキュメント生成)

環境構築

# 依存関係のインストール
pip install -r requirements.txt

# テスト実行(全モジュール)
python -m pytest test/

# 特定モジュールのテスト実行
python -m pytest test/common/config/
python -m pytest test/common/home/
python -m pytest test/common/save/

# ドキュメント生成
cd docs
make html

アーキテクチャ規約

3層構造の統一

全モジュールは以下の3層構造で実装:

common/{module_name}/
├── {function}.py              # Controller層
├── service/
│   └── {function}.py          # Service層
└── component/                 # Component層(必要に応じて)
    ├── {target}Validator.py   # バリデーション
    ├── {target}Manager.py     # リソース管理
    └── {target}Check.py       # 状態チェック

ファイル命名規則

レイヤー

ファイル名

Controller

{機能名}.py

action.py, display.py

Service

service/{機能名}.py

service/sound.py

Validator

component/{対象}RequestValidator.py

actionRequestValidator.py

Manager

component/{対象}{リソース}Manager.py

soundChannelManager.py

Check

component/{対象}{機能}Check.py

soundChannelCheck.py

クラス設計原則

  1. 単一責任原則: 1つのクラスは1つの責任のみ

  2. 依存関係逆転: 具象ではなく抽象に依存

  3. オープン・クローズド: 拡張に開いて修正に閉じる

# Good: 単一責任
class SoundChannelManager:
    """音声チャンネルの管理のみを行う"""
    def start(self): ...
    def stop(self): ...

# Good: バリデーションの分離
class RequestValidator:
    """リクエスト検証のみを行う"""
    def raise_if_invalid(self): ...

Request/Response パターン

全モジュール間の通信は統一されたパターンを使用:

# Request オブジェクト
@dataclass
class ModuleActionRequest:
    param1: bool
    param2: str
    param3: int

# Response オブジェクト
from common.layer.response.response import Response
from common.layer.code.code import Code

def process(request: ModuleActionRequest) -> Response:
    if valid_condition:
        return Response(data=result_data, result=Code.OK)
    else:
        return Response(data=error_data, result=Code.ARGUMENT_ERROR)

新モジュール追加手順

1. ディレクトリ構造作成

mkdir common/{new_module}
mkdir common/{new_module}/service
mkdir common/{new_module}/service/component  # 必要に応じて
mkdir test/common/{new_module}
mkdir test/common/{new_module}/service
mkdir test/common/{new_module}/service/component

2. 基本ファイル作成

Controller層の基本ファイル:

# common/{new_module}/action.py
from common.abstract.{new_module}.abstractAction import AbstractAction

class Action(AbstractAction):
    @staticmethod
    def execute(form, request):
        service = Service(request)
        result = service.execute()
        # フォームの更新処理

3. Service層の実装

# common/{new_module}/service/action.py
class Action:
    def __init__(self, request):
        self._request = request

    def execute(self):
        # ビジネスロジックの実装
        return Response(data=result, result=Code.OK)

4. テストファイル作成

# test/common/{new_module}/action_test.py
import unittest

class ActionTest(unittest.TestCase):
    def test_normal_case(self):
        # テスト実装
        pass

5. ドキュメント追加

# docs/modules/{new_module}_overview.rst
{MODULE}機能の概要
==================

概要
----

機能の概要説明

6. API参照に追加

docs/api/module_api.rst に新モジュールのautomodule定義を追加

テスト作成ガイド

テスト方針

  • 正常系: 期待される入力での動作確認

  • 異常系: エラー条件での例外処理確認

  • 境界値: 最小値・最大値での動作確認

テストファイル構成

test/common/{module}/
├── action_test.py                    # Controller層のテスト
├── display_test.py
├── sound_test.py
├── status_test.py
└── service/
    ├── action_test.py                # Service層のテスト
    └── component/
        ├── {target}_validator_test.py
        └── {target}_manager_test.py

共通テストテンプレート

# 例: test/common/config/status_test.py
import unittest
from common.config.service.status import Status

class StatusTest(unittest.TestCase):
    """
    Statusのテストクラス

    実際の実装時は、以下のようにモジュール名に合わせて変更:
    - インポート: from common.{モジュール}.service.{機能} import {クラス}
    - クラス名: {クラス}Test
    """

    def test_normal_case_returns_expected_result(self):
        """
        正常系: 正しい入力での期待結果確認
            - 条件: 有効な入力データ
            - 期待結果: 期待される戻り値
            - 例外: なし
        """
        # Arrange
        component = Status(valid_input)

        # Act
        result = component.execute()

        # Assert
        self.assertEqual(expected_result, result)

    def test_invalid_input_raises_value_error(self):
        """
        異常系: 無効な入力での例外発生確認
            - 条件: 無効な入力データ
            - 期待結果: ValueError例外が発生
            - 例外: ValueError
        """
        with self.assertRaises(ValueError):
            Status(invalid_input)

ドキュメント作成ガイド

ドキュメント構成

docs/
├── index.rst                    # メインページ
├── system_overview.rst          # システム全体概要
├── modules/                     # モジュール別概要
│   ├── config_overview.rst
│   ├── home_overview.rst
│   ├── save_overview.rst
│   ├── end_overview.rst
│   └── {new_module}_overview.rst
├── api/                         # API詳細仕様
│   └── module_api.rst
├── development_guide.rst        # 開発ガイド(本ファイル)
├── changelog.rst               # 変更履歴
└── diagrams/                   # フローチャート
    └── {module}/
        └── {function}_flow.md

ドキュメント規約

すべての公開クラス・メソッドには以下を記述:

def example_method(self, param: str) -> Response:
    """
    メソッドの概要を1行で記述。

    詳細な説明がある場合はここに記述する。

    .. dropdown:: 処理フロー図を確認する
       :color: primary
       :icon: eye

       .. mermaid:: /diagrams/{module}/{function}_flow.md
          :alt: 処理フロー図

    :param param: パラメータの説明
    :type param: str
    :return: 戻り値の説明
    :rtype: Response
    :raises ValueError: 例外が発生する条件の説明
    """

コード品質管理

静的解析

# コード品質チェック
flake8 common/{module}/
pylint common/{module}/

# 型チェック
mypy common/{module}/

継続的インテグレーション

全モジュールで以下を自動実行:

  1. 単体テスト実行

  2. 静的解析チェック

  3. ドキュメント生成確認

  4. テストカバレッジ測定

モジュール別注意点

CONFIG

  • 設定値の型チェックを厳密に

  • デフォルト値の適切な管理

  • 暗号化処理のテスト

HOME

  • UI操作のタイミング制御

  • 音声リソースの適切な管理

  • 画面遷移の状態管理

SAVE

  • データ整合性の確保

  • 暗号化・復号化の確実性

  • エラー時の復旧処理

END

  • リソース解放の完全性

  • 異常終了時の対応

  • ログ出力の適切な実装

トラブルシューティング

よくある問題と対処法

問題

対処法

インポートエラー

モジュールパス・__init__.py の確認

テスト失敗

モック設定とテストデータの見直し

ドキュメント生成失敗

automoduleのパス・構文確認

型エラー

型注釈の修正・mypy設定確認