Files
jrshikoku/docs/refactoring-backlog.md

282 lines
14 KiB
Markdown

# リファクタリング残件チェックリスト
最終確認日: 2026-08-31
この文書は、A-1/A-2 実施後に残っているリファクタリング候補を、着手順と確認項目付きで管理するためのチェックリストです。
過去の実施記録は [REFACTORING.md](../REFACTORING.md) を参照してください。
## 現在の基準点
- [x] A-1: 外部レスポンス境界の型付け・実行時検証
- [x] A-2: navigation / ActionSheet 型の共通化
- [x] npx tsc --noEmit が成功
- [x] 既存モックデータ 94 件を train response parser で検証
- [x] git diff --check が成功
## 推奨着手順
| 順序 | ID | 内容 | 優先度 | 主なリスク |
| --- | --- | --- | --- | --- |
| 1 | A-3 | ActionSheet 呼び出し側の @ts-ignore 除去 | 高 | シート起動 payload の実動作 |
| 2 | A-4 | ストレージ境界の完全な型付け | 高 | 既存保存データとの互換性 |
| 3 | A-5 | 残存 any の分類・段階的な削減 | 中 | 外部ライブラリ型との衝突 |
| 4 | A-6 | WebView 注入スクリプトの責務分割 | 中 | 公式サイト依存・生成物 |
| 5 | A-7 | 状態管理フックの責務分割 | 中 | ポーリング・録画・復旧処理 |
| 6 | A-8 | エラー処理・ログ出力の統一 | 中 | 障害時の観測性 |
| 7 | A-9 | 大型コンポーネントの分割 | 中 | UI 差分・再レンダリング |
| 8 | A-10 | URL・タイムアウト・間隔の設定集約 | 低〜中 | 意図しない更新頻度変更 |
| 9 | A-11 | パフォーマンス測定と最適化 | 低〜中 | 計測なしの過剰最適化 |
| 10 | A-12 | 純粋関数・parser・状態遷移のテスト追加 | 中 | テスト基盤の導入コスト |
| 11 | A-13 | 命名・旧形式ファイル・生成物の整理 | 低 | import / OTA 互換性 |
## N-1 Nitro Fetch再検討のarchive記録
Status: Archived / not active backlog
Decision: Not adopted for 7.2
Current transport: Standard fetch
この項目は過去の検証結果と、明示的な再評価を開始した場合の確認項目を保存するarchiveである。ここから通常の開発作業を自動開始しない。
再開条件:
- ユーザーまたは担当者から明示的な再検討依頼がある
- Nitro Fetch / Nitro Modules側の互換性状況が変わっている
- Expo / React Native側の環境が変わっている
- 起動時クラッシュの原因を隔離検証できる
- 標準fetchをbaselineとして維持する
- 専用branch / 専用binaryで検証する
SDK57で react-native-nitro-fetch / react-native-nitro-modules をcurrent positionsへ試験導入したが、Nitro経路を有効にしたiOS/Android Preview Buildで起動時クラッシュが発生した。Nitro native libraryを同梱したまま標準fetchへ戻したA/B Buildは両OSで起動したため、7.2では採用せずarchive扱いとする。現在の依存・専用コードは撤去済み。
再開時の検証項目(現在のactive backlogではない):
- [ ] react-native-nitro-fetch / Nitro Modulesの新しい互換バージョンと既知の起動クラッシュ修正を確認する
- [ ] SDK57 / RN0.86の最小ExpoサンプルでNitro Modules初期化を再現確認する
- [ ] iOSのException Reason / native backtraceとAndroidのlogcat native backtraceを取得する
- [ ] current positionsを自動実行する前に、明示操作だけでNitro module読み込みを試す
- [ ] 標準fetchを維持した対照buildと、clean install / updateの両方を比較する
- [ ] 起動、AbortController、Response.text、headers、15秒polling、fallback、background復帰を確認する
再開時の完了条件(明示的な再評価を開始した場合のみ):
- [ ] iOS / Androidのclean installで起動時クラッシュがない
- [ ] 標準fetch版との機能・初回表示時間・メモリ差を同一端末で計測する
- [ ] native変更を含むbuild、runtimeVersion、OTA channelを分離して確認する
## A-3 ActionSheet 呼び出し側の型を完成させる
現状、登録側の payload 型は共通化済みですが、呼び出し側に型抑制が残っています。
対象候補:
- components/Menu/Carousel/CarouselBox.tsx
- components/StationDiagram/ListViewItem.tsx
- components/StationDiagram/ExGridViewItem.tsx
- components/StationDiagram/ExGridSimpleViewItem.tsx
- components/Apps/FixedPositionBox/FixedStationBox.tsx
チェックリスト:
- [ ] 上記ファイルの SheetManager.show 周辺の @ts-ignore を除去する
- [ ] 呼び出し側の payload を EachTrainInfoPayload / StationDetailViewPayload へ寄せる
- [ ] useShow、onExit、goTo の必須・任意条件を実際の呼び出しと一致させる
- [ ] SheetManager.show の全シートについて payload 省略時の挙動を確認する
- [ ] 列車情報・駅詳細・ニュース・臨時列車の手動起動を確認する
完了条件:
- 対象ファイルの ActionSheet 呼び出しに @ts-ignore がない
- npx tsc --noEmit が成功する
- payload 欠落時に画面がクラッシュしない
## A-4 ストレージ境界の完全な型付け
ASCore は型付け済みですが、AS.getItem は依存ライブラリの戻り値型に依存しています。
保存値は文字列・boolean・JSON が混在しているため、単純に全てを一つの型へ置換しないことが重要です。
チェックリスト:
- [ ] AS.getItem の戻り値を unknown またはジェネリック境界にする
- [ ] 文字列・boolean・JSON 用の読み出し helper を定義する
- [ ] false、0、空文字を「未保存」と誤判定しない
- [ ] 既存キーごとの保存形式を一覧化する
- [ ] 設定画面、通知、駅情報、録画設定の読み書きを確認する
- [ ] 旧バージョンの保存値を読める移行処理が必要か判断する
完了条件:
- storage library 由来の any がアプリ側へ漏れない
- 型変換・既定値・移行方針がキーごとに明確になっている
- 初回起動と既存ユーザーの起動の両方で設定が維持される
## A-5 残存 any の分類・削減
any は一括置換せず、次の3種類に分類してから対応します。
1. アプリ内部のデータ型不足: 優先して具体型へ置換
2. React Native / 外部ライブラリの型不足: adapter 型または最小限の型 assertion を使用
3. WebView / JSON / file 境界: unknown と parser を使用
チェックリスト:
- [ ] stateBox/useTrainMenu.tsx の globalThis / file access を境界型にする
- [ ] WebView ref、ActionSheet ref、ViewShot ref の型を具体化する
- [ ] ndView.tsx の @ts-ignore 2 箇所を、型定義または adapter で置換できるか確認する
- [ ] components/Settings と components/ActionSheetComponents の残存 any を分類する
- [ ] rg で残存箇所を一覧化し、正当な外部境界には理由をコメントする
完了条件:
- アプリ内部のモデル・props・状態に any が残っていない
- 外部境界の assertion が局所化されている
- 型抑制を消した後も型チェックが成功する
## A-6 WebView 注入スクリプトの責務分割
lib/webViewInjectjavascript.ts は約 1,600 行あり、XHR、外部データ取得、DOM 更新、列車表示、ログが同居しています。
docs/generated/ の生成物は直接編集せず、生成元と compile script を変更します。
チェックリスト:
- [ ] XHR / fetch interceptor を独立モジュールへ分ける
- [ ] UnyoHub / Elesite の取得・cache・失敗処理を分ける
- [ ] 列車位置の正規化・表示用変換を純粋関数へ分ける
- [ ] DOM 更新処理を表示単位ごとに分ける
- [ ] WebView と React Native 間の message schema を定義する
- [ ] 生成スクリプトを実行し、generated ファイルとの差分を確認する
- [ ] 公式サイトの XHR 仕様変更時に壊れる箇所をコメントで明示する
完了条件:
- 注入スクリプトの責務ごとに単体確認できる
- 生成物は scripts/compile-web-script.ts から再生成できる
- 走行位置、運用情報、外部ソース表示の動作が維持される
## A-7 状態管理フックの責務分割
stateBox/useCurrentTrain.tsx と stateBox/useTrainMenu.tsx は、取得・mock API・録画再生・UI 状態・WebView 操作が集中しています。
チェックリスト:
- [ ] current train の parser / mapper / fallback を純粋関数として切り出す
- [ ] ポーリングと AbortController の lifecycle を専用 hook に分ける
- [ ] 録画中・再生中のデータ経路を専用モジュールに分ける
- [ ] stale cache と GAS fallback の優先順位を文書化する
- [ ] useTrainMenu から設定値、mock、録画、画面 UI の責務を段階的に分ける
- [ ] unmount 後の state 更新と重複リクエストを確認する
完了条件:
- 取得元を追加・変更しても UI hook 全体を編集しなくてよい
- polling / playback / fallback の状態遷移が追跡できる
- 既存の録画・再生機能に回帰がない
## A-8 エラー処理・ログ出力の統一
React Native 側の logger と、WebView 内で実行される console logging は実行環境が異なります。
WebView 内のログを機械的に React Native logger へ置き換えない方針で整理します。
チェックリスト:
- [ ] useUnyohub.tsx / useElesite.tsx の parse/fetch error を logger または共通 error handler に寄せる
- [ ] 意図的に無視する catch に理由を残す
- [ ] network error、parse error、stale cache、user cancel を区別する
- [ ] WebView 内ログは production での出力方針を決める
- [ ] ユーザーに表示するエラーと Sentry breadcrumb の責務を分ける
- [ ] 失敗時の fallback が無限 retry にならないことを確認する
完了条件:
- 障害の種類と発生経路がログから判別できる
- 予期しない失敗を空の catch が隠さない
- ネットワーク障害時のユーザー体験が変わっていない
## A-9 大型コンポーネントの分割
行数だけを理由に分割せず、責務の境界が明確なものから着手します。
優先候補:
- components/ActionSheetComponents/TrainDataSources.tsx
- components/Apps/FixedPositionBox/FixedTrainBox.tsx
- ndView.tsx
- components/StationDiagram/StationDiagramView.tsx
- components/Settings/DataSourceSettings.tsx
低優先・要判断:
- lib/felicaStationMap.ts
- components/custom-train-data.ts
後者は大部分が静的データの可能性があるため、無理な分割より生成・ロード方式の確認を先に行います。
チェックリスト:
- [ ] 各ファイルの責務を UI、データ取得、変換、イベントに分類する
- [ ] まず純粋関数・設定・表示部品を分離する
- [ ] public props を変える場合は呼び出し側を同時に更新する
- [ ] 分割前後で画面遷移、WebView、ActionSheet の動作を比較する
- [ ] 分割を一つの大きな変更にせず、ファイル単位で検証する
## A-10 URL・タイムアウト・間隔の設定集約
既存の constants/ を利用しつつ、全てを機械的に定数化するのではなく、意味のある設定だけを集約します。
チェックリスト:
- [ ] API URL、WebView URL、GAS URL の重複を一覧化する
- [ ] timeout、polling interval、cache TTL を用途別に整理する
- [ ] ユーザー向け更新間隔と内部 retry 間隔を区別する
- [ ] 開発・本番で値を変える必要があるか確認する
- [ ] 定数化後に URL path template と実 URL の不一致を確認する
## A-11 パフォーマンス測定と最適化
先に計測し、効果が確認できる箇所だけを最適化します。
チェックリスト:
- [ ] positions WebView の初回表示、再表示、tab 切替を計測する
- [ ] TrainDataSources と駅ダイアグラムの再レンダリングを計測する
- [ ] 重い transform / sort / JSON stringify の頻度を確認する
- [ ] useMemo / useCallback の依存配列が正しいか確認する
- [ ] memo 化後に stale data やイベント callback の取りこぼしがないか確認する
## A-12 テスト追加
現状は npx tsc --noEmit が主な自動検証です。まず副作用のない処理からテスト対象にします。
チェックリスト:
- [ ] train position parser の正常系・sentinel・不正データをテストする
- [ ] position master の validation / lookup / serialize をテストする
- [ ] train data mapper の delay / Pos fallback / Direction をテストする
- [ ] ActionSheet payload の必須項目を型チェックで維持する
- [ ] storage の既定値・旧形式・false/0 の扱いをテストする
- [ ] 録画 import/export の round-trip をテストする
- [ ] CI で typecheck とテストを実行できるようにする
## A-13 命名・旧形式ファイル・生成物の整理
これは挙動変更を伴いやすいため、最後に実施します。
チェックリスト:
- [ ] StationDeteilView の綴りを変更する場合、Sheet ID と互換性を確認する
- [ ] .js / .ts / .tsx の同名・旧実装を一覧化する
- [ ] index.js / index.ts の二重管理が必要か確認する
- [ ] generated userscript と生成元の変更手順を明文化する
- [ ] import path の alias / 相対 path 方針を統一する
- [ ] rename は単独変更にして、機能変更と混ぜない
## 着手前の共通確認
- [ ] 対象範囲と変更しない範囲を issue / PR の冒頭に書く
- [ ] npx tsc --noEmit を実施する
- [ ] 変更対象の画面・データ経路を一つ以上手動確認する
- [ ] generated file を直接編集していないことを確認する
- [ ] git diff --check を実施する
- [ ] 既存の staged changes と混ぜず、差分の所有者を確認する