前回、流通業者の出荷予定登録機能を実装しました。
その際に「コンポーネント化を積極的に行った」と書きましたが、実際にやってみて感じた理想と現実のギャップについて、リアルな体験談を書いてみます。
最初の理想:「コンポーネント化すれば使い回せる」
React学習時の思い込み
React を学習した時、以下のような「教科書的な知識」を身につけました:
- コンポーネント化すると再利用できる
- DRY原則(Don’t Repeat Yourself)を守るべき
- 責務を分離して保守性を向上させる
そこで、最初に作った FlexibleShipmentTable
コンポーネントを④⑤⑥⑦の全機能で使い回そうと考えました。
理想的な構想
FlexibleShipmentTable
├── ③出荷予定登録 (planned-shipments)
├── ④生産者の出荷確認 (shipment-view)
├── ⑤生産者の伝票作成 (new-shipment)
├── ⑥OCR登録 (new-shipment)
└── ⑦出荷履歴確認 (shipments)
「1つのコンポーネントで全部カバーできる!」と思っていました。
現実:用途が違うとUIも違う
実際にできた構成
結果的に、以下の11個のコンポーネントに分かれました:
/auth/new-shipment/page.tsx
├── NewShipmentForm.tsx
├── DestinationSelect.tsx
└── OcrUpload.tsx
/auth/planned-shipments/page.tsx
├── FlexibleShipmentTable.tsx (PC用)
├── ShipmentRow.tsx
└── MobileFlexibleShipmentTable.tsx (スマホ用)
/auth/shipment-view/page.tsx
└── MobileShipmentView.tsx
/auth/destinations/page.tsx
├── DestinationForm.tsx
└── DestinationTable.tsx
/auth/shipments/page.tsx
└── CompletedShipmentTable.tsx
/auth/shipment-trader/page.tsx
└── CompletedShipmentTable.tsx (再利用予定)
なぜこうなったか
用途が違うと、必要なUIも違うことが分かりました:
- 商社の入力画面 vs 農家の確認画面
- PC表形式 vs スマホ縦並び
- 登録用 vs 表示専用
- 編集可能 vs 読み取り専用
例えば:
- 商社は複数行を一括入力したい → 表形式
- 農家は当日分だけ確認したい → シンプルな一覧
- スマホは画面が狭い → 縦並び表示
ChatGPTとの格闘
「コンポーネントを分けないといけない」論争
開発中、ChatGPTに「全部1つのコンポーネントで済ませたい」と相談しました。
私:「FlexibleShipmentTable 1つで全部できないの?」
ChatGPT:「コンポーネントは責務を分離すべきです。以下の理由で分けることをお勧めします:
- 登録と表示では責務が異なる
- PC とモバイルでは UI 構造が異なる
- 将来的な拡張性を考えると…」
結局、ChatGPTの言う通りに分けました。
実際に分けた結果
メリット:
- 各コンポーネントの責務が明確
- 修正時に影響範囲が特定しやすい
- テストしやすい
デメリット:
- ファイルが増えて把握が大変(11個のコンポーネント)
- どこに何が書いてあるか分からない
- 修正時に複数ファイルを行き来する必要がある
別のアプローチ:「3回出てきたらコンポーネント化」
後日、Claude に相談したところ、こんなアドバイスをもらいました:
Claude:「実際に同じような処理が3回出てきたらコンポーネント化を検討してみては?最初はベタ書きで作って、重複が発生してから共通化する方法もあります。」
これを最初に聞いていたら、違うアプローチを取っていたかもしれません:
- 最初はベタ書きで各画面を作成
- 重複が3回発生したらコンポーネント化を検討
- **「使い回し」より「ファイルが長すぎて辛い」**時に分割
振り返り:結局どうだったか
実際に使い回せたもの
11個のコンポーネントのうち、実際に使い回せたのは:
ShipmentRow.tsx
– 表の1行部分DestinationSelect.tsx
– 出荷先選択プルダウンCompletedShipmentTable.tsx
– 出荷履歴表示(予定)
3個だけでした。
「ベタ書きでも良かった」説
正直に言うと、**「ベタ書きの方でも良かった」**と思います。
理由:
- 規模的にはそこまで複雑ではない
- 使い回しは結局あまりなかった
- 1ファイルで完結する方が楽だった
- 開発スピードはベタ書きの方が速かった
でも、コンポーネント化して得られたもの
一方で、以下のメリットもありました:
- 責務が明確になった
- 修正箇所が特定しやすい(OcrUpload だけいじれば OK)
- テストしやすい(各コンポーネント単体で)
- なんとなく「ちゃんとした」感
現実的な結論
「どちらでも良かった」が正解
完全に間違いでも、完全に正解でもない。
「まあ、どっちでも動くよね」
これが、実際の開発でよくある選択だと思います。
今後の方針
結局、**「もう作ったから、作り直さない」**です。
動いているものを作り直す意味はありません。
コンポーネント化したことで修正時には恩恵を受けられそうなので、とりあえずはこのまま継続します。
やってみてわかったこと
理論より実践。
教科書通りにやっても、実際の開発では思った通りにならないことが多いです。
でも、やってみてわかることも沢山あったので、それはそれで良い経験だったと思います。
学んだこと
1. コンポーネント化のタイミング
- 最初から完璧を目指さない
- 重複が発生してから検討する
- 「使い回し」より「責務分離」を重視する
2. 「教科書通り」が正解とは限らない
- 理論と実践にはギャップがある
- 規模や要件によって最適解は変わる
- 「どちらでも動く」なら、どちらでも OK
3. 開発は完璧である必要はない
- 動いているならそれで良い
- 後から改善すれば良い
- 完璧を目指して進まないより、動くものを作る方が大事
次回の開発では…
今度同じような機能を作る時は:
- 最初はベタ書きで作る
- 本当に使い回す場面が出てきたらコンポーネント化
- **「ファイルが長すぎて辛い」**と感じたら分割
このアプローチを試してみたいと思います。
まとめ
「React初心者がコンポーネント化してみた結果」:
- 理想:1つのコンポーネントで全部カバー
- 現実:11個のコンポーネントに分散
- 結論:「ベタ書きでも良かった」けど、「これはこれで OK」
完璧な設計なんて最初から分からないし、作りながら調整していくのが普通の開発プロセスだと思います。