コードレビューで上長から指摘された3点と、実装中に気付いたこと2点を書いています。
レビューコメント
1. 「ComponentをComponent内にinlineで定義するのは非推奨です」
- 理由:コンポーネントが再描画されるたびに、中のコンポーネントが再計算されて新規に定義される。パフォーマンス上の問題
- 対応:別コンポーネントとして切り出す
2. 「discriminated unionを利用してほしい」
-
type State = | { status: "loading" } | { status: "success"; data: string } | { status: "error"; error: string };- status: 判別用のプロパティ
- プロパティを見て候補を絞る
- errorなのにdataが存在するというあり得ない状態を作ることが無い
- 網羅性チェック:
const exhaustiveCheck: never = state;を入れると全パターンを処理したかチェックしてくれる- 追加したstatusのswitch文を書き忘れるとエラーになり、追加漏れをコンパイラが教えてくれる
3. 「Parse, don't validateです」
- TypeScriptなどでデータを扱うときの設計思想
- 境界で不正なデータを排除して、アプリ内部には正しいデータだけを入れる
- APIから来るJSONは特に信用できない
- Parseしてからアプリ内部へ渡すようにする
- 外部データを、アプリが使いやすい「信頼できるデータ」に変換するという意味でparse
- Parseしてからアプリ内部へ渡すようにする
- Zodがよく使われる
- アプリ内部では、もうチェック済みだからこの型を信じて良い、という状態にできる
- APIから来るJSONは特に信用できない
- Discriminated Unionとの関係
- Parse:外部の信用できないデータを、正しいドメインモデルにする
- Discriminated Union:その正しいデータの状態を、型として表現する
実装中に気付いたこと
1. 最初からAIに頼りすぎると、修正に時間がかかる
- ゼロの状態からAIに書かせると、その設計思想に沿った修正しかできなくなる
- 今回の例:AIの書いたコードを理解→おかしい所を突っ込む→芋づる式で突っ込みが増える→ほぼ全部作り直し
- 先にデータや状態の設計を行ったうえで、それを元にAIに実装してもらうべきだったと反省
- そのためには設計思想を基礎からしっかり学ばなければならない
2. Claude:同セッション内でモデルを変更すると、消費量が大きい
- 新モデルが履歴を読み込むのにトークンをかなり消費してしまうらしい
- 長くなったセッションほど、切替コストがかかるのかも
- どうして気付いたか
- スタンダードシートだから
- 使用可能トークンが少なく、数回実行するたびに消費量を確認し、「まだ80%だから余裕やな」「あと20%しかないやん!effort下げないと!」と一喜一憂している
- チーム内でプレミアムシートが枯渇しており、以前奪われたまま返ってきていない
- スタンダードシートだから
6カ月計画の進捗
↓ 6カ月計画とは
1カ月目:TypeScript / Reactの設計基礎
TypeScript
-
基本型・
interface/type - Union Type / Discriminated Union
- Generic / Utility Types
-
型ガード /
unknown/never - optional / nullable
- 型設計
- Parse, Don't Validate
- Zodの基本
React
- Component / Props / State / Event
- Effect / Custom Hook / Context
- Form / Error Boundary
- Componentの責務・分割
- Stateの所有者
- Local / Global / Server / URL / Form State
実践
- TODOアプリの要件を整理
- データ・State・Componentを自分で設計
- 設計をもとにClaude Codeで実装
- 生成されたコードを読んでレビュー
- AIの提案を自分で判断・修正
- 設計上の判断を記録
アウトプット
- TODOアプリ完成
- 設計ドキュメント作成
- Qiitaで週報を書く
- 1ヶ月目の振り返りを書く
1ヶ月目のゴール
- 「なぜこの型・State・Component構成にしたのか」を自分の言葉で説明できるようになる。