アーキテクチャとエンジニアリングガイド
コードの置き場所、依存関係の追加、配布アセットの変更を判断するときに使います。 実行手順とトラブル対応は開発ガイドを参照してください。
既定の設計
1つのインストール可能なパッケージと、薄いアプリケーション境界で構成します。
CLI(Typer、設定、ログ) -> コアロジック(値と具体的な例外)
src/template_python/core.py は、環境変数、ログ、CLI の副作用を持たない決定的な
処理を担当します。cli.py が設定を読み、ログを構成してコアを呼び出します。
__init__.py は CLI を import せず再利用可能な処理を公開し、
__main__.py は起動だけを担当します。
この分離により、ライブラリの利用者は関数を呼ぶだけなら、Typer、環境変数の 読み込み、プロセス全体のログ設定を理解する必要がありません。
変更箇所の早見表
| 変更したいこと | 主な変更先 | テストする契約 |
|---|---|---|
| 再利用可能な処理 | src/template_python/core.py または目的の明確な新モジュール |
tests/test_core.py または対応する新テストで、値・正規化・具体的な例外を確認 |
| コマンド・オプション・利用者向けエラー | src/template_python/cli.py |
tests/test_cli.py で stdout・stderr・終了コードを確認 |
| 環境変数による設定 | src/template_python/settings.py と .env.template |
tests/test_settings.py で既定値・許容値・拒否を確認 |
| ログ設定 | src/template_python/logging.py |
tests/test_logging.py でレベル検証・出力を確認 |
| ライブラリの公開 API | src/template_python/__init__.py |
CLI を初期化せず公開 API を import・実行できることを確認 |
| ビルド・依存関係 | pyproject.toml と uv.lock |
make package-check でインストール済み wheel の動作を確認 |
認知負荷を小さく保つ
既定の方針には理由があります。将来必要かもしれないものではなく、具体的な要求に 応じて変更します。
| 判断 | まず選ぶもの | 見直す条件 |
|---|---|---|
| 新しい処理の置き場所 | 目的の明確なモジュールの名前付き関数 | 外部 I/O の具体的な要求によりアプリケーション側の adapter が必要 |
| 共通化するか | 責務が分かる名前で局所的に実装 | 複数の実際の利用箇所で同じ安定した振る舞いが必要 |
| class・framework を追加するか | 関数と明示的な引数 | 状態や lifecycle の所有者が必要で、単純な組み合わせでは不足 |
| 依存関係・ツールを追加するか | 標準ライブラリと既存ツール | 実行時・保守時のコストに見合う、測定可能な不足がある |
| 任意アセットを使うか | 未使用のままにするか削除 | 実際の配布・開発要件で必要 |
utils・commonの寄せ集め、基底クラス階層、サービスロケータ、 将来を想像した DI framework は避けます。- 入出力と責務を表す名前を使います。小さな処理を理解するために、何層ものコードを 追う必要がない構造にします。
- 値を返すか、具体的な例外を送出します。失敗を成功に見える既定値へ置き換えたり、 広く握りつぶしたり、秘密情報をログへ出したりしません。
- 手順の正本を1つにします。複数の文書や Workflow へコマンドをコピーせず、 参照・再利用します。
自明ではない判断は、問題、最も単純な代替案、選んだトレードオフ、検証方法を PR の説明に残します。別の設計文書は、その変更後も理由を参照する必要があるとき だけ作ります。
情報の正本
| 対象 | 正本 |
|---|---|
| メタデータ、依存関係、ツール設定 | pyproject.toml |
| 解決済み依存バージョン | uv.lock |
| ローカルと CI のコマンド | Makefile |
| 最低 Python・テスト対象バージョン | pyproject.toml・.github/workflows/test.yaml |
| 設定の schema・設定例 | src/template_python/settings.py・.env.template |
| コンテナ動作 | Dockerfile と compose.yml |
| ドキュメント構成 | mkdocs.yml |
宣言と、その宣言から生成するものは一緒に更新します。依存関係は
pyproject.toml で変更し、uv lock で lock を再生成します。
CI は同じ検証を独自に実装せず、Make target を呼びます。
ランタイムのルール
- パッケージの import 時にログ設定や環境変数読み込みを行いません。
- コアは Typer や設定に依存せず、CLI が値と例外を表示・終了コードへ変換します。
ProjectSettingsがPROJECT_*と任意の.envを一元管理します。 別の dotenv loader を追加しません。- root logger の設定は CLI callback で一度だけ行い、ライブラリは名前付き logger を取得するだけにします。
- CLI は
[project.scripts]で公開し、python -m template_pythonも維持します。
品質ゲート
変更内容に応じた検証を選びます。 Python の品質ゲートは、整形、型、Lint、Workflow のルール、全テストを確認し、 branch coverage 95% 以上を要求します。wheel と sdist をビルドした後、 wheel の CLI とモジュール起動を隔離環境で確認します。 sdist のインストール試験は行いません。
内部構造ではなく、失敗時を含む観測可能な契約をテストします。互換性を壊す必要が 明示されていない限り、stdout、stderr、終了コード、import 時の動作を保ちます。
配布
- Pull Request と対象ブランチで Python とコンテナを検証します。
mainから GitHub Pages へ英日ドキュメントを公開します。v*tag から Docker Hub と GHCR へ multi-platform image を公開します。- GHCR release には push 済み digest に対応する provenance を付与します。
- Azure Static Web Apps は手動デプロイを維持します。
Release Workflow は、tag が v と pyproject.toml の version を連結した値に
一致することを確認してから公開します。Docker Hub には
DOCKERHUB_USERNAME と DOCKERHUB_TOKEN の secret が必要です。
GHCR は Workflow の GitHub token を使います。手動のサイト公開には
AZURE_STATIC_WEB_APPS_API_TOKEN が必要です。これらの認証情報はローカル開発に
不要です。PyPI への公開は設定されていません。
外部 Action は commit SHA で固定します。Workflow は明示的な最小権限、 checkout credential の無効化、timeout を使い、自動キャンセルは後続実行で 置き換えられる release 以外の処理に限定します。
テンプレートの導入
新しいプロジェクトを作ったときに一度行い、公開を有効にする前に確認します。
pyproject.tomlの配布名、説明、version、URL、console script を設定し、 ライセンスが適切か確認します。- import 名を変えるなら
src/template_python/を改名し、import、テストの参照、 script の参照先、モジュール起動コマンド、coverage などのツール設定も揃えます。 型付きパッケージのpy.typedは維持します。 - 設定の既定値、
.env.template、Notebook の例、Makefile の配布物検証コマンドと image の既定値、Dockerfile の起動先と label、Compose、Dev Container 名、 docs の URL、Workflow の image 名、README の badge を更新します。 配布名はハイフン、Python の import 名はアンダースコアを使います。 - 次の表に従い不要なアセットを外し、実行できない CI の参照を残しません。
uv lockを実行し、残したアセットを検証します。ソースの直接 import だけでなく、 改名後のインストール済み CLI を確認します。- 残した配布 Workflow にだけ、リポジトリの公開設定と secret を用意します。 release tag とパッケージ version を一致させます。
任意アセット
Notebook、docs、コンテナ、registry、Azure、Dev Container は独立したサンプルです。 別のアプリケーション動作を作らず、インストール済みパッケージを利用します。
| 外すアセット | 同時に削除・更新するもの |
|---|---|
| Notebook | notebooks/、notebook 依存グループ、jupyterlab Make target |
| ドキュメントサイト | docs/、mkdocs.yml、docs グループと Make target、両サイト公開 Workflow、test.yaml の docs コマンド |
| コンテナ | Dockerfile、Compose、.dockerignore、Docker の Make target・変数、コンテナ検証・公開 Workflow |
| registry 公開だけ | 不要な job または container-release Workflow。必要ならローカルのコンテナ検証は残す |
| 手動のサイト公開だけ | azure-static-web-app.yaml とデプロイの説明 |
| Dev Container | .devcontainer/ と環境構築の説明 |
依存グループを変更したら lock を再生成し、badge、リンク、ガイドの項目も同じ変更で 整理します。認証情報を要求する未使用の Workflow を残さないでください。
多言語出力が MkDocs 1 の plugin ecosystem に依存する間、MkDocs は 2 未満に 固定します。
変更チェックリスト
- [ ] 変更の目的が1つで、上記のモジュール境界を守っている。
- [ ] 期待する値と失敗をテストし、互換性を変える場合は明示している。
- [ ] 依存宣言、lock、影響する配布アセットが一致している。
- [ ] コマンドは既存 Make target を再利用し、新ツールは実際の不足を補っている。
- [ ] 影響する英日ドキュメントを更新し、手順を重複させていない。
- [ ] 変更した各領域の検証が成功し、必要なインストール済みパッケージの確認も行った。