システム設計を最初に
ほとんどのチケットは何を構築するかを記述し、それが本番環境で生き残るかどうかを決める質問を隠しています:ユーザー数、頻度、データ量、依存関係が遅いときの対処、2人のライターが競合したときの真実の所有者。このスキルは、コードが書かれる前に、タスクの作成者が読んで反論できる形で、これらの質問を明示的にします。
プロセスは:スコープ → 見積もり → ハイレベル設計 → 深掘り → まとめ。実際の作業に適用します:既存のコードベース、意図を持った作成者、予算があります。目標は、システムの観点から機能の明確な全体像を得ることです。
ユーザーが書く言語で返信してください。概要はあなたのためではなく、彼らのためのものです。
1. 最初に深さを見極める
タイプミスの修正を過剰に設計することは、支払いフローを過小設計することと同じくらい間違っています。レベルを選択し、1行で述べ、それに応じて時間を費やします。
| レベル | 典型的なタスク | 生成するもの |
|---|---|---|
| L0 – 自明 | コピー変更、リネーム、スタイル調整、ローカルな修正で済む明白なバグ | 追加のものはなし。隠れたリスクが存在する場合(「このラベルはCDNに24時間キャッシュされている」)、最大1文。その後、単にタスクを実行する。 |
| L1 – ローカルな変更 | 新しいフィールド、新しいフィルター、小さなエンドポイント変更、フック、クエリの調整 | インラインでの設計チェック(3〜7行):何に触れるか、それが乗る負荷、注意すべき1つのこと(N+1、キャッシュ無効化、ページネーション、冪等性)。その後、実装する。 |
| L2 – 機能 | データフローを伴う新しい画面、新しいエンドポイント+ストレージ、通知、検索、エクスポート、サードパーティとの統合 | 設計概要(セクション4)、約1ページ。その後、概要に従って実装する。 |
| L3 – サブシステム | 新しいサービス、リアルタイムチャネル、イベントパイプライン、マルチテナントデータモデル、ホットパスの移行、「スケール」という言葉がチケットにあるもの | 完全な概要に加えて、リスクの高いコンポーネントごとの深掘り、検討した代替案、移行パス、リリース後の測定項目。 |
タスクを上げるシグナル:ユーザー向けレイテンシ、同時書き込み、ファンアウト(1つのイベント → 多数の受信者)、テーブルまたはリストの無制限な成長、サードパーティのレート制限、お金、PII、スケジュールで実行されるもの、または明らかに残る「一時的な」ソリューション。タスクを下げるシグナル:ユーザー数が少ない内部ツール、メモリに永久に収まるデータ、キルスイッチ付きの機能フラグ実験。
ユーザーが明示的に設計レビューまたはより深い分析を要求した場合は、サイズに関係なくL3として扱います。
2. プロセス、ステップバイステップ
これらを順に進めてください。L1の場合は数行に圧縮します。L2/L3の場合は各ステップが概要のセクションになります。references/framework.mdには各ステップの質問チェックリストがあります。セッションで初めてL2+のプロセスを実行するときに読んでください。
ステップ 1 — 理解とスコープ
- 機能をシステムがどのように見るかで1段落で言い換えます:アクター、トリガー、入力、出力、副作用。
- 機能要件(何をするか)と非機能要件(どれだけうまく:スケール、レイテンシ、可用性、一貫性、耐久性、セキュリティ、コスト、運用性)を分離します。チケットは2番目の種類をほとんど明記しません。製品コンテキストから推測し、推測したと明記します。
- スコープ外を書き留め、概要が静かに拡大しないようにします。
- 作成者の意図を収集します:チケットテキスト、PR説明、コメント、リンクされた設計、既存のADR、このリポジトリで類似機能がどのように構築されたか。作成者は通常、頭の中に設計を持っています。それを置き換えるのではなく、表面化させます。
- 設計を実質的に変える質問のみユーザーにします(例:「これは1秒以内に表示される必要がありますか、それとも1分で十分ですか?」)。それ以外については、仮定を述べて先に進みます。仮定は概要に入れます。
ステップ 2 — 見積もり
数値は意見を決定に変えます。チケットに数値がない場合でも、ざっくりとした見積もりを行います。references/estimation.mdには参照数値(レイテンシラダー、2のべき乗、可用性の9's、ノードあたりの容量)と計算例が含まれています。
- ユーザー/テナント → デイリーアクティブ → 1日あたりのアクション → 平均およびピークQPS(ピークは通常平均の2〜5倍、バーストフローではそれ以上。例えば「全員が9:00にアプリを開く」など)。
- 読み取り/書き込み比率、ペイロードサイズ → 1日/年あたりのストレージ、帯域幅。
- 成長:製品が成功した場合の12か月後の数値はいくつか。
- 実際の数値が存在する場合(分析、DB行数、既存のダッシュボード、構成制限)、それらを使用し出典を明記します。それ以外の場合は範囲を指定し、仮定であることをマークします。
次に、数値を使用してパターンを排除します。単に正当化するためだけではありません。「PostgreSQLテーブルにインデックスがあれば、書き込みが30/sなら問題ありません。スループットのためにキューは必要ありません。再試行とメールプロバイダーからのデカップリングが必要な場合のみ必要です。」
ステップ 3 — 現在の設計をマッピングする(as-is)
コードを記述する前に読んでください。実際のファイル、モジュール、テーブル、エンドポイント、ジョブ、キャッシュ、キューに名前を付けます。コンポーネントを発明しないでください。
- 機能が触れるコンポーネントはどれですか?短いテキスト図でデータフローを描きます(
client → BFF → service → Postgres、event → queue → worker)。 - 状態はどこにあり、誰が所有していますか(DB、キャッシュ、クライアントストア、URL)?
- 再利用可能な既存のプリミティブはありますか(outboxテーブル、ジョブランナー、クエリキャッシュ、WebSocketハブ、共有
Paginationコンポーネント)? - ホットパス、既知のボトルネック、既存のSPOF、機能が継承する現在の制限(レート制限、ページサイズ、タイムアウト)。
- フロントエンドタスクの場合、as-isは依然としてシステムです:データ取得レイヤー、キャッシュポリシー、バンドル境界、リアルタイムトランスポート —
references/frontend.mdを参照してください。
ステップ 4 — ターゲット設計を提案する(to-be)
作成者の意図から始めます。それが妥当であれば、そう言って引き締めます。数値やよく知られた障害モードと矛盾する場合は、その結果を伴う矛盾を示し、それを修正する最小の変更を提案します。決定するのは作成者です。あなたの仕事はトレードオフを可視化することです。
- テキスト図としてのハイレベル設計、さらにAPIコントラクト(形状を持つエンドポイント/イベント/メッセージ)とデータモデル(テーブル、キー、インデックス、保持期間)。
- 自明でない選択ごとに、パターンと拒否した代替案を、ステップ2の数値に結びつけた理由とともに挙げます。
references/patterns.mdがカタログです:スケーリング、キャッシング、非同期/キュー、データストアと一貫性、APIスタイルとリアルタイムトランスポート、レート制限、ID生成、信頼性、可観測性 — それぞれに「いつ使うか/いつ避けるか/トレードオフ」があります。 - 機能を適切な標準システムにマッピングします(「これは通知システムです:キュー + チャネルごとのワーカー + 重複排除」、「これはニュースフィードファンアウトです」、「これはレート制限装置です」)。カタログの最後のセクションに、標準的な形状とその標準的な構成要素がリストされています。類似性により、読者に既知の参照点と、そのようなシステムが通常必要とするもののチェックリストを提供します。
- リポジトリの既存のプリミティブと、数値を満たす十分な余裕がある最も単純な設計を優先します。どのアップグレードが延期され、どのシグナルがそれらをトリガーするかを明示的に述べます(「このクエリのp95が200msを超えるか、テーブルが5000万行を超えたら、読み取りレプリカを追加する」)。
ステップ 5 — 壊れる可能性があるものの深掘り
L2の場合は最もリスクの高い1つまたは2つの部分を選びます。L3の場合はすべてを検討します。標準的な質問を、問題を起こす頻度のおおよその順に並べます:
- 並行性と冪等性 — 二重送信、再試行、2人の書き込み、少なくとも1回の配信。冪等性キーはどこにあるか?一意制約は何か?
- 一貫性 — 誰がどのくらいの期間古いデータを読み取るか。それは許容できるか。キャッシュ無効化パス。自分の書き込みの読み取り。
- 依存関係の障害 — プロバイダーダウン、キュー遅延、リモートモジュールの読み込み失敗。タイムアウト、ジッター付き再試行、サーキットブレーカー、グレースフルデグラデーション、ユーザーに表示されるもの。
- ホットスポット — ホットキー、有名人テナント、無制限リスト、N+1、フルテーブルスキャン、インデックス欠如、キャッシュ有効期限切れ時のサンダリングハード。
- 成長 — 無制限に成長するテーブル/リスト/キュー。保持、アーカイブ、ページネーション(オフセットではなくカーソル)、パーティショニング。
- 移行とロールアウト — バックフィル、デュアルライト期間、フィーチャーフラグ、ロールバックパス、後方互換性のあるコントラクト変更。
- セキュリティとプライバシー — データレベルの認可(テナント分離)、ログ/キュー内のPII、パブリックエンドポイントのレート制限、入力検証。
- 可観測性 — どのメトリクスが機能することを証明するか(SLI)、機能しない場合にどのアラートが発報するか、単一のリクエストをデバッグするために何をログに記録するか。
ステップ 6 — まとめ、可視化の提供
図はトークンを消費するため、オプトインです。概要自体は1行のテキストフロー(client → API → Postgres)のみを使用します。
L2およびL3の場合、概要を1つの質問と未解決の質問で締めくくります。ユーザーの言語で:
アーキテクチャを描きますか? 1 — ターミナル内のas-is/to-be図 2 — デザインフォルダ付き(Mermaid +
architecture.html) 3 — しない
- ユーザーが1または2を選択した後にのみ、
references/visualization.mdに従って描画します。回答を待たずに実装を開始します。ユーザーが回答せずに先に進んだ場合は、「しない」とみなします。 - ユーザーがすでに図、画像、可視化、またはデザインフォルダを要求した場合のみ、質問をスキップしてすぐに描画します。
- 誰も回答できない場合(非対話型実行、CI、評価)、描画も質問もしません。図はリクエストに応じて利用可能であることを1行で述べます。
- L0またはL1では絶対に提供しません。
概要(次のセクション)を作成し、その後タスクを続行します:概要に従って実装し、概要をPR/MR説明にも残し、未解決の質問を黙って決定するのではなく、作成者にリストします。
3. 判断ルール
- 数値が先、パターンは後。 それらを必要とする見積もりなしに、Kafka、シャーディング、CQRS、専用キャッシュクラスター、マイクロサービスを決して推奨しないでください。シンプルさは機能です。複雑さはその地位を獲得しなければなりません。
- 説明し、講義しないでください。 各推奨事項には、作成者が検証できる1文の「なぜ」が含まれます。標準システムへの類似性は歓迎します。バズワードのリストは歓迎しません。
- 作成者の設計を尊重してください。 不同意は「Xは負荷ZでYを引き起こします。最も安価な修正はWです」と提示します。それでも作成者が自分の方法を好む場合は、その方法を実装し、概要にリスクを記載します。
- 既存のコードは証拠です。 それを読んでください。存在しないコンポーネントを説明する概要は、概要がないことよりも悪いです。
- 必須とあったらいいものを分離してください。 各推奨事項を「今すぐ必要」、「リリース前に必要」、または「約Nユーザー時に必要」としてマークします。
- フロントエンドもカウントされます。 クライアントキャッシング、ページネーション、楽観的更新、リアルタイムトランスポート、バンドル境界、障害分離はシステム設計です。
references/frontend.mdは各ステップのクライアント側バージョンをカバーしています。 - ユーザーの言語と語彙に従ってください。 チームがそうする場合はパターン名を翻訳します。最初の出現時には英語の用語を括弧内に残します。
4. 設計概要
L2およびL3にはこの構造を使用します。見出しは維持します。セクションが本当に空の場合のみ削除し、1行でその旨を述べます。L2の場合は約1ページを目標とします。references/brief-template.mdには記入例とコンパクトなL1インラインフォームがあります。
# 設計概要: <機能>
**深さ:** L2 · **ステータス:** 提案 · **作成者の意図:** <1行>
## 1. スコープ
機能: ...
非機能(明記がない限り推測): スケール · レイテンシ · 可用性 · 一貫性 · セキュリティ · コスト
スコープ外: ...
仮定: ...
## 2. 見積もり
| メトリクス | 現在 | +12か月 | ソース |
| --- | --- | --- | --- |
| DAU / テナント | | | |
| ピークQPS(読み取り/書き込み) | | | |
| ストレージ成長 | | | |
結論: <数値が許可/禁止するもの>
## 3. 現在の設計(as-is)
<1行テキストフロー> · 状態所有権 · 再利用可能なプリミティブ · 継承された制限
ファイル: ...
## 4. ターゲット設計(to-be)
<1行テキストフロー> · APIコントラクト · データモデル · 標準システム類似性
パターン選択: <パターン> — 理由: <理由>; 拒否した代替案: <代替案> — 理由: <理由>。
## 5. リスクと深掘り
1. <リスク> → 緩和策(今すぐ必要 / リリース前に必要 / Nユーザー時に必要)
...
## 6. ロールアウト、移行、可観測性
フラグ、バックフィル、ロールバック · SLI + アラート · ログに記録するもの
## 7. 作成者への未解決の質問
- ...
- アーキテクチャを描きますか? 1 — ターミナル図 · 2 — デザインフォルダ付き · 3 — しない
## 8. 実装計画
各ステップがレビュー可能な大きさの、順序付けられたステップ。
5. 参考文献 — いつ何を読むか
| ファイル | 読むタイミング |
|---|---|
references/framework.md | セッションでの初回L2+のプロセス実行時:ステップごとの質問チェックリスト、NFRリスト、作成者の意図の抽出方法、分析のアンチパターン。 |
references/estimation.md | 数値が必要な場合:レイテンシラダー、9's、ノードあたりの容量、QPS/ストレージ計算、計算例。 |
references/patterns.md | パターンの選択または正当化時。機能を標準システム(チャット、フィード、通知、検索オートコンプリート、ファイル同期、レートリミッター、KVストア、ID生成、支払いなど)にマッピングする場合。目次あり。 |
references/frontend.md | タスクがUI / SPA / マイクロフロントエンドの変更の場合:データ取得キャッシュ、ページネーション、リアルタイム、バンドル境界、障害分離、クライアント側の数値。 |
references/brief-template.md | 概要の作成時:完全なL2の例とコンパクトなL1インラインフォーム。 |
references/visualization.md | ユーザーが図を要求した場合のみ(ステップ6)。図の描画:ターミナルボックス図のルール、Mermaid規則、デザインフォルダ構成、assets/architecture.htmlの埋め方。 |