フルスタックデザインパターンガイド
このスキルを使用して、エンドツーエンドのフルスタックシステムのアドバイス、アーキテクチャ設計、リファクタリングを行います。パターンは特定可能なアーキテクチャ上の摩擦を解決するためにのみ厳密に適用し、推測による抽象化には使用しないでください。
コア原則
- 問題ファーストの選択: 明示的なアーキテクチャ上の摩擦やコード臭(例:prop drilling、肥大化したgod-component、密結合なAPI、テスト不能なロジック、カスケードするネットワーク障害)なしに、デザインパターンを導入しないでください。
- 明確なアーキテクチャ上の境界: 以下の間で明確な境界を維持します:
- ビュー/プレゼンテーション: propsによって駆動される、宣言的で状態を持たないコンポーネント。
- クライアント状態とインタラクション: ヘッドレスフック、集中ストア、サーバー状態キャッシュ。
- API/コントラクト層: 型付けされたスキーマ、DTOアダプター、および腐敗防止層。
- ドメインとデータアクセス: 疎結合なビジネスルールとリポジトリで支えられたデータベースアクセス。
- 過剰設計の回避: 単純なCRUDページや標準的なWebアプリに、マイクロフロントエンド、CQRS、分散Pub/Subのような複雑なエンタープライズ抽象化を適用しないでください。
パターン決定マトリックスとトリガーヒューリスティック
| レイヤー | コードベース内の症状/摩擦 | 推奨パターン | アーキテクチャ上の境界 |
|---|---|---|---|
| フロントエンドUI | APIフェッチ、フォーマット、JSXレイアウトを組み合わせたgod-component | Container/Presentational | UIレンダリングをデータフェッチから分離 |
| フロントエンドUI | インタラクティブなコンポーネント(モーダル、ドロップダウン)内での密結合なスタイリング | Headless Component / Custom Hooks | 状態とキーボード/インタラクションロジックを分離 |
| フロントエンドUI | 柔軟なサブ要素を必要とする堅牢なコンポーネントAPI | Compound Components | 宣言的な親子状態共有(例:Tabs、Select) |
| フロントエンドUI | 深いprop drilling、または同期が取れていないマルチコンポーネントUI状態 | Observer / Store (Zustand/Redux/Context) | 共有クライアント状態を集中管理 |
| フルスタックAPI | バックエンドAPIスキーマの変更がフロントエンドUIコンポーネントを壊す | Adapterパターン (Data Mapper) | DTOをViewModelに変換する腐敗防止層 |
| フルスタックAPI | UIがユーザーアクションを確認する前に、遅いネットワークを待つ | Optimistic UI with Rollback | トランザクションロールバックで支えられた即時UI応答 |
| バックエンド | SQL/ORM呼び出しがルートハンドラーやサービス内に散在 | Repositoryパターン | 永続化クエリをビジネスルールから分離 |
| バックエンド | インラインのif-elseを使用して異なるサードパーティSDKをインスタンス化 | Factoryパターン | オブジェクトとクライアントの作成を集中管理 |
| バックエンド | 価格計算、認証、アルゴリズムを計算するカスケードif-else/switch | Strategyパターン | 交換可能なアルゴリズムをインターフェースの背後にカプセル化 |
| バックエンド/分散 | コアビジネスアクションが5つ以上の無関係な副作用をトリガー | Observer / イベント駆動 (Pub/Sub) | ドメインイベントまたはメッセージキューを介して副作用を分離 |
| バックエンド/分散 | 外部APIレイテンシがスレッド枯渇とカスケードダウンタイムを引き起こす | Circuit Breaker | 早期失敗、フォールバック応答、およびダウンストリームヘルスプロービング |
深掘り: フルスタックパターンと実装ルール
1. フロントエンド: Container/Presentationalパターン
- コンテキスト:
useEffect、クエリ、データ変換、レイアウトJSXを組み合わせることで、200行を超えるコンポーネント。 - ルール:
- Presentationalコンポーネント: propsを介してのみデータとコールバックを受け取る; 純粋で、APIモックなしでStorybookで簡単にテスト可能。
- Container (またはPage Hook): サーバーデータをフェッチし、ローディング/エラー状態を管理し、変換されたデータを渡す。
2. フロントエンド: Headless Component & Custom Hookパターン
- コンテキスト: 異なるビジュアルデザイン間で再利用が必要な複雑なインタラクティブ動作(オートコンプリート、マルチステップウィザード、アコーディオン)。
- ルール:
- 状態、キーハンドラー、ARIA属性をヘッドレスカスタムフック(例:
useAutocomplete、useDisclosure)に抽出する。 - スタイリングとDOMマークアップは完全にコンシューマーの手に委ねる。
- 状態、キーハンドラー、ARIA属性をヘッドレスカスタムフック(例:
3. フロントエンド: Compound Components
- コンテキスト: 深く関連するサブパーツを持ち、数十の設定propsを渡さずに、コンポーネント内部で一貫した状態を必要とするコンポーネント。
- ルール:
- React Contextを活用して、親子間で暗黙的に通信する(
<Accordion><Accordion.Item /><Accordion.Panel /></Accordion>)。
- React Contextを活用して、親子間で暗黙的に通信する(
4. 統合: Adapterパターン(腐敗防止層)
- コンテキスト: サードパーティのREST/GraphQLペイロードが、UIコンポーネントのpropsやコアドメインモデルに直接漏れ出している。
- ルール:
- 生のバックエンドDTOキーにフロントエンドコンポーネントのprops形状を決定させない。
- 明示的なマッパー関数(例:
toUserViewModel(dto: UserApiDto): UserVM)を作成し、スキーマの変更からUIコンポーネントを保護する。
5. 統合: Optimistic UI with Rollback
- コンテキスト: 「いいね」、トグル、タスク完了、並び替えなど、ネットワークレイテンシが応答性を損なう頻繁なユーザーインタラクション。
- ルール:
- インタラクション時にローカル状態を即座に更新する。
- サーバーへの変更をキューイングし、拒否された場合は以前のスナップショットにロールバックし、ユーザーに邪魔にならない方法で通知する。
6. バックエンド: Repositoryパターン
- コンテキスト: ビジネスロジックがORMクエリ(Prisma、TypeORM、Drizzle、SQL)と絡み合っている。
- ルール:
- サービスはインターフェース(例:
OrderRepository)とのみやり取りする。 - ドメインロジックをリポジトリから遠ざけ、クエリ構築をサービスから遠ざける。
- サービスはインターフェース(例:
7. バックエンド: Strategy & Factoryパターン
- コンテキスト: 交換可能なプロバイダー(決済ゲートウェイ、通知チャネル、ファイルストレージ)。
- ルール:
- 共通のインターフェース(
PaymentGateway)を通じて振る舞いを標準化する。 - Factory/Registryを使用して、構成またはテナントに基づいて具体的な実装を解決する。
- 共通のインターフェース(
8. バックエンド: Circuit Breakerパターン
- コンテキスト: 断続的なダウンタイムまたは深刻なレイテンシに悩まされる外部マイクロサービスまたはサードパーティAPI。
- ルール:
- 失敗しきい値を追跡する。遷移:
Closed(正常) ->Open(早期失敗、キャッシュ/フォールバックを返す) ->Half-Open(カナリアプローブ)。
- 失敗しきい値を追跡する。遷移:
エージェント出力ワークフロー
アーキテクチャに関するアドバイスやフルスタックコードのリファクタリングを求められた場合:
- 境界とボトルネックを特定する: 摩擦がUIレンダリング、状態同期、APIコントラクトの不一致、バックエンドの結合のいずれにあるかを特定する。
- 一致するパターンを選択する: 特定のコード臭に対処する明確な根拠とともにパターンを提案する。
- Before / Afterの例を提供する: 責任の分離を示す、簡潔で慣用的なコードスニペットを提供する。
- テスト容易性と保守性を強調する: リファクタリングが単体/コンポーネントテストを簡素化し、将来の変更から保護する方法を説明する。