# GUI知識

画面（Webではページ）がRootのMediatorとなり、独立した状態を持つ領域のコンポーネントが子のMediatorとなる。表示部品はPassive Viewとし、表示、操作の通知、操作の処理を分ける。状態と操作判断の所有者は利用範囲・寿命に合わせ、不要な独自の状態保持・購読・操作処理の層を増やさない。

画面・領域のMediatorには、採用フレームワークで標準的な、その画面・領域に対応する状態保持オブジェクト（画面に対応するViewModel、参照型の状態所有者、Angularのcomponent単位のserviceなど）と、画面専用hookによる実装分割を含む。

許容構成は、画面・領域に対応するフレームワーク標準の状態保持実装、画面専用hookによる実装分割、採用済みの状態管理・取得基盤の利用、または独立した状態所有者を必要とする共有・寿命の要件に基づく構成である。画面の再描画をまたいで保持することや、画面内の複数部品が使うことだけでは、独自の状態所有者を新設する根拠にならない。

許容構成に該当しない、画面内の状態と操作判断を移し、画面を委譲と描画だけにする独自層は新設しない。名前や標準の購読APIへの接続だけでは標準構成にならない。別の独自状態所有者へ委譲するだけのhookも、画面専用hookによる実装分割には含めない。

## Rootから始まる階層

Rootは画面（Webではページ）自身であり、最上位のMediatorとして状態を持ち、操作を受理または拒否し、次の状態を決め、子へ値と操作の通知先を渡す。画面は領域や表示部品を組み合わせる。画面内に独立した状態と操作を持つ領域があれば、その領域のコンポーネントが子のMediatorとして状態と操作を管理する。Passive Viewの表示部品は担当する画面や領域へ操作の意図を通知し、複数の領域が共有する状態や領域間の調整は親が受け持つ。

状態は、同じ値を使う範囲と、その値が残る時間に合う画面や領域で管理する。

## Passive Viewの役割

Passive Viewの表示部品は、上位の画面や領域から渡された表示内容と操作の可否を描画し、利用者の操作の意図を担当する画面や領域へ通知する。操作を受理または拒否する判断、その後の通信・遷移・次状態の決定を表示部品へ持ち込まず、画面や領域が処理を受け持つ。

部品内だけで使う入力途中の値や開閉状態は、その部品で管理する。複数の部品が扱う対象の識別子や処理の進行状態は、それらを調整する画面または領域で共有する。Providerや外部storeは許容構成の範囲で値の利用範囲・寿命に合わせて使う。画面が値と操作を作り、画面内の複数部品へProviderで配る構成も含む。フォームなど画面ローカルの編集状態は原則画面に置き、サーバーデータの取得状態とキャッシュは採用した取得基盤の責務として扱う。

## Chain of Responsibilityで未担当の操作を渡す

部品が担当しない操作は、操作の通知を受けた上位へ順に渡す。各階層は自分が担当する操作だけを処理し、処理した操作を別の階層で再実行しない。

## 画面や領域のコンポーネントがMediatorとして状態に応じて処理する

画面や領域のコンポーネントはMediatorとして状態を持ち、操作の通知を受け、現在の状態と対象を見て、操作を受け入れるか拒否するか、受け入れた操作に必要な処理の開始、次の状態、表示を決める。表示内容だけでなく、操作の可否と表示対象・処理対象の整合も同じ判断から定まる。同時に実行できない操作は、処理中の再実行を防ぐ。

引数から新しい値や真偽を返す純粋関数は別ファイルに分けられる。検証、一覧の追加・合算、差分判定、価格計算、reducer関数などがこれに当たる。画面固有の型・API・状態を直接扱い、画面の判断を閉じて持つ画面専用custom hookへの切り出しも、画面の実装分割として扱う。別のMediator層を新設するものではない。通信だけを行うAPI関数も分離できる。

操作要素の無効化やモーダル表示だけに依存せず、クリックやキーボードなど異なる入口からの通知も同じMediatorの状態判断を通す。操作を受け入れた場合だけ処理を開始し、拒否した操作は処理を開始せず、その場で結果を示す。成功、失敗、入力不備、権限不足などの結果を状態へ反映して表示を更新する。未担当の操作だけを上位へ渡す。

確認への回答を待たずに、対象や入力、保存状態など、判断の前提を変える操作は処理担当が拒否する。確認対象に影響しない独立した操作は、仕様が許す範囲で継続できるようにする。処理中も同じように、同じ処理の重複実行や競合する操作を止める範囲と、独立して続けられる操作を分ける。

画面や領域のコンポーネントはMediatorとして、現在の状態と操作から次の状態を決める。専用の状態機械の仕組みを要求するものではない。画面内のuseReducerや、props、callback、binding、hook、Context、form actionなど、フレームワークの標準の仕組みで役割を実現できる。祖先が渡したcallbackやContextの操作で、担当する画面や領域へ直接通知できる。処理担当が現在の状態に応じて操作を受理または拒否し、処理後の状態と表示を決めることを確認する。

## 参考資料

- Martin Fowler: Passive View
  https://martinfowler.com/eaaDev/PassiveScreen.html
