mcpField
D
design-code-architecture

design-code-architecture

github.com/wondelai開発2.5k2.3k 回インストール7 週間前に更新
リポジトリ

design-code-architecture について

新しいアプリのアーキテクチャを設計する、開発者やチーム向けの対話型スキルです。変更コストの高い判断を重視し、境界、ドメイン、データ、信頼性を8段階で検討して docs/ に記録します。

主な機能

  1. 018段階のアーキテクチャ設計
  2. 02コード依存関係とシステム境界の整理
  3. 03ドメインコンテキストと用語のモデル化
  4. 04データ設計とシステム規模の評価
  5. 05判断と却下した代替案の記録

活用シーン

  1. 01新規アプリのモジュール境界の決定
  2. 02ドメインコンテキストと集約の設計
  3. 03ストレージと一貫性要件の評価
  4. 04外部依存関係のレジリエンス計画

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/wondelai/skills --skill design-code-architecture

インストール後、Claude Code で/design-code-architectureを入力して読み込まれたか確認します。

同梱ファイルreferences/artifact-templates.md

詳細

コードアーキテクチャの設計

新しいアプリのアーキテクチャを設計します。後から変更するのにコストがかかる少数の決定を正しく行い、それ以外は徹底してシンプルに保ちます。これは8つのフェーズからなる、対話形式で中断・再開可能なプロセスです。エージェントは各決定の前に確認し、結果をプロジェクトの docs/ フォルダーに記録するため、どのフェーズで止めても後から再開できます。最も基盤となり、変更が最も難しい要素(境界、ドメイン)から、調整可能な要素(データ、レジリエンス)、さらに一貫して適用する横断的な規律(複雑さ、可逆性、スコープ)へと進みます。週末のプロジェクトなら3つのフェーズを簡易的に使い、資金提供を受けてローンチを目指すチームなら、すべてのフェーズを活用できます。

基本原則

アーキテクチャとは、変更するのにコストがかかる決定の集合です。そうした決定だけを慎重に行い、簡単に変更できることはすべて先送りにしてください。 このスキルはフェーズを順序立て、決定のための質問を行い、すべての選択を docs/ に記録します。具体的な方法は各スキルが担うため、そのフレームワークを即興で組み立てるのではなく、各スキルを呼び出してください。戦略全体として、境界を設けてコストのかかる決定を簡単に変更できるようにし、どうしてもコストのかかる決定の数を慎重に正しく判断できる範囲に抑えます。

プロセス一覧

フェーズスキル答える問い成果物
1clean-architectureソースコードの依存関係は内側を向いていますか。DB、Web、フレームワークなしでコアをテストできますか。docs/ARCHITECTURE.md を作成
2domain-driven-designビジネスの実際の境界はどこで、それぞれの用語は何を意味しますか。docs/ARCHITECTURE.md を拡張
3system-design実際の負荷に必要なシステムを、どこまで小さくできますか。docs/ARCHITECTURE.md を拡張
4ddia-systems各ワークロードに必要なデータモデル、ストレージエンジン、一貫性は何ですか。docs/ARCHITECTURE.md を拡張
5software-design-philosophy複雑さは深いモジュールの背後に隠れていますか。それともクラス過多になっていませんか。docs/TECH-DEBT.md を拡張
6release-it依存先が遅い、または停止しているとき、適切に縮退できますか。docs/RELIABILITY.md を作成
7pragmatic-programmer境界を検証する最小限の実装は何ですか。また、境界を可逆的に保つ習慣は何ですか。docs/TESTING.md + docs/TECH-DEBT.md を拡張
837signals-wayv1 に不可欠なものは何ですか。また、推測に基づく抽象化のうち削るものは何ですか。docs/ARCHITECTURE.md + docs/TECH-DEBT.md を拡張

運用ルール

  1. まず再開します。 何よりも先に、docs/DESIGN-CODE-ARCHITECTURE-PLAN.md とジャーニーマップ内のすべての成果物を読みます。トラッカーが存在する場合は、ジャーニーの状態を3~5行で要約し、どのフェーズから始めるかを尋ねます。開始地点についてユーザーが確認したら完了です。トラッカーがあるジャーニーは再開し、最初からやり直すことはありません。
  2. 初回実行時のみインテークを行います。 トラッカーがない場合は、以下のインテークを実施してから、すべてのフェーズのステータスを pending | in-progress | awaiting-evidence | done | deferred: reason | skipped: reason のいずれかに設定した docs/DESIGN-CODE-ARCHITECTURE-PLAN.md を作成します。トラッカーが存在し、ユーザーがフェーズ計画を確認したら完了です。
  3. フェーズへの移行。 フェーズの内容、必要となる判断、作成する成果物、おおよその作業量を伝えます。続行/スキップ/延期の選択肢を提示します。GATE と記されたフェーズは延期できますが、スキップはできません。続行する場合はフェーズを in-progress にします。ユーザーが選択したら完了です。
  4. スキルの呼び出しとフォールバック。 フェーズのスキルを読み込んで使用します。各フェーズの Invoke 行にはスキルがスラッグで記載されているため、そのスキルを使ってフェーズを実施します。利用できない場合は、npx skills add wondelai/skills/<slug> --global を提案します。ユーザーが辞退した場合は、Brief に基づいて、そのフェーズを実施するための最小限の方法を使います。どの方法で進めているかを明示します。
  5. フェーズ内の判断。 「ユーザーと決める」の下にあるすべての質問を、具体的な選択肢と推奨案を添えて尋ねます。選択内容をトラッカーの Key Decisions に記録します。判断をユーザーに確認せずに行うことは不備です。
  6. フェーズの終了。 書き込む前に、成果物の草案を提示して承認を得ます。承認後、docs/ ファイルを作成または追記し、トラッカーを更新します(ステータス、Key Decisions、Next Actions)。ファイルが書き込まれ、フェーズの行が done になったら完了です。
  7. 成果物の取り扱い。 書き込む前に読み込みます。ファイルは存在しない場合にのみ作成し、存在する場合は追記します。ほかの人が作成した内容を保持しながら、該当するセクションを追加または更新します。docs/ 内のファイル名はすべて大文字にします。すべての推奨事項は、担当者と優先度を記載したチェックボックスまたは表の行として残します。docs/ ファイルを初めて作成するときは、references/artifact-templates.md を参照します。すべてのセクション見出しを含む完全なひな形からファイルを作成してから、フェーズで指定されたセクションに内容を記入します。
  8. 元に戻すコストが高い判断はすべて、コードがその前提に依存する前に、Decision Log に判断、理由、却下した代替案を記録します。 デフォルトではモジュラーモノリスを採用し、サービスの分割は、境界づけられたコンテキストが実証された場合に限ります。

事前確認

トラッカーを作成する前に、以下を確認してください。

  1. アプリは何をするもので、本当の競争優位となる機能は何ですか?(Phase 2 で中核となるサブドメインを定めます。深くモデリングする領域と既製品を利用する領域の判断に役立ちます)
  2. どのような技術スタックを考えていますか。言語、Web フレームワーク、ORM、データベースは何ですか?(Phase 1 の境界と Phase 4 のデータに関する判断を左右します。詳細として扱い、骨組みにはしません)
  3. 1 年目に見込まれる負荷はどれくらいですか。おおよそのデイリーアクティブユーザー数と、各ユーザーが主に行う操作を教えてください。(Phase 3 の規模設計を左右します。ソリューションより先に要件を確認します)
  4. 決済、メール、LLM API、配送、キューなど、どのような外部依存先を呼び出しますか?(Phase 6 の統合ポイント監査を左右します)
  5. システムオブレコードとなるデータは何ですか。また、検索、分析、フィードなど、ほかの読み取りパターンはありますか?(Phase 4 の整合性と派生データに関する判断を左右します)
  6. このアプリが実際に求められていることを、誰かが検証しましたか?(まだの場合は、まず create-business / create-app に進んでください。未検証のアイデアを設計しないでください)
  7. このシステムを担当するチームはいくつありますか。また、現時点でどこまでの工程を希望しますか?(チームトポロジーの任意フェーズと Phase 8 の取り組み方を左右します)

フェーズを省略する際の目安:1 年目の負荷がどのしきい値よりも大幅に低い場合は、Phase 3 のスケーリング機構と Phase 4 のレプリケーションの大半を省略してください(単一のインデックス付き DB が答えです。記録して先に進みます)。単一チームのアプリでは、チームトポロジーの任意フェーズを省略してください。Phase 1 と Phase 2 は決して省略しないでください。境界とドメインモデルは、後続のすべての判断を低コストにする追加の取り組みです。実際のユーザーと外部呼び出しが存在する場合、Phase 6 のレジリエンスは任意ではありません。その後、テンプレートからトラッカーを作成し、計画を確認してください。

docs/DESIGN-CODE-ARCHITECTURE-PLAN.md が存在し、すべてのフェーズのステータスが記入され、ユーザーが計画を確認したら完了です。

フェーズ

フェーズは、元に戻しにくいものから、調整可能なもの、横断的なものへと、記載順に進みます。それぞれのフェーズでは、前のフェーズの成果物が存在することを前提とします。Operating Rules に従って、どのフェーズにも着手、省略、延期できます。Phase 1〜2 は、その後のすべての変更を低コストにする追加の取り組みです。

各フェーズは、システムを反映した依存関係の連鎖を形成します。Domain-Driven Design は境界をどこに置くか(コンテキストと集約の境目)を示し、Clean Architecture は依存関係がその境界をどちら向きに越えるかを示します。Data-Intensive Apps は永続化レイヤーで境界の内側に何を置くかを決め、System Design は実際にどれほどのインフラが必要かを示します。通常、その量は懸念されているほど多くありません。Software Design はモジュールが浅い儀式を増やすのではなく、深さを保つようにし、Release It! は統合ポイントを強化します。Pragmatic Programmer は構造を長期にわたって支える横断的な習慣をもたらし、37signals Way は時間を固定してスコープを絞り、全体を導きます。

フェーズ 1 — 境界を引く(clean-architecture)

目的: ビジネスルールをフレームワーク、データベース、ベンダーから独立させ、後のあらゆる決定を差し替え可能に保ちます。これが、ほかのすべてを取り戻すための一手です。

概要(フォールバック): 依存関係のルールでは、ソースコードの依存関係は内側を向きます。フレームワーク → インターフェースアダプター → ユースケース → エンティティの順です。内側のものが外側のものを名前で参照することはありません。データベース、Web、ベンダーは詳細であり、ルールに対するプラグインです。依存性逆転によってこれを徹底します。ユースケースがリポジトリーインターフェースを所有し、Postgres/Stripe の実装は外側のアダプターに置きます。完全な境界を設けるのは、実際に変動しやすい箇所(DB、外部サービス、配信)に限り、それ以外ではレイヤーを統合します。重要なのは方向であり、フォルダーの数ではありません。

実行: clean-architecture スキルを、具体的な最初の機能とインテークで得た技術スタックを使って実行します。その機能をレイヤーに分けるよう依頼します(エンティティ、リクエスト/レスポンスモデルを持つユースケース、リポジトリーとゲートウェイのインターフェース、外側のリングに置く HTTP コントローラーと DB アダプター)。また、どの境界が形式的なだけなのか、どの境界が実際の変動に見合う価値をもたらすのかを明示するよう依頼します。

ユーザーと決めること: (1) モジュラーモノリスにするか、サービスに分割するか。既定では、内部に明確な境界を持つモジュラーモノリスを選びます。共有データモデルを持つマイクロサービスは分散モノリスであり、明らかにより悪い選択肢です。(2) どの変動しやすい箇所に、今すぐインターフェースを含む完全な境界を設け、どこでレイヤーを統合するか。

成果物: docs/ARCHITECTURE.md を作成し、## System Context(何をするか、連携先)、## Layer Map & Dependency Rule(レイヤー、依存関係。違反箇所 | 場所 | 修正 | 状態)、および ## Decision Log にモノリスかサービスかの選択(日付 | 決定 | 理由 | 却下した代替案)を記載します。トラッカーを更新します。

完了条件: レイヤーマップが存在し、最初の機能がレイヤー分けされ、フレームワーク/ORM の型が外側のリングに限定されていること。コアが DB/Web/フレームワークなしでテストできる設計になっていること。モノリスかサービスかの決定が Decision Log に記録されていること。フェーズ 1 の状態が done になっていること。

フェーズ 2 — ドメインをモデル化する(domain-driven-design)

目的: ビジネスが実際に分かれる場所に境界を置き、コードにドメインの言葉を反映します。白紙の状態から語彙を作れる今が、最もコストの低いタイミングです。

概要(フォールバック): モデルとはコードです。チームで使う言葉をコード上の名前にもするため、ユビキタス言語を構築します。ドメインの概念に基づいて名前を付けます(Order.place() とし、OrderManager.process() とはしません)。しっくりこない名前は厄介なものではなく、設計上のシグナルです。境界づけられたコンテキストとは、ある言葉が一つの意味だけを持つ領域です(「顧客」は請求とサポートでは意味が異なります)。これらは将来のサービス境界になります。集約とは、不変条件を守る小さなルートクラスターであり、内部では即時整合性、外部では結果整合性を保ちます。他の集約は ID で参照します。振る舞いをエンティティに持たせ、貧血データバッグにしないでください。

実行: domain-driven-design スキルを、ドメインの語彙とフェーズ 1 のレイヤーマップを使って実行します。チームが実際に使う言葉から境界づけられたコンテキストのマップを作成し、主要な集約とその不変条件を洗い出し、サブドメインを分類するよう依頼します(コア/支援/汎用)。

ユーザーと決めること: (1) 同じ言葉がコンテキストによって正当に異なる意味を持つ場所。全知的な単一モデルに統合してはいけません。(2) どのサブドメインがコアなのか(深くモデル化する)、どれが汎用なのか(購入するか OSS を使う。認証、メール、決済など)。

成果物: docs/ARCHITECTURE.md を拡張し、## Bounded Contexts & Context Map(コンテキスト、関係、腐敗防止層)および ## Domain Glossary (Ubiquitous Language)(用語 | 意味 | コード上の名前)を追加します。集約とコアドメインの選択を ## Decision Log に記録します。トラッカーを更新します。

完了条件: コンテキストとその関係がマッピングされ、用語集にコア用語が記載され、各集約に不変条件と ID による参照が明記され、コアサブドメインが選定されていること。また、コンテキストの境界がフェーズ 1 のレイヤーマップと整合していること。

フェーズ 3 — システムの規模を正直に見積もる(system-design)

目的: 数値に基づいてシステムをどこまで小さくできるかを証明し、正当化できない仕組みを省けるようにします。

概要(フォールバック): 解決策ではなく、要件から始めます。概算では、QPS = 1 日のアクティブユーザー数 × 1 日あたりのアクション数 ÷ 86,400、ピーク時は平均の 2~5 倍です。ストレージ容量 = 1 日あたりのレコード数 × サイズ × 保持期間です。数百~数千ユーザーであれば、インデックス付きの単一 DB と読み取りパスのキャッシュで、長期間対応できます。スケールの順序は、まず垂直スケール、次にキャッシュ・アサイド(TTL + 明示的な無効化)、次に読み取りレプリカ、最後に、根拠がある場合のみシャーディングです。低速または急増する処理を分離するにはメッセージキュー、グローバルな静的アセットには CDN を利用します。早すぎるシャーディングやサービス分割は、よく知られた失敗です。

実行: インテークで把握した負荷の実態をもとに、system-design スキルを使います。平均およびピーク時の QPS、年間ストレージ容量、最初にボトルネックとなるコンポーネント、そして現時点では不要な技術(シャーディング、レプリカ、CDN、キュー、マルチリージョン)を簡潔に列挙するよう依頼します。

ユーザーと決定する内容: 数値に基づき、今すぐ採用するスケーリング施策と先送りする施策を決めます(ユーザー数が 50 人の段階で 5 万人向けに構築しないでください)。該当する場合は、最初にメッセージキューの背後へ移す低速なワークロードも決めます。

成果物: docs/ARCHITECTURE.md の ## System Context に負荷の実態と概算値を追記し、各スケーリング施策を ## Decision Log に記録します(今すぐ採用/トリガー条件付きで先送り)。トラッカーを更新します。

完了条件: 平均およびピーク時の QPS と年間ストレージ容量が記録され、最初のボトルネックが特定され、すべてのスケーリング技術について、理由を添えて採用するか、採用のトリガーとなる数値とともに先送りするかが決まっていること。

フェーズ 4 — データに関する決定を慎重に行う(ddia-systems)

目的: コードより長く使われるレイヤーを正しく設計します。アクセスパターンに基づいて、データモデル、ストレージエンジン、一貫性を選び、慣習で決めないようにします。

概要(フォールバック): データはコードより長く存続します。アクセスパターンに合わせてモデルを選びます。多対多の関係やアドホッククエリにはリレーショナルモデル、局所性のある自己完結型の集約にはドキュメントモデル、再帰的な走査にはグラフモデルを使います。ストレージエンジンは読み取りと書き込みのトレードオフがあります(LSM は書き込みスループット、B-tree は読み取りレイテンシを重視します)。ほとんどのデータベースのデフォルトは read-committed または snapshot であり、serializable ではありません。単純な読み取り後の書き込みは、書き込みスキューを引き起こします(2 人の購入者が最後の 1 個を購入するケースなど)。不変条件を守る必要がある場合は、明示的にロックする(SELECT ... FOR UPDATE)か、serializable トランザクションを使います。読み取りが多い場合のデフォルトは、単一リーダーと読み取りレプリカの組み合わせです。レプリケーションラグがある場合は、読み取り後に書き込み結果を読み取る方法を意識して選びます。システムオブレコードと、再構築可能な派生データは分けます。

実行: フェーズ 2 の集約とフェーズ 3 のレプリカ計画から想定されるワークロードをもとに、ddia-systems スキルを使います。ワークロードごとのモデルとストレージエンジンの適合性、実際のデフォルト分離レベルとその異常、ロックが必要な読み取り後の書き込みパスを確認するよう依頼します。

ユーザーと決定する内容: (1)ワークロードごとの適合性に基づき、データストアを 1 つにするか、ポリグロット永続化にするか。(2)どのパスをロックまたは serializable トランザクションで保護し、どのパスで結果整合性を許容するか。2 つ目の読み取りパターン(検索、分析)のために、CDC で同期する派生データを持つ価値があるかどうか。

成果物: docs/ARCHITECTURE.md の ## Data & Storage Decisions に、モデル、エンジン、分離レベル、ロック対象のパス、システムオブレコードと派生データの区別を追記し、判断の根拠を ## Decision Log に記録します。トラッカーを更新します。

完了条件: 各ワークロードについて、適合性に基づいたモデルとエンジンが選定され、デフォルトの分離レベルが文書化され、書き込みスキューが起きうるすべてのパスがロックまたは serializable によって保護され、派生データがある場合は同期方法が定義されていること。

フェーズ 5 — モジュールを深く保つ(software-design-philosophy)

目的: 構造そのものが新たな問題にならないようにします。浅いクラスに細分化するのではなく、シンプルなインターフェースの背後に仕組みを隠します。

概要(フォールバック): 複雑さは敵です。あらゆる判断の基準は、システム全体をよりシンプルにするかどうかです。モジュールの深さ = 機能 ÷ インターフェースの複雑さです。深いモジュールは小さなインターフェースの背後に豊富な機能を隠しますが、浅いモジュール(クラス過多)は複雑さを隠さず、インターフェースのコストを増やします。適切なレイヤリングと深いモジュールは互いに相性がよい一方、適切なレイヤリングとクラス過多はそうではありません。情報漏洩、つまり一つの設計上の判断が複数のモジュールに反映されている状態は、重大な危険信号です。知識の各要素は一度だけカプセル化します。戦略を戦術より優先します。設計をクリーンに保つために 10〜20% を投資します。立ち上げ時の近道は、チームの成長とともに技術的負債として積み重なります。

実行方法: フェーズ 1〜2 で提案したモジュール構成を使い、software-design-philosophy スキルを適用します。統合すべき浅い中継モジュールはどれか、境界を越えて漏れている知識はどこか、計画した境界が深さをもたらすのではなく形式だけのものになっていないかを確認します。

ユーザーと決定すること: 本当に無関係な関心事まで統合しないよう注意しながら、今すぐ統合する浅いモジュールと、チームが採用する設計規約(命名、振る舞いを配置する場所、知識の要素ごとにファイルを分けること)を決定します。

成果物: docs/TECH-DEBT.md の ## Smell Inventory を拡張し、(統合を適用した)shallow-module / information-leakage の項目を追加します。また、合意した規則を ## Adopted Conventions に記録します。トラッカーを更新します。

完了条件: 浅いモジュールの各まとまりが統合されるか、修正方法とともに記録されていること、単一の設計上の判断が複数のモジュールで重複していないこと、設計規約が文書化されていること。

フェーズ 6 — 障害を前提に設計する(release-it)

目的: 依存関係が遅い、または停止しているときにシステムが崩壊せず、適切に機能を縮退できるようにします。設計時に対応しておくほうが、午前 2 時に対応するより低コストです。

概要(フォールバック): QA に合格したソフトウェアが、本番環境でも持ちこたえるとは限りません。統合ポイントが最大の障害要因です。応答がないより遅い応答のほうが深刻です。ハングした依存関係はログに何も残さず、スレッドやプールを枯渇させます。必須事項:すべての外部への呼び出しに接続タイムアウトと読み取りタイムアウトを設定すること。重要な呼び出しにはサーキットブレーカー(オープン状態への移行、即時失敗、ハーフオープン状態での復旧)を設けること。依存関係ごとにプールを分離するバルクヘッドを設けること。バックオフとジッターを伴うリトライを行うこと。すべてのリストエンドポイントをページネーションすること(上限のない結果セットは実データでクラッシュします)。安定稼働時のクリーンアップをスケジュールすること。フィーチャーフラグと後方互換性のある拡張・縮小マイグレーションにより、デプロイとリリースを切り離します。

実行方法: インテークで洗い出した外部依存関係を使い、release-it スキルを適用します。依存関係ごとのタイムアウト値とブレーカーのしきい値、バルクヘッドの配置、統合ごとの適切な縮退経路、および詳細なヘルスチェック + RED メトリクス + 拡張・縮小マイグレーションに必要な要素を確認します。

ユーザーと決定すること: ブレーカーのしきい値、専用プールを割り当てる依存関係、重要でない依存関係が停止した場合にコアフローをどのように縮退させるか、信頼できるロールバック手順を決定します。最初の 1,000 ユーザーに対しては、カオスエンジニアリングやマルチリージョンのフェイルオーバーは避けます。

成果物: docs/RELIABILITY.md を作成し、## Integration-Point Audit(依存関係 | タイムアウト | サーキットブレーカー | バルクヘッド | リトライポリシー | ステータス)、## Query & Resource Findings、## Health Checks & Metrics、## Deploy vs Release を含めます。トラッカーを更新します。

完了条件: 計画した外部への呼び出しすべてにタイムアウトが設定されていること、重要な依存関係にブレーカーとバルクヘッドがあること、すべてのリストエンドポイントがページネーションされていること、詳細なヘルスチェック + RED メトリクス + 拡張・縮小マイグレーション + 信頼できるロールバックが定義されていること、重要な経路に関する監査項目に未解決のものがないこと。

フェーズ 7 — 配線を実証し、習慣を定着させる(pragmatic-programmer)

目的: すべての層を通る実際の薄いスライスを 1 つ構築して境界がつながっていることを実証し、アーキテクチャの可逆性を保つ習慣を確立します。

概要(代替案): トレーサーバレット — 薄くても完全に実動する垂直スライスを 1 つ(HTTP → ユースケース → リポジトリ → DB → 戻り)構築し、本番コードとして維持します。2 日目からエンドツーエンドのフィードバックを得て、作り込む前に境界がつながっていることを実証します。可逆性:各ベンダーを自分たちのインターフェースの背後に抽象化します(分岐路テスト — 1 週間で DB や LLM プロバイダーを切り替えられますか?)。直交性:要件を 1 つ大きく変更したとき、変更が 1 つのモジュールに収まるようにします。DRY の対象は知識であり、偶然の類似ではありません。重複したルールは統合し、似ているだけのものはそのままにします。割れ窓理論:最初のハックを修正するか、追跡チケットを作成してふさぎます。

実行: フェーズ 1 の境界を踏まえて pragmatic-programmer スキルを使用します。すべての層を通る、最も薄いエンドツーエンドのトレーサーバレット、各ベンダーのアダプターインターフェース、そして 1 つの変更が多数のモジュールに影響する箇所やベンダー API がビジネスロジックに漏れる箇所の監査を依頼します。

ユーザーと決定する事項: トレーサーバレットとするスライス(認証されたコアアクションを 1 つ、機能は最小限)、割れ窓ポリシーとイテレーションごとの負債予算、最初に独自インターフェースを設けるベンダーを決めます。

成果物: docs/TESTING.md の ## Test Strategy、## Safety Net Map(トレーサーバレットの経路を最初のエンドツーエンドテストとして記載)、## CI Gates を拡張します。docs/TECH-DEBT.md の ## Debt Budget & Broken-Windows Policy と ## Adopted Conventions(可逆性、直交性)を拡張します。トラッカーを更新します。

完了条件: トレーサーバレットのスライスがすべての層を通じてエンドツーエンドで動作し、最初の CI ゲートとして固定されていること。各ベンダーが独自のインターフェースの背後にあること。割れ窓ポリシーと負債予算が文書化されていること。

フェーズ 8 — 本質に絞ってスコープを縮小する(37signals-way)

目的: これらの作業を出荷するかどうかを判断します。期間を固定し、スコープを調整し、推測に基づく抽象化が抱える複雑さになる前に取り除きます。

概要(代替案): 作るものを減らします — 優れた製品は、より少ない機能をうまく提供します。中途半端な製品のほうが、いい加減な製品より優れています。作業にかける価値が本当にある期間を定め、際限なく膨らむアーキテクチャを見積もるのではなく、その期間に合わせてスコープを絞ります。YAGNI:汎用プラグインシステム、イベントソーシング、ユーザーが 0 人なのに設定可能なマルチテナント機能など、推測に基づく抽象化はすべて、現在の複雑さと引き換えに、想像上の未来へ判断を先送りするものです。小さく可逆的な判断を行い、優れた判断に余裕を持たせるため、原則として断ります。元に戻すコストの高い少数の判断は、決して削りません。

実行: フェーズ 1〜7 のアーキテクチャ計画全体を踏まえて 37signals-way スキルを使用します。作業を期間固定の枠組みに整え、ローンチに不可欠なものと過剰な作り込みを分け、深追いしそうなテーマを挙げ、削除するか、動作する最もシンプルな方法に置き換える推測的な抽象化を列挙するよう依頼します。

ユーザーと決定する事項: v1 のアーキテクチャ作業にかける期間、今すぐ削る抽象化、再検討のきっかけを設けて先送りする抽象化、最もシンプルな方法に置き換える抽象化を決めます。時間を節約するために、元に戻すコストの高い判断を削っていないことを確認します。

成果物: docs/ARCHITECTURE.md の ## Decision Log に、v1 では意図的に構築しないものを追加します。docs/TECH-DEBT.md の ## Debt Ledger を拡張します(先送りした抽象化は意図的に引き受けた負債として記録し、それぞれに再検討のきっかけを記載します)。トラッカーを更新します。

完了条件: v1 のスコープが期間に合わせて確定していること。削除または先送りする抽象化がすべて、再検討のきっかけとともに Decision Log または Debt Ledger に記録されていること。時間を理由に、元に戻すコストの高い判断を削っていないこと。

オプションのフェーズ

スキル追加するタイミング成果物
team-topologies複数のチームがシステムを担当するため、モジュールの境界をチームの境界に合わせる必要がある場合(コンウェイの法則)docs/OPERATIONS.md を拡張(## Team Structure)

オプションのフェーズにも同じ運用ルールが適用されます。記載された各スキルをコアフェーズと同じように読み込んで使用し、追加条件が初めて満たされた時点で挿入します。ここでは、チームの境界に合わせるべき境界づけられたコンテキストが定義された後、つまりフェーズ 2 の直後です。

よくある間違い

間違い対策
フレームワークをアーキテクチャそのものにしてしまうクリーンアーキテクチャの依存性ルール(フェーズ 1)を適用します。フレームワークの呼び出しは内側に向け、ORM とリクエスト型は外側のリングに閉じ込めます。
必要性を証明できない規模に向けて過剰設計するまず概算で QPS とストレージの計算を行います(system-design、フェーズ 3)。インデックス付き DB 1 つとキャッシュがあれば、通常は何年も余裕があります。
過剰なクラス化に陥る深いモジュールのルール(software-design-philosophy、フェーズ 5)を適用します。浅いモジュールを大量に作るより、深いモジュールを少数にする方が効果的です。境界を設けるのは、実際に変化しやすい箇所に限ります。
データベースが実際に保証する一貫性を無視するデフォルトの分離レベルを確認し、書き込みスキューが発生しやすい経路をロックします(ddia-systems、フェーズ 4)。書き込みスキューは、単一ユーザーのテストでは必ず見逃されます。
レジリエンスをリリース後の課題として扱うタイムアウト、サーキットブレーカー、ページネーションを最初から設計に組み込みます(release-it、フェーズ 6)。タイムアウトのない低速な依存先は、すべてを停止させます。
ビルド不要と、慎重さを欠いたビルドを混同する機能と先回りした抽象化を削ります(37signals-way、フェーズ 8)。ただし、後から変更するコストが高い少数の判断は決して削りません。

プロセスを完了する

プロジェクトに応じて、取り組みの度合いを調整します。週末の開発なら、フェーズ 1 の依存性ルール、手早く定義するユビキタス言語、外部呼び出しのタイムアウト、スコープを削るフェーズ 8 の考え方に重点を置きます。数時間の作業で、数週間を節約できます。資金を得てローンチを目指すチームなら、全体を通して取り組み、実際のボトルネックや統合ポイントが見つかった時点で、データとレジリエンスのフェーズを取り入れます。

完了チェックリスト — 各項目を成果物に紐づけます。

  • 変更コストの高い各判断(境界、コンテキスト、データ/一貫性)が、却下した代替案とともに Decision Log の項目になっている(ARCHITECTURE.md)。
  • 中核となるビジネスルールが、DB、Web、フレームワークなしで実行できるよう設計されている(ARCHITECTURE.md の Layer Map に内向きの依存違反がない)。
  • すべての外部呼び出しにタイムアウトがあり、重要な呼び出しにはサーキットブレーカーがあり、すべてのリストにページネーションがある(RELIABILITY.md の Integration-Point Audit で問題がない)。
  • 境界がエンドツーエンドで接続されることをトレーサーバレットのスライスで実証し、それが最初の CI ゲートになっている(TESTING.md)。
  • v1 のスコープが許容範囲に合わせて定められ、先回りした抽象化は削除されるか、発動条件を明記して延期されている(TECH-DEBT.md の Debt Ledger)。

トラッカーを締めくくります。すべてのフェーズを done または skipped: reason にし、残りの Next Actions を ARCHITECTURE.md の Decision Log と TECH-DEBT.md に引き継いで、何も失われないようにします。その後、次のステップに進みます。製品として検証と構築がまだ必要なアーキテクチャなら、create-app スキルを続けて使用します。既存のプロトタイプをこの構造に整える必要がある場合は、improve-code-quality スキルを続けて使用します。

コメント