2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

なぜTDDは設計を改善するのか:関心の分離・依存の明示・責務の単純化

Posted at

概要

TDD(Test-Driven Development)は、
しばしば「品質向上のための手法」と誤解されるが、
その本質は**“設計改善のプロセス”**にある。

本稿では、TDDが設計に与える影響を以下の3つの軸で構造的に分析する:

  • 関心の分離(Separation of Concerns)
  • 依存の明示(Dependency Visibility)
  • 責務の単純化(Responsibility Isolation)

Python + pytest を用いた実装例を交え、**「TDDを設計手法として捉える視点」**を提示する。


1. TDDがもたらす「関心の分離」

✅ テストファーストで始めると「副作用」と「ロジック」が分離される

# app.py
def calculate_tax(price: float, rate: float) -> float:
    return price * rate
# test_app.py
def test_calculate_tax():
    assert calculate_tax(100, 0.1) == 10.0

副作用(ログ、DBアクセス)を含まない純粋ロジックだけを最初に作ることが可能になる。

👉 結果:UIやインフラ層とロジックの関心が分離される


2. 「依存の明示」が設計を透明にする

テストを書く前提で設計すると、**隠れた依存(現在時刻、グローバル変数、DBなど)**が即座に浮かび上がる。

# ❌ テスト不能:datetime.now() に依存
def should_send_email():
    return datetime.now().weekday() == 0
# ✅ TDD設計:依存を注入
def should_send_email(today):
    return today.weekday() == 0
  • TDDは依存の明示を強制し、副作用の分離・DI設計を促進する
  • 結果として Mockやスタブで差し替え可能な構造が生まれる

3. 責務の単純化:関数が「一つのこと」だけをするようになる

TDDでは、最小の期待(仕様)をテストで先に書くため、
実装は必然的に「1つの責務」を持った関数・メソッドになる。

def parse_email(text: str) -> str:
    # メールアドレスだけを抽出する(責務は1つ)
def send_email(to: str, body: str):
    # 送信だけを行う(パースしない)

✅ 関数やクラスの「責任」が小さく明確になることで、再利用・保守性が高まる


4. 設計改善の実例:料金計算のTDDプロセス

要求

  • 基本料金:500円
  • 土日は20%割引

テスト(Red)

def test_weekday_charge():
    assert calc_charge('2024-04-01') == 500

def test_weekend_discount():
    assert calc_charge('2024-04-06') == 400

実装(Green)

from datetime import datetime

def is_weekend(date_str: str) -> bool:
    day = datetime.strptime(date_str, '%Y-%m-%d').weekday()
    return day >= 5

def calc_charge(date_str: str) -> int:
    return 400 if is_weekend(date_str) else 500

設計効果(Refactor)

  • is_weekend が分離され関心の明確化
  • 料金計算ロジックは1関数1責務
  • 日付依存は str で受け取りテストしやすい構造

設計判断フロー

① ロジックと副作用が混在していないか? → 分離すべき

② 外部依存(時間・ランダム・I/O)が埋め込まれていないか? → 注入方式に

③ テストしづらい箇所があるか? → それは設計の匂い(Smell)

④ 1つの関数に複数の責任がないか? → TDDに従い分解する

よくあるミスと対策

❌ TDDをやってもテストしづらいコードになる

→ ✅ TDDは「テストを先に書く」だけではなく、設計改善が主目的であることを再認識


❌ テストのために実装を「無理やり弄る」

→ ✅ 依存を明示・注入すれば、設計は自然にテスタブルになる


❌ 結果的に1つの関数が肥大化

→ ✅ テストケースが大きくなったら、それは分割のサイン


結語

TDDがもたらす最大の恩恵は「テストがあること」ではない。
それは**“設計がシンプルになり、進化に耐える構造になること”**である。

  • 思考が仕様ベースになる
  • 関心が自然に分離される
  • 依存と副作用が明示され、構造が透明になる

TDDとは、
“テストを通して設計と責任の境界線を描き出す建築的プロセスである。”

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?