• #FastAPI
  • #リファクタリング
  • #Python
  • #tax-assistant
開発tax-assistantメモ

背景

tax-assistantプロジェクトのocr_server.pyが1,075行に膨れ上がっていた。レシートAPI、Square連携API、クレカ明細API、実装計画APIなど複数の機能が1ファイルに詰め込まれており、見通しが悪くなっていた。

db.pyで同様のモジュール分割を行った経験があったため、同じパターンでocr_server.pyを分割することにした。

新しいディレクトリ構成

src/server/
├── __init__.py      # FastAPI app インスタンス
├── config.py        # 設定・定数
├── receipts.py      # レシートAPI
├── square.py        # Square連携API
├── creditcard.py    # クレカ明細API
└── plans.py         # 実装計画API

各ファイルの役割

__init__.py

FastAPIアプリケーションのエントリーポイント。各モジュールのルーターを集約する。

from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware

from .receipts import router as receipts_router
from .square import router as square_router
from .creditcard import router as creditcard_router
from .plans import router as plans_router

app = FastAPI(title="OCR Server")

# CORS設定
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# ルーター登録
app.include_router(receipts_router)
app.include_router(square_router)
app.include_router(creditcard_router)
app.include_router(plans_router)

config.py

環境変数やパス定数を一元管理。

from pathlib import Path

# ベースディレクトリ
BASE_DIR = Path(__file__).parent.parent.parent

# データディレクトリ
DATA_DIR = BASE_DIR / "data"
RECEIPTS_DIR = DATA_DIR / "receipts"

receipts.py

レシートのOCR処理とCRUD操作を担当するAPIRouter。

from fastapi import APIRouter

router = APIRouter(prefix="/api/receipts", tags=["receipts"])

@router.get("/")
async def list_receipts():
    ...

@router.post("/ocr")
async def ocr_receipt():
    ...

square.py

Square決済との連携APIを担当。

creditcard.py

クレジットカード明細のインポートと突き合わせAPIを担当。

plans.py

実装計画の管理APIを担当。

起動方法の変更

変更前

python ocr_server.py

変更後

uvicorn server:app --port 8000 --reload

src/ディレクトリから実行する場合:

cd src
uvicorn server:app --port 8000 --reload

db.pyと同じパターン

以前db.pyを分割した際と同じアプローチを採用した。

  • 機能ごとにファイルを分離
  • APIRouterを使用してルーティングをモジュール化
  • __init__.pyでルーターを集約
  • 設定はconfig.pyに集約

この分割により、各機能が独立して開発・テストしやすくなった。

得られた効果

  1. 可読性向上: 1,075行から各ファイル200-300行程度に分割
  2. 保守性向上: 機能ごとにファイルが分かれているため、修正箇所の特定が容易
  3. テスト容易性: 各モジュールを個別にテスト可能
  4. チーム開発対応: 複数人で同時に別機能を開発しやすい