• #Python
  • #リファクタリング
  • #モジュール分割
  • #tax-assistant
開発tax-assistantメモ

概要

tax-assistantプロジェクトで、2,602行・68関数という巨大なdb.pyを機能別モジュールに分割した。

ロジックは一切変更せず、ファイル構造のみを変更。インポート確認のみでテスト完了。

Before: 単一ファイル構成

src/
└── db.py          # 2,602行、68関数

1ファイルに全機能が詰め込まれていた状態:

  • DB接続・初期化
  • マイグレーション
  • コメント機能
  • バリデーション
  • レシート処理
  • バッチ処理
  • CSV入出力
  • Square連携
  • 仕訳ルール
  • クレカ明細

After: 機能別モジュール構成

src/
└── db/
    ├── __init__.py        # 後方互換性レイヤー(全関数を再エクスポート)
    ├── core.py            # DB接続、初期化、マイグレーション
    ├── comments.py        # コメント機能
    ├── validation.py      # バリデーション
    ├── receipts.py        # レシート関連
    ├── batches.py         # バッチ処理
    ├── csv_io.py          # CSV入出力
    ├── square.py          # Square連携
    ├── shiwake_rules.py   # 仕訳ルール
    └── creditcard.py      # クレカ明細

分割の方針

1. 機能の凝集度で分割

関連する関数をグループ化。例えばreceipts.pyにはレシート関連の全関数をまとめた:

  • get_receipts()
  • insert_receipt()
  • update_receipt()
  • delete_receipt()
  • search_receipts()

2. 依存関係の整理

core.pyに共通の接続・初期化処理を配置し、他モジュールから参照する構造にした。

# core.py
def get_connection():
    ...

def initialize_database():
    ...
# receipts.py
from .core import get_connection

def get_receipts():
    conn = get_connection()
    ...

3. 後方互換性の確保

__init__.pyで全関数を再エクスポート。既存コードのfrom src.db import xxxを変更せずに動作する。

# __init__.py
from .core import get_connection, initialize_database, run_migrations
from .comments import get_comments, add_comment, delete_comment
from .validation import validate_receipt, validate_batch
from .receipts import get_receipts, insert_receipt, update_receipt
from .batches import get_batches, create_batch, process_batch
from .csv_io import export_to_csv, import_from_csv
from .square import sync_square_transactions, get_square_payments
from .shiwake_rules import get_rules, apply_rules, create_rule
from .creditcard import import_statement, match_receipts

# 後方互換性のため全てをエクスポート
__all__ = [
    # core
    'get_connection', 'initialize_database', 'run_migrations',
    # comments
    'get_comments', 'add_comment', 'delete_comment',
    # ... 以下省略
]

テスト方法

ロジック変更がないため、インポート確認のみで検証を完了した。

# テストスクリプト
from src.db import (
    get_connection,
    get_receipts,
    get_comments,
    # ... 全68関数をインポート
)

print("All imports successful")

全関数のインポートが成功すれば、分割は正常に完了している。

分割後のメリット

  1. 可読性向上: 関連機能が1ファイルにまとまり、コードを追いやすくなった
  2. 保守性向上: 特定機能の修正時に影響範囲が明確
  3. 並行開発: 異なる機能を別々に開発しやすい
  4. テスト容易性: モジュール単位でのテストが可能

今後の課題

  • 各モジュールの単体テスト追加
  • 型ヒントの整備
  • docstringの充実