回答A: OpenAI GPT-5.4
リアルタイム共同編集ホワイトボードのハイレベル計画
- 目標と仮定
- 1つのボードで50人以上の同時ユーザーをサポートする。
- 500ミリ秒未満のエンドツーエンドの更新可視性。
- 操作:フリーハンドストローク、テキストボックス、長方形/円、移動/リサイズ/削除。
- 全ユーザーのビューを最終的に整合させながら、強力な応答性を維持する。
- 厳密なグローバル順序付けよりも可用性と低遅延を優先する。
- ハイレベルアーキテクチャ
クライアントアプリケーション
- Web/モバイルホワイトボードUI。
- Canvas/WebGL/SVGを使用したローカルレンダリングエンジン。
- ポインター/マウス/タッチイベント用の入力キャプチャレイヤー。
- ローカル操作バッファと楽...
全文を表示 ▼
リアルタイム共同編集ホワイトボードのハイレベル計画
- 目標と仮定
- 1つのボードで50人以上の同時ユーザーをサポートする。
- 500ミリ秒未満のエンドツーエンドの更新可視性。
- 操作:フリーハンドストローク、テキストボックス、長方形/円、移動/リサイズ/削除。
- 全ユーザーのビューを最終的に整合させながら、強力な応答性を維持する。
- 厳密なグローバル順序付けよりも可用性と低遅延を優先する。
- ハイレベルアーキテクチャ
クライアントアプリケーション
- Web/モバイルホワイトボードUI。
- Canvas/WebGL/SVGを使用したローカルレンダリングエンジン。
- ポインター/マウス/タッチイベント用の入力キャプチャレイヤー。
- ローカル操作バッファと楽観的な適用。
- WebSocket over のリアルタイム同期モジュール。
- 現在のボード状態のスナップショット/キャッシュストア。
APIおよびセッションレイヤー
- 認証、ボード検出、権限、初期ボードスナップショットのロード、ボードのエクスポート用のHTTPS API。
- リアルタイムセッショントラフィック用のWebSocketゲートウェイ。
コラボレーションバックエンド
- セッションコーディネーターサービス:ボードごとの接続ユーザー、プレゼンス、カーソル、ルーティングを追跡する。
- オペレーションプロセッサー:オペレーションを検証し、シーケンスメタデータを割り当て、イベントログを永続化し、参加者にブロードキャストする。
- 競合解決レイヤー:順序付け/冪等性ルールおよびオブジェクトレベルのマージポリシーを適用する。
ストレージレイヤー
- ボード操作の永続イベントログ。
- 高速ロード用の定期的なボードスナップショットストア。
- ユーザー、ボード、ACL、セッション情報用のメタデータDB。
- ホットセッション、プレゼンス、一時的なカーソル状態用のオプションのインメモリキャッシュ(例:Redis)。
- クライアントサイド設計
レンダリングモデル
- ボードをオブジェクトのシーングラフとして表現する:
- ストローク
- テキストボックス
- 図形
- 各オブジェクトは、安定したobject_id、z_index、スタイル、トランスフォーム、created_by、タイムスタンプ/バージョンを持つ。
- フリーフォーム描画の場合、クライアントはポイントをサンプリングし、即時フィードバックのためにローカルでスムージングする。
ローカルファースト動作
- ユーザーアクションは、低い知覚遅延のためにクライアントで即座に適用される。
- クライアントは非同期でサーバーに操作を送信する。
- サーバーの確認応答は、ローカルの保留中オペレーションと正規順序を調整する。
クライアントモジュール
- プレゼンス/カーソルモジュール:軽量のカーソル/選択範囲の更新を間隔を空けて送信する。
- 同期エンジン:再接続、再送信、重複排除、および最後の確認済みシーケンスからのキャッチアップを処理する。
- 状態マネージャー:確認済み状態+保留中のローカルオペレーションを維持する。
- サーバーサイド設計
4.1 WebSocketゲートウェイ
- 永続的な双方向接続を維持する。
- ユーザー認証とボードアクセス権限の付与。
- ボード/セッションIDごとにメッセージをルーティングする。
- 水平方向にスケーリング可能。ステッキセッションは役立つが、セッション状態が外部化されていれば必須ではない。
4.2 セッションコーディネーター
- 各ボードセッションのメンバーシップを維持する。
- 参加/退出、カーソルプレゼンス、選択状態を公開する。
- Redis pub/subまたはメッセージバスを使用して、すべてのゲートウェイインスタンスが同じボードの参加者にブロードキャストできるようにする。
4.3 オペレーションプロセッサー
- クライアント操作を受信する。
- スキーマ、ボード権限、オブジェクトの存在、レート制限を検証する。
- ボードごとにサーバーシーケンス番号を割り当てる。
- 追記型イベントログに操作を書き込む。
- インメモリボード状態またはスナップショットキャッシュを更新する。
- 正規操作を接続されているすべてのユーザーにブロードキャストする。
4.4 スナップショットビルダー
- イベントログを定期的にボードスナップショットに圧縮する。
- N回の操作またはT秒ごとにスナップショット作成をトリガーする。
- ボードロード時、クライアントは最新のスナップショット+スナップショットバージョン以降のオペレーションのテールをフェッチする。
- 通信プロトコル
WebSocketをリアルタイム更新に使用
- 低遅延双方向通信に最適。
- 頻繁な小メッセージをサポート:ストローク、トランスフォーム、カーソル移動、確認。
- HTTPポーリングへのフォールバックは必要に応じてのみ、WebSocketがプライマリ。
HTTPS/REST(またはGraphQL)を非リアルタイムフローに使用
- ログイン/認証。
- ボードメタデータの取得。
- 最新スナップショット/履歴の取得。
- ボード/セッションの作成。
- エクスポート/インポート。
WebSocketメッセージタイプの例
- join_board {board_id, last_seq_seen}
- op_create_object
- op_append_stroke_points
- op_update_object
- op_delete_object
- op_reorder_object
- cursor_update
- selection_update
- ack {server_seq}
- snapshot_required / resync
- データモデルと永続化
6.1 論理ボードモデル
ボード
- board_id
- owner/team
- permissions
- latest_seq
- snapshot_version
- created_at, updated_at
描画可能オブジェクト
- object_id
- type: stroke | textbox | rectangle | circle
- version
- z_index
- style: color, width, fill, font, etc.
- geometry:
- stroke: pointsのリストまたは圧縮されたパスセグメント
- textbox: x, y, width, height, text content
- shape: x, y, width, height, rotation
- deleted flag or tombstone
操作/イベント
- op_id (冪等性用のUUID)
- board_id
- actor_id
- client_id
- client_op_seq
- server_seq
- timestamp
- op_type
- payload
- base_version or dependency metadata
6.2 永続化戦略
イベントソーシング+スナップショット
- すべてのユーザーアクションを不変の操作としてイベントログに永続化する。
- 定期的にマテリアライズされたスナップショットを保存して、ボードの再構築を高速化する。
- 利点:
- 再生と監査証跡が容易。
- 同期とリカバリが簡素化される。
- コラボレーティブなタイムラインに適している。
推奨されるストレージ分割
- メタデータはリレーショナルDBに。
- イベントログは耐久性のある追記フレンドリーなストレージに(SQLテーブル、Kafka + DBシンク、またはNoSQLログストア)。
- スナップショットはオブジェクトストレージまたはドキュメントストアに。
- Redisは一時的なプレゼンスとホットボード状態用。
- リアルタイム同期戦略
7.1 オペレーションベースの同期
- クライアントは、完全なキャンバスビットマップではなく、セマンティックな操作を送信する。
- 例:
- 長方形の作成
- ストロークSにポイントを追加
- テキストボックスTのテキストを更新
- 図形Xをデルタで移動
- オブジェクトYの削除
- これにより帯域幅が低く保たれ、マージが管理可能になる。
7.2 シーケンスモデル
- サーバーはボードごとに単調増加するserver_seqを割り当てる。
- 正規のブロードキャスト順序はserver_seqによる。
- クライアントはlast_seq_seenを追跡する。
- 再接続時、クライアントはlast_seq_seen以降の欠落しているオペレーションを要求する。
7.3 楽観的なUI
- クライアントは自身のオペレーションを即座に適用する。
- server_seqで確認されるまで保留中としてマークする。
- サーバーがオペレーションを変換/拒否した場合、クライアントは保留中のオペレーションを正規状態の上にリベースして解決する。
7.4 バッチ処理とスロットリング
- フリーハンド描画は多数のポイントを生成するため、20〜50ミリ秒ごとに、またはNポイント後にポイントをバッチ処理する。
- カーソル更新は一時的なものであり、約20〜30 Hzにスロットリングし、永続化しない。
- これにより、リアルタイム感を維持しながら負荷が軽減される。
- 競合解決
ホワイトボードには多くの独立したオブジェクトが含まれているため、単一のグローバルロックではなく、オブジェクトレベルの競合処理を使用する。
8.1 推奨アプローチ
オブジェクトごとのバージョニングと、オブジェクトタイプに応じた単純なOT/CRDTインスパイアールールを使用したオペレーションベースのモデルを使用する。
A. 独立したオブジェクト作成
- 同時作成は決して競合しない。
- 各オブジェクトにはグローバルに一意なobject_idが割り当てられる。
B. ストローク
- 描画中は各ストロークを追記専用として扱う。
- ストロークは通常、アクティブな描画状態中は作成者が所有する。
- 他のユーザーは通常、同じ進行中のストロークを変更できない。
- 一度完了すると、編集は個別のオペレーション(移動、スタイル変更、削除)になる。
- これにより、競合の複雑さが大幅に軽減される。
C. 図形とテキストボックス
- オブジェクトごとのバージョンを使用する。
- 更新にはbase_versionが含まれる。
- base_versionが現在のバージョンと一致する場合、直接適用する。
- 一致しない場合は、フィールドレベルのマージで解決する:
- 位置とサイズの編集:ラストライターウィンまたはオペレーションが可換であればトランスフォームの合成。
- 異なるフィールドでのスタイル変更はマージ可能。
- テキストコンテンツ:同じテキストボックス内での同時テキスト編集が必須の体験であれば、テキストCRDT/OTを使用する。
- リッチな同時テキスト編集がコアでない場合、各テキストボックスのアクティブなエディタロックを1つ許可するように簡略化する。
D. 削除対更新
- 削除は古い更新よりも優先される(更新がより新しいserver_seqを持ち、オブジェクトが削除解除/バージョン復元をサポートする場合を除く)。
- 後続のオペレーションを安全に識別して無視できるように、一時停止を短時間保持する。
8.2 このシステムの実用的な競合ポリシー
中程度の複雑さのホワイトボードの場合、実用的なポリシーは次のとおりです:
- server_seqによるボードレベルの順序付け。
- オブジェクトレベルのバージョンチェック。
- 図形/テキストボックスのトランスフォームとスタイルに対するラストライターウィン(編集が衝突した場合)。
- アクティブなテキストボックスコンテンツ編集に対するソフトロックまたはシングルエディタリース。
- 描画中の作成者所有権を持つ追記専用ストローク作成。
これはフルボードOTよりもシンプルであり、ほとんどの編集が異なるオブジェクトを対象とするホワイトボードには適しています。
- 50人の同時ユーザー/ボードのスケーリング処理
これが実現可能な理由
- メッセージがコンパクトで、一時的なトラフィックがスロットリングされていれば、50ユーザーは中程度。
テクニック
- 高速ファンアウトのためのメモリ/キャッシュ内のボードごとのセッションシャード。
- pub/subを介したWebSocketファンアウト。
- ストロークポイントのバッチ処理。
- 必要であればpermessage-deflateでメッセージを圧縮する。
- カーソル/プレゼンスノイズの永続化を避ける。
- 長い再生時間を避けるために十分な頻度でスナップショットを取得する。
容量の考慮事項
- メモリ内のホットボード状態:現在のオブジェクトマップ、最新のシーケンス、参加者リスト。
- ブロードキャストパスはO(ボード内のユーザー数)であるべきで、50ユーザーなら問題ない。
- 後でセッションが大きくなった場合、リージョンエッジゲートウェイを追加し、コラボレーションワーカー間でセッションをパーティション化する。
- 障害処理と信頼性
- すべてのオペレーションには、再試行時の重複排除のためのop_idがある。
- クライアントはlast_seq_seenで再接続し、見逃したオペレーションを受信する。
- ギャップが大きすぎるかスナップショットが期限切れの場合、サーバーは最新スナップショットからの完全な再同期を指示する。
- コラボレーションワーカーがクラッシュした場合、イベントログが耐久性を提供する。
- プレゼンス状態は一時的なものであり、再接続時に再構築される。
- 500ミリ秒未満を維持するための遅延戦略
- WebSocket永続接続はリクエストセットアップコストを回避する。
- クライアントサイドの楽観的なレンダリングは、ほぼ即時のローカル応答を提供する。
- コラボレーションサーバーは、メモリ内でホットセッション状態を維持する。
- リージョン展開により、ユーザーは最寄りのゲートウェイの近くに配置される。
- バッチ処理はスループットと遅延のバランスを取る。ストロークには短いフラッシュ間隔を使用する。
- データベースを各更新で再読み取りするのではなく、メモリ/キャッシュからブロードキャストする。
- セキュリティとアクセス制御
- トークン/Cookieを使用した認証済みWebSocketアップグレード。
- ボードレベルのACL:所有者/エディタ/ビューアロール。
- サーバーは、すべての操作を権限に対して検証する。
- 乱用や偶発的なフラッドを防ぐためのクライアントごとのレート制限。
- エンドツーエンドフローの例
- ユーザーがHTTPS経由でボードを開き、最新のスナップショット+テールオペレーションを取得する。
- クライアントはWebSocketを確立し、last_seq_seenとともにjoin_boardを送信する。
- ユーザーが線を描画する。クライアントは即座にレンダリングし、バッチ処理されたappend_stroke_pointsオペレーションを送信する。
- サーバーは検証し、server_seqを割り当て、イベントログに追記し、セッション状態を更新し、すべてのユーザーにブロードキャストする。
- 他のクライアントはオペレーションを受信し、ストロークを段階的にレンダリングする。
- クライアントの1つが切断された場合、再接続して最後のシーケンス以降のオペレーションを要求する。
- 推奨最終設計選択
- クライアント:ローカルファーストキャンバスレンダラー+楽観的なオペレーションバッファ。
- サーバー:WebSocketゲートウェイ+コラボレーション/セッションサービス+追記型オペレーションログ+スナップショット。
- プロトコル:リアルタイムオペレーション/プレゼンスにはWebSocket、ボードロードおよび管理APIにはHTTPS。
- 一貫性モデル:オブジェクトレベルのバージョニングによるサーバー順序のオペレーション。
- 競合解決:追記専用ストローク、図形用の単純なマージ/LWW、テキストボックスコンテンツ用のオプションロックまたはCRDT。
この設計は構築が容易で、ニアリアルタイムの共同編集ニーズを満たし、同期と競合処理を管理可能に保ちながら、ホワイトボードあたり50人の同時ユーザーに快適にスケーリングします。
判定
勝利票
2 / 3
平均スコア
総合点
総評
これは、リアルタイム共同編集ホワイトボードのための、優れた包括的なシステム設計計画です。要求されたすべての主要な側面、すなわちクライアントサイドとサーバーサイドのアーキテクチャ、通信プロトコル、データモデリング、永続化、リアルタイム同期、競合解決を網羅しています。この計画は14の明確に区分されたセクションでよく構成されており、ドメインに対する深い理解を示し、全体を通して現実的なエンジニアリングの選択がなされています。競合解決のセクションは特に強力で、異なるオブジェクトタイプを区別し、それぞれに適切な戦略を適用しています。また、再接続、障害処理、セキュリティなどのエッジケースにも対処しています。改善の余地がある点としては、CRDTとOTのトレードオフについてもう少し深く掘り下げ、具体的な技術スタックの推奨事項をさらに追加することが挙げられますが、全体としては非常に強力な回答です。
採点詳細を表示 ▼
設計の質
重み 30%アーキテクチャは適切にレイヤー化されており、関心事を明確に分離しています。クライアントレンダリング/同期、WebSocketゲートウェイ、セッションコーディネーター、オペレーションプロセッサー、スナップショットビルダー、ストレージレイヤーです。リアルタイム通信にWebSocket、非リアルタイム通信にRESTを選択したことは適切に正当化されています。イベントソーシング+スナップショットのアプローチは適切です。ゲートウェイ間のファンアウトにRedis pub/subを使用したことは堅実な選択です。アーキテクチャはゲートウェイの水平スケーリングをサポートします。1つのマイナーなギャップは、一部のコンポーネントに対する具体的な技術推奨事項の欠如ですが、アーキテクチャパターンは健全で明確に説明されています。
完全性
重み 20%この計画は驚くほど包括的で、要求されたすべての側面とそれ以上を網羅しています。ローカルファースト動作を持つクライアントサイド設計、サーバーサイドコンポーネント、例示的なメッセージタイプを持つ通信プロトコル、詳細なデータモデル、永続化戦略、同期アプローチ、オブジェクトタイプごとの戦略を持つ競合解決、スケーラビリティの考慮事項、障害処理、レイテンシ戦略、セキュリティ/アクセス制御、エンドツーエンドのフロー例です。要求された自由形式の線、テキストボックス、形状を扱っています。プレゼンス/カーソルシステムもカバーされています。ギャップはほとんど存在しません。
トレードオフの説明力
重み 20%この計画は、いくつかの分野で良好なトレードオフの推論を示しています。厳密なグローバル順序付けよりも可用性と低レイテンシを選択すること、グローバルロックではなくオブジェクトレベルの競合処理を使用すること、形状に対する実用的なLWW対テキスト編集に対するオプションのCRDT/ロック、スループットとレイテンシのバランスをとるためのストロークポイントのバッチ処理、純粋な状態ベースの永続化よりもスナップショットを持つイベントソーシングを選択することです。テキストボックスのソフトロックとCRDTの使い分けに関する議論は、ニュアンスのある思考を示しています。しかし、OTとCRDTアプローチの比較、それらの文脈におけるそれぞれの長所/短所、そしてハイブリッドアプローチが純粋なCRDTまたは純粋なOTソリューションではなく選択された理由を説明することについて、さらに深く掘り下げることができたでしょう。
拡張性・信頼性
重み 20%この計画は、メッセージバッチング、カーソル更新のスロットリング、ファンアウトのためのpub/sub、ホットステートをメモリに保持するなどの技術により、50人の同時ユーザーのスケーラビリティにうまく対応しています。信頼性セクションでは、op_idによるopの重複排除、last_seq_seenによる再接続、フルリシンクフォールバック、イベントログの耐久性をカバーしています。レイテンシのためにリージョナルデプロイメントが言及されています。計画では、50人を超えるスケーリングにはエッジゲートウェイとセッションパーティショニングが含まれる可能性があると述べています。データベースのスケーリング、レプリケーション戦略、災害復旧については、もう少し詳細であった可能性がありますが、コアのスケーラビリティと信頼性の懸念はよく対処されています。
分かりやすさ
重み 10%この計画は、14の番号付きセクション、明確な見出し、一貫したフォーマットで、例外的に整理されています。箇条書き、サブセクション(例:8.1 A/B/C/D)、エンドツーエンドのフロー例の使用により、非常に理解しやすくなっています。技術的な概念は、不必要な専門用語なしに明確に説明されています。セクション14の要約は、すべてを効果的にまとめています。記述は簡潔かつ包括的です。
総合点
総評
強力で一貫性のあるシステム設計であり、適切なリアルタイムアーキテクチャ(WebSockets、セッション調整、op log + スナップショット)で必須機能を処理し、ホワイトボードに合わせた実用的な同期/競合戦略を提供しています。操作、シーケンス、再接続/キャッチアップを明確にモデル化し、一時的なプレゼンスと永続的な状態を分離しています。トレードオフ(実用的なLWW/ロック対完全なOT/CRDT)が議論されていますが、エッジケース(例:同時移動/リサイズ合成セマンティクス、クロスリージョンレイテンシの影響、正確な一貫性保証)の詳細な分析はさらに明確にできる可能性があります。信頼性/スケーリング計画は50ユーザーにとっては堅実ですが、一部の側面(正確なシャーディング戦略、バックプレッシャー、水平スケーリングされたゲートウェイ間のメッセージ順序)はさらに改善される可能性があります。
採点詳細を表示 ▼
設計の質
重み 30%明確な高レベルアーキテクチャと適切に選択されたコンポーネント:クライアントローカルファーストレンダラー+ opバッファ、WebSocketゲートウェイ、セッションコーディネーター、操作プロセッサー、スナップショット付きイベントソーシング、および個別のメタデータ/プレゼンスストア。責任とデータフローの分割は、500ミリ秒未満のコラボレーションにとって合理的です。
完全性
重み 20%要求されたすべての領域をカバーしています:マルチユーザーセッション、描画/テキスト/図形操作、ニアリアルタイム伝播、50ユーザーセッション処理、プロトコル選択、データモデリング、永続化、同期、再接続、競合処理。主要な操作の具体的なAPI/スキーマ例と、選択した場合のテキストCRDTの統合方法に関する深さがわずかに不足しています。
トレードオフの説明力
重み 20%WebSockets、opベースの同期、スナップショット付きイベントソーシング、および実用的な競合ポリシー(追記専用ストローク、LWW、オプションのテキストボックスロック/CRDT)の優れた正当化。完全なOT/CRDTとのトレードオフが言及されていますが、LWW/ロックがUXに与える影響、および同時変換の変換/可換性に関する詳細についての議論を強化できます。
拡張性・信頼性
重み 20%50ユーザー向けの合理的なスケーリングアプローチ:バッチング/スロットリング、pub/subファンアウト、水平ゲートウェイのスケーリング、一時状態用のRedis、永続的なop log、op_idによる重複排除、およびシーケンス番号/スナップショットによるキャッチアップ。バックプレッシャー、ストロークフラッド下でのレート制限、および複数のプロセッサが導入された場合のメッセージ順序保証について、さらに詳しく説明できます。
分かりやすさ
重み 10%構造化されており、理解しやすく、具体的な用語(server_seq、last_seq_seen、op_id、snapshots)を使用しています。競合解決セクションは特に読みやすく、ポリシーをオブジェクトタイプにマッピングしています。
総合点
総評
設計計画は非常に包括的かつ構造化されており、リアルタイム共同編集ホワイトボードのための堅牢なアーキテクチャを提供しています。リアルタイム同期、競合解決、スケーラビリティの詳細な戦略を含む、プロンプトからのすべての要件を綿密に検討しています。トレードオフと技術および整合性モデルのための実践的な選択肢の明示的な議論は、問題空間に対する深い理解を示しています。
採点詳細を表示 ▼
設計の質
重み 30%提案されたアーキテクチャは、よく定義されており、モジュール化されており、リアルタイム共同編集アプリケーションに非常に適しています。クライアントサイド、API/セッション、コラボレーションバックエンド、ストレージレイヤーを明確に区分し、リアルタイム通信のためにWebSockets、静的データのためにRESTを効果的に利用しています。永続化のためのスナップショット付きイベントソーシングの選択は堅牢で、よく正当化されています。
完全性
重み 20%応答は、プロンプトによって要求されたすべての側面をカバーし、それを超える、信じられないほど徹底した計画を提供します。クライアントサイド設計、サーバーサイドコンポーネント、通信プロトコル、データモデリング、永続化、リアルタイム同期、競合解決を模範的な詳細で詳述しています。スケーラビリティ、信頼性、セキュリティ、およびエンドツーエンドフローの例に関する追加セクションは、その完全性をさらに高めます。
トレードオフの説明力
重み 20%この計画は、特に厳密なグローバル順序付けよりも可用性と低レイテンシを優先するという選択において、主要なトレードオフを効果的に明確にしています。競合解決に対する実践的なアプローチであり、完全なOperational Transformation(OT)またはConflict-free Replicated Data Types(CRDT)ではなく、特定のオブジェクトタイプに対してオブジェクトレベルのバージョン管理とよりシンプルなLWW/作成者所有権を選択することは、ホワイトボードのコンテキストでうまく正当化されています。楽観的UIとその調整の必要性の議論も、健全な推論を示しています。
拡張性・信頼性
重み 20%設計には、WebSocketゲートウェイの水平スケーリング、ファンアウトのためのPub/Subの使用、メッセージのインテリジェントなバッチ処理とスロットリング、一時データと永続データの分離など、スケーラビリティのための強力な戦略が組み込まれています。信頼性は、重複排除のための操作ID、シーケンス追跡による堅牢なクライアント再接続ロジック、およびイベントソーシングによって提供される耐久性によって対処されます。これらの対策は、ボードあたり50人以上の同時ユーザーを効果的にサポートします。
分かりやすさ
重み 10%計画は非常に明確で、明確なセクションとサブセクションで論理的に構成されており、正確でプロフェッショナルな言語を使用しています。概念は理解しやすい方法で説明されており、構造は可読性を大いに助け、高レベルの目標から複雑な詳細まで、提案された設計を楽に追跡できます。