0から作るときの開発工程ガイド:機能実装、整理、拡張に備える設計の進め方

目次
サイト制作を進める際、私はいつも「どのような手順でコードを書いていくべきか」で迷ってしまいます。
普段はデザインを完成させてからコーディングに入るのですが、どうしても意識がデザイン寄りになり、パーツごとのコンポーネント作成から手をつけてしまいがちです。
もちろん、UIを作っている段階では綺麗に分割できているのですが、機能を追加していくうちにコードがどんどん煩雑になっていきます。最終的には自分でも全体を把握しきれなくなり、AIにヘルプを求める……なんてことも珍しくありません。
そこで今回はこの負の連鎖を断ち切るために、サイトを制作する際のファーストステップを考えていこうと思います。
サイトの根幹は機能!まずは動かす!(プロトタイプ)
先ほども述べた通り、これまでの私はUIを先に作り、その後に機能を追加していくという流れで進めていました。
しかし、その方法だと「想定外の値のやり取り」や「考慮漏れのデザインパターン」が後から次々と発生してしまいます。ページが増え、機能が追加されるたびに、コードは理想的な保守性からどんどんかけ離れていきました。
そうした失敗を防ぐために色々調べて自分と相性が良かったのは、**「まずは1つのファイルに、機能やページに必要なコードをすべて書いてしまう」**という方法です。
具体的なすすめかた
Next.jsでの制作を例に挙げると、以下のようなルールで進めます。
- page.tsx に全部書いてOK
- 型定義も同じファイルでOK
- API呼び出しも同じファイルでOK
まずは「機能が正しく動くこと」を最優先に考えます。こうすることで、コンポーネントの細分化といった「細かい最適化」に思考を奪われず、ロジックだけに集中して効率的に進められるようになりました。
また、意外な収穫だったのが、自分自身が書いたコードへの理解度が深まったことです。一箇所にすべてがまとまっているため、データの流れが追いやすく、結果として修正にも強いコードの土台が出来上がります。
ルール:余計なことは考えない
コーディングが波に乗ってくると、つい「今のうちにコンポーネント化しておこうかな……」と先の工程を考えてしまいがちです。
しかし、ここで手を広げると本末転倒です。自分の中に、次のような「ルール」を言い聞かせています。
- 分割しない(まだ早いぞ!)
- 追加設計しない(まだどうなるか分からないぞ!)
- 動作確認に集中(余計なことは考えないぞ!)
このルールを自分に言い聞かせることで、迷うことなく「まずは動かす」という目的を完遂できるようになりました。
「まずは動かす!」のゴール
1つのファイルに色々書き込んでいると、「どこまで作り込めばいいのか」と迷う瞬間があります。そんな時は、以下の4点が確認できれば「このステップは完了!」と判断しています。
- 機能が意図通りに動く
- 必要なデータが正しく取得できている
- 画面に最低限の情報が表示されている
- 基本的な操作(クリックや入力など)ができる
機能ができたら、次は整理!(リファクタリング)
機能が動くページができたら、次はとうとう整理の段階に移ります。
私はこの工程がとても好きです。平日散らかした部屋を週末一気に片づけるような爽快感があります。……少し話がそれましたね。
ここでいう整理とは、「同じコードの繰り返しを減らす」ことです。そのために、まずはこの3つの項目を分離するかどうかを考えます。
- 型定義を分離するか?
- 関数を分離するか?
- コンポーネント(UI)を分離するか?
分離する条件
型・関数・コンポーネントの3つを確認していきますが、基本的にはどれも考え方は同じです。
判断の目安:
- 2箇所以上で使っている
- 一定行数以上書いている
- 別のページでも使いそう
私の場合は、型は20行・関数は30行・コンポーネントは100行くらいを目安にしています。逆に、そのページ専用に書かれている場合は、分離せずに残しておくことが多いです。
分離する手順
ステップ1:重複を探す コードを見返して、**「同じようなのをどこかで書いたな」**と思ったら分離します。もし2ページ目以降で、似たような処理が「まずは動かす」段階で出てきた場合も、すぐに分離に移ってOKです。
- パターン1:明らかに同じもの → すぐに既存のものを使う
- パターン2:似ているけど微妙に違う → 一旦コピペして動かしてから、すぐ分離
- パターン3:全く新しいロジック → まずは動かすことを優先

ステップ2:小さく分離する 一度に全部整理をするのではなく、1つずつ「分離 → テスト → コミット」を繰り返します。
- types/note.tsを作成
- Note型を移動
- import文を追加
- 動作確認
- コミット
この「小さく分離すること」には、次のようなメリットがあります。
- バグの原因がすぐ分かる
- 動作確認が簡単
- 作業範囲が狭くて短時間でできる
私は作業時間が細切れになることが多いので、短時間でできるこのスタイルが合っていてよかったです。
(余談ですが、こまめにプルリクエストを送れるので「仕事してる感」が出るのも密かなメリットです!)
分離の順番
分離の順番については、私の好みの話になりますが、簡単な順に進めていくのがおすすめです。
- 型定義の分離
- ユーティリティ関数の分離
- API呼び出しの分離
- カスタムフックの作成
- コンポーネント分割
毎回同じ技術要件で制作できるわけではないので、簡単なものから始めて徐々に慣れていく方が、制作のリズムがつかみやすいです。
「整理」のゴール
整理はやろうと思えばいくらでもできてしまいます。ですが、あくまでこのフェーズは「整理」ですので、次の項目を達成することをゴールにしています。
- 明らかな重複がない
- 1ファイル200行以内
- 「何がどこにあるか」が分かる
- 動作が変わっていない
整理が出来たら、拡張に備える(設計改善)
整理ができたら、次は拡張性を高めていく作業に入ります。 ただし、これまでの段階でもプログラムとしては十分な品質が保てています。そのため、プロジェクトの規模によってはこのフェーズを行わないという選択肢もあります。
この段階の目的は、あくまで「次の機能追加がしやすい」構成にすることです。主に行うのは、以下の3点です。
- ディレクトリ構造の確立
- index.ts(バレルファイル)の追加
- コンポーネントの粒度調整
ディレクトリ構造確立
ネットで検索すると色々な分け方が出てきますが、多くのプロジェクトが一定の決まった構造を採用しています。自分なりの「定番」を決めておくと、ファイルの保存場所に困ることがなくなるのでオススメです。

index.tsの追加
各ディレクトでindex.tsを作成することによって、インポートの手間が圧倒的に楽になります。テキストだけでは分かりづらいので、イメージコードで比較してみます。
index.ts がない場合
- 5つの型を使うのに5行書く必要がある
- どのファイルにあるか覚えておく必要がある
- ファイル名が変わったら全部修正
import { Recipe } from "@/types/recipe";
import { Material } from "@/types/material";
import { BuyList } from "@/types/buylist";
import { DateEntry } from "@/types/recipe";
import { Ingredient } from "@/types/material";
index.ts がある場合
- 1行で全部インポートできる
- ファイル構造を知らなくていい
- とにかく楽!
// types/recipe.ts
export interface Recipe {
id: string;
name: string;
ingredients: Ingredient[];
category: string[];
frequency: number; // 登録回数(提案頻度の管理用)
status: boolean; // 有効/無効フラグ
}
// types/index.ts
export type { Recipe} from "./recipe"
// どこかのコンポーネント
import { Recipe, Material, BuyList, DateEntry, Ingredient } from "@/types";
index.tsを作成する恩恵は、初回は感じにくいかもしれませんが、機能追加や運用のフェーズに入るとそのありがたみを実感します。
公開APIを管理できる
開発方法を模索しているときはなかなか利用イメージが湧かなかったのですが、実際に試してみるとメリットがよく分かりました。 呼び出す必要のあるAPIだけを index.tsにまとめておけば、ページの追加や似た機能の実装時に、index.tsを見るだけで済むのが助かります。
具体的には、次のようなメリットがあります。
- 「使っていいもの」が明確(実装に直接関係ないものが視界に入らない)
- 内部実装の変更が外部に影響しない(コンポーネント側の修正がいらない)
- 中身を知らなくても使える(APIの境界線が明確になる)
要するに、**リファクタリングが超楽になる!**ということです!
コンポーネントの粒度調整
コンポーネントディレクトリの構造についてです。 以前はアトミックデザイン(Atomic Design)を参考に、「atoms」から「pages」までの5層で分けていました。しかし、私の担当する規模の制作では、逆に煩雑になることが多かったです。
現在は、Next.jsの環境に合わせて以下のような形に落ち着きました。
- UIディレクトリ:パーツ単体や組み合わせなどの汎用パーツ(atoms, moleculesに相当)をまとめます。
- 各ページのディレクトリ:特定のページで使う大きな塊(organismsに相当)を切り分けます。
- layout.tsx / page.tsx:templatesとpagesの役割はこれらで代用できるため、わざわざディレクトリは作成していません。

「拡張」のゴール
この段階の作業は、効果を実感するのが開発の後半以降になります。ですが、ここまで対応することができれば、自信を持って運用できるコードになっているはずです。
- 新機能を追加するときに「どこに書けばいいか」迷わない
- ディレクトリ構造が一貫している
- importパスがシンプルに保たれている
参考文献
自分の制作プロセスを固めるにあたり、下記の記事には大変お世話になりました。
私はこれまで独学やOJTを中心に進んできたこともあり、改めて基礎となる考え方を学んだり、逆に「自分の手法はこれで良かったんだ」と自信を持てたりと、非常に充実したインプットの時間になりました。
TypeScriptで学ぶ!SOLID原則
https://zenn.dev/milab/articles/05d800b173bbad
フロントエンド開発でのコード分割とアーキテクチャ設計
https://zenn.dev/mojakun/articles/ac6636e11e9686
Reactのコードデザインパターンとか設計原則とか
https://zenn.dev/fullyou/scraps/326aa1ec802073
そして、お恥ずかしながら私は、学習の過程で出会ったこの言葉を今まで知りませんでした。
Make It Work, Make It Right, Make It Fast
(まずは動かせ、正しく直せ、それから速くせよ)
まさに今回私が辿り着いた「まずは1ファイルで動かし、その後に整理・拡張する」という手順そのものであり、指針となる大切な言葉になりました。
おわりに
これまで「見た目」から入って迷走していた私ですが、この3つのステップを意識するようになってから、開発のストレスが劇的に減りました。
- まずは動かす!(page.tsxに全部書く)
- 次に整理する!(重複を削って小さくコミット)
- 最後に拡張に備える!(ディレクトリとインポートを整える)
もちろん、プロジェクトの規模や状況によって最適な正解は変わると思います。ですが、もし私と同じように「機能が増えるたびにコードが把握できなくなる……」と悩んでいる方がいたら、ぜひ一度この「まずは動かす」順序を試してみてください。
結局のところ、「急がば回れ」が一番の近道だったりします。
