Skip to content

Latest commit

 

History

History
380 lines (220 loc) · 6.41 KB

phase-5-8.md

File metadata and controls

380 lines (220 loc) · 6.41 KB

Phase 5.8: BaseModel / 抽象化をTDDで設計する

← 前へ: Phase 5.7 | 目次 | 次へ: Phase 5.9 →

概要

実行前に共通セットアップと各Phaseの確認手順を確認してください。演習コードはwork/で前のPhaseから引き継ぎます。

このフェーズでは、これまでに構築してきた各Modelの実装を見直し、共通化と抽象化(BaseModel)をTDDで導入します。

Phase 5.7までで、あなたは以下を実現しています:

  • データ取得(all / find / where)
  • レコードのオブジェクト化
  • 永続化(save / update / destroy)
  • バリデーション

しかし、現状のコードを見返すと、次のような問題があるはずです:

  • User と Post で同じコードが存在する
  • DB接続処理が重複している
  • SQL生成ロジックが分散している
  • オブジェクト生成処理が各Modelにある
  • バリデーションの仕組みも重複している

このフェーズでは、それらを整理し、

「共通化すべきもの」と「Model固有に残すべきもの」

を切り分けながら、BaseModelを導入します。


このフェーズの目的

以下を説明できる状態になること:

  • なぜBaseModelが必要になるのか
  • 抽象化の適切なタイミング
  • 共通化と過剰抽象化の違い
  • フレームワークの内部構造の考え方

到達目標

  • 共通処理をBaseModelに集約できる
  • 各Modelは差分だけを持つ構造になる
  • Finder / Persistence / Validationが整理される
  • 抽象化の判断を説明できる

前提

  • Phase 5.7(バリデーション)完了
  • User / Post など複数Modelが存在する

重要ルール

1. 必ずテストから書く(RED)

2. 最小の共通化で通す(GREEN)

3. 抽象化しすぎない(REFACTOR)


このフェーズで目指す最終形(イメージ)

class User < BaseModel
end

class Post < BaseModel
end
  • 共通処理は BaseModel に集約
  • 各Modelは最小の記述

演習課題


Step 1: Model間の重複を明確にする

まずは現状を観察します。

観察ポイント

  • all
  • find
  • where
  • save
  • destroy
  • バリデーション

課題

どの処理が共通かを書き出してください。


Step 2: 共通化したいというテストを書く(RED)

テストの方向性

  • User と Post が同じ仕組みで動く
  • 共通のロジックで処理される

👉 RED


Step 3: BaseModelを導入する(GREEN)

やること

  • 共通クラスを作る
  • Modelを継承構造にする

ヒント

  • 継承(inheritance)
  • 共通メソッドの移動

Step 4: Finder処理をBaseModelに移す(REFACTOR)

対象

  • all
  • find
  • where

問い

  • どこまで共通化できるか?
  • 何がModelごとの差分か?

Step 5: テーブル名の扱いを整理する(RED)

共通化すると問題が出ます:

  • Modelごとにテーブルが違う

テストの方向性

  • Modelごとに正しいテーブルを参照する

👉 RED


Step 6: テーブル名の抽象化を実装する(GREEN)

やること

  • Modelごとにテーブル名を扱う仕組みを作る

ヒント

  • クラス名から推測する
  • 明示的に指定する

Step 7: 永続化処理をBaseModelに移す(REFACTOR)

対象

  • save
  • insert
  • update
  • destroy

観察

  • ほぼ共通処理ではないか?

Step 8: バリデーションを共通化する(REFACTOR)

やること

  • バリデーションの仕組みをBaseModelへ移す

問い

  • Modelごとの差分は何か?

Step 9: オブジェクト生成の共通化(REFACTOR)

観察

  • DB → オブジェクト変換が重複している

やること

  • 共通メソッド化

Step 10: APIの自然さをテストで確認する(RED)

テストの方向性

  • 各Modelが同じAPIを持つ
User.all
Post.all

👉 RED


Step 11: 最小修正で通す(GREEN)


Step 12: BaseModelの責務を整理する

問い

  • BaseModelは何をするクラスか?
  • Modelは何を持つべきか?

Step 13: 過剰抽象化を避ける

注意

  • すべてを共通化しない
  • 読みにくくしない

Step 14: 「どこまで抽象化するか」を言語化する

必ず説明すること

  • なぜここまで共通化したか
  • なぜこれ以上やらないのか
  • 抽象化の判断基準

発展課題


課題1: カラム定義の自動化

  • attr_accessorを自動化したくなる

課題2: メタプログラミングの導入

  • define_method など

※ 必須ではない


課題3: DSL風API

class User < BaseModel
  validates :name, presence: true
end

提出物


1. テストコード

  • 複数Modelで同じAPIが使える
  • 共通処理が機能している

2. 実装コード

  • BaseModel
  • 各Model

3. 設計メモ(最重要)

以下を説明:

  • なぜBaseModelが必要になったか
  • 何を共通化したか
  • 何を残したか
  • 抽象化の判断基準

レビュー観点

  • TDDが守られているか
  • 共通化が適切か
  • 可読性が保たれているか
  • 過剰設計でないか
  • 説明できるか

よくある失敗


❌ なんでも共通化する

→ 可読性崩壊


❌ メタプログラミングに逃げる

→ 理解が浅くなる


❌ BaseModelが巨大化する

→ 責務崩壊


❌ 個別Modelの責務を消す

→ ドメインが消える


このフェーズの本質

このフェーズで得るべき理解は:

抽象化とは「共通化すること」ではなく、 「変化に強い構造を作ること」である


次フェーズへの接続

ここまでであなたは:

  • フレームワーク
  • ORM
  • MVC

を自力で構築しました。

最後にやるべきこと:

👉 Phase 5.9: ORMの限界とActiveRecordの理解


← 前へ: Phase 5.7 | 目次 | 次へ: Phase 5.9 →