refactor(domain): ツリー可視性ルールをvisibleChildrenOfに単一化#72
Open
hashrock wants to merge 1 commit into
Open
Conversation
getFlatOrder/flattenToNodes/outlineRowsが「collapsedなら子を隠す、 objectノードは直接の子だけ見せて孫は隠す」というルールをそれぞれ 独立に再実装しており、コード中のコメントも "mirroring getFlatOrder" と手動同期を認めていた。domain/model.tsにvisibleChildrenOfを追加し、 3箇所とも同じ判定に委譲するよう変更(挙動は変えていない)。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CVSS2TV3EqjYHspRQ5HyYj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
観測した問題(SSoT違反)
「ノードの子がどこまで見えるか」という同一のルール — collapsedなノードは子孫を全て隠す。
objectノードは直接の子だけをカードの行として見せ、孫はカード内に隠す — が、3箇所で独立に再実装されていました。app/domain/model.tsのgetFlatOrder(キーボード操作の移動順)app/application/nodeUtils.tsのflattenToNodes(canvasレイアウト)app/application/outline.tsのoutlineRows(アウトライン/モバイル行リスト)各所のコメントがこの重複を認識していたのが根拠です(
nodeUtils.ts: 「mirroring getFlatOrder」、outline.ts: 「Mirror getFlatOrder」)。つまり実装ではなく散文コメントだけで3箇所の同期を保っていました。ドリフトのシナリオ: 新しいNodeTypeで孫を隠す挙動を追加/変更する、あるいはcollapsedの意味を拡張するとき、開発者はテストが直接紐づく
getFlatOrderは更新しても、flattenToNodesやoutlineRowsの“ミラー”実装を見落とし得ます。結果として、canvasの矢印キー移動がアウトラインに描画されないノードへ着地する、あるいはアウトラインがcanvasのレイアウトが配置しないノードを表示する、という不整合が生まれます(本リポジトリのCLAUDE.mdが定めるキーボード不変条件と同じ種類のバグですが、対象はエディタサーフェスではなく可視性です)。変更内容
app/domain/model.tsにvisibleChildrenOf(node)を追加し、上記3関数すべてがこの1つの判定に委譲するようにしました。既存挙動は変更していません(純粋なルール抽出のリファクタリング)。
visibleChildrenOfの単体テストをapp/domain/model.test.tsに追加しました。守りたい設計意図
「ノードの子孫がどこまで到達可能か」という事実は、このアプリの3つの異なる出力(キーボード移動順・canvasレイアウト・アウトライン行)すべてが依存する共有ルールであり、1箇所で定義され他はそれを参照するべきである、というSSoT原則です。今後NodeTypeやcollapsedの意味を拡張する際は
visibleChildrenOf一箇所を変更すれば3箇所すべてに反映されます。確認方法
npx tsc --noEmit -p .→ エラーなしpnpm test→ 変更前と同じ2件の失敗(editorKeymap.test.tsの Right/Left collapse系、本PRとは無関係・mainブランチでも同様に失敗することを確認済み)。それ以外は新規3件を含め全て成功(450 passed)。app/domain/model.test.ts(getFlatOrder/新規visibleChildrenOf)、app/application/outline.test.ts、app/application/objectNode.test.ts、app/application/editorReducer.test.tsを個別実行し全件成功を確認。keyboardEscape.browser.test.tsx)はこのサンドボックス環境のPlaywrightブラウザバージョン不整合により実行できず未検証です(環境起因、本変更とは無関係)。ローカル環境でのCIでの実行を推奨します。レビュー観点
visibleChildrenOfの3分岐(none/leaves/recurse)が、置き換え前の各関数のif分岐と1対1で対応していることの確認(特に「collapsedなobjectノード」はtype === "object" && !collapsedの条件が false になるため元々 leaves 分岐に入らず、collapsed優先判定と一致している点)。flattenToNodes側でcollapsed変数を可視性判定とは別にノードのプロパティ値(children: collapsed ? [] : ...,collapsed,フィールド)としてそのまま残している点が妥当か。Co-Authored-By: Claude Sonnet 5 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_01CVSS2TV3EqjYHspRQ5HyYj
Generated by Claude Code