7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

第1話 AIでReactアプリを一気に作った。でも、設計不在で機能を追加していく未来にゾッとした

Last updated at Posted at 2025-05-06

師匠:「動くコードは誰でも作れるが、“役割の形”がどこにもないからだよ」

前任不在、急な無茶ぶり。AIで爆速開発したけれど──

そのプロジェクトは、すでに継続が危ぶまれる状態だった。

要件は曖昧、スケジュールは逼迫。
仕様が決まらないまま、実装だけが進められる。

上司も余裕がなく、会話はいつも指示だけ。
そして追い詰められたように、前任のフロントエンド担当が、ある日突然いなくなった。

それでもプロジェクトは止まらない。

「君、React触れるよね?」

上司にそう言われて、若手の自分にすべてが降ってきた。

設計も方針も分からない。
ただ“早く作れ”という空気だけが漂っていた。

若手(心の声):「……無理だろ、これ……」

唯一の救いは、「AI使っていい」という社内ルールだった。
自分に残された時間も、気力も、決して多くはなかった。

試しにChatGPTに打ち込んだ。

「ReactでTodoアプリ作って」

ほんの数秒でコードが返ってきた。
コピペして実行すると、ちゃんと動く。
フォームもボタンも、リストも整っている。

若手:「……これ、本当に使えるんじゃないか……?」

興奮気味に追加機能も投げ込んだ。
完了チェック、削除、残数カウント……
ChatGPTは言えば言うだけ応えてくれる。

誰も教えてくれない現場で、唯一“助けてくれる存在”のように思えた。

若手:「……もう、開発ってこういう時代なんじゃないか?」

けれど、ふとした瞬間に違和感が刺す。

似たような処理があちこちに散らばっていく。
コードを読むたび、「これ、どこで何してるんだっけ?」と手が止まる。

若手:「このまま機能や処理を積み重ねたら……」
「いつか“触るのが怖いコード”になってしまう……」

目の前にあるのは、“今は動くアプリ”。
でもその裏側に広がるコードは、
かつて自分がプロジェクトで経験した“破綻の兆し”と、どこか似ていた。

作成した画面

Todoアプリ.png

作成したコード

import { useState } from 'react';

function App() {
  const [text, setText] = useState('');
  const [todos, setTodos] = useState<string[]>([]);

  const handleAdd = () => {
    if (text.trim() === '') return;
    setTodos([...todos, text]);
    setText('');
  };

  return (
    <div style={{ padding: '2rem' }}>
      <h1>Todoアプリ</h1>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
        placeholder="やることを入力"
      />
      <button onClick={handleAdd}>追加</button>
      <ul>
        {todos.map((todo, idx) => (
          <li key={idx}>{todo}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

機能が増えると、コードが長く複雑化して不安が募る

締切・優先度・並び替えなど、よくある仕様を追加し始めると、
useState や useEffect が画面中にどんどん増えていった。

最初はコピペで済んでいた処理も、だんだん違いが出てきて、
似たようなロジックがあちこちに散らばるようになった。

変更するたびに、「あれ、ここも直すんだっけ?」と不安になる。
気づけば、「どこで何をしてるのか」が自分でも把握しきれなくなっていた。

「今は動いてる。でも……もう全体が読めない」
「手を入れるたびに、自分の書いたコードが怖くなる」

機能追加した画面

Todoアプリ機能追加.png

作成したコード

import React, { useState, useEffect } from 'react';

type Todo = {
  text: string;
  done: boolean;
};

const TodoApp: React.FC = () => {
  const [todos, setTodos] = useState<Todo[]>([]);
  const [newTodo, setNewTodo] = useState('');
  const [filter, setFilter] = useState<'all' | 'active' | 'completed'>('all');
  const [sorted, setSorted] = useState(false);
  const [filteredTodos, setFilteredTodos] = useState<Todo[]>([]);

  useEffect(() => {
    let result = [...todos];

    if (filter === 'active') {
      result = result.filter(todo => !todo.done);
    } else if (filter === 'completed') {
      result = result.filter(todo => todo.done);
    }

    if (sorted) {
      result.sort((a, b) => a.text.localeCompare(b.text));
    }

    setFilteredTodos(result);
  }, [todos, filter, sorted]);

  const addTodo = () => {
    if (newTodo.trim() === '') return;
    setTodos([...todos, { text: newTodo, done: false }]);
    setNewTodo('');
  };

  const toggleTodo = (index: number) => {
    const updated = [...todos];
    updated[index].done = !updated[index].done;
    setTodos(updated);
  };

  const deleteTodo = (index: number) => {
    const updated = [...todos];
    updated.splice(index, 1);
    setTodos(updated);
  };

  return (
    <div>
      <h1>Todo List</h1>
      <input
        value={newTodo}
        onChange={e => setNewTodo(e.target.value)}
        placeholder="Add new todo"
      />
      <button onClick={addTodo}>Add</button>
      <div>
        <button onClick={() => setFilter('all')}>All</button>
        <button onClick={() => setFilter('active')}>Active</button>
        <button onClick={() => setFilter('completed')}>Completed</button>
        <button onClick={() => setSorted(!sorted)}>
          {sorted ? 'Unsort' : 'Sort'}
        </button>
      </div>
      <ul>
        {filteredTodos.map((todo, index) => (
          <li key={index}>
            <input
              type="checkbox"
              checked={todo.done}
              onChange={() => toggleTodo(index)}
            />
            {todo.text}
            <button onClick={() => deleteTodo(index)}>Delete</button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default TodoApp;

“どこから手をつけていいか分からないコード”にぶつかったとき、頼る人は一人だった

過去、別のプロジェクトで、
不具合だらけのコードに誰もが匙を投げかけていたとき――

一人の技術者が、黙々とコードを読み解き、整理し、
機能を壊さずにリファクタリングを進めていった。

60代、酒好きでちょっと豪快。
でも書くコードは静かで、整っていて、まるで無駄がなかった。

その姿に、技術だけじゃない「人としての芯」を感じた。
そして何より、崩れていたコードが美しく整っていくあの体験が忘れられなかった。

若手:「この人に、もっと近づきたい」

そう思って、弟子入りを願い出たのが、あのときだった。

再び師匠から教わる。キーワードは“WHATで説明しろ”

若手は迷いながらも、師匠に連絡を入れた。
すぐに「近くにいる」と返事があり、その日のうちに会うことになった。

カウンターの奥、酒を片手に師匠は待っていた。
ノートPCを開いて座ると、師匠が静かに言った。

師匠:「……そのコード、見せてごらん」

機能を追加したコードではなく、シンプルな機能に戻したコードを師匠に見せた。

画面を見つめながら、師匠はスクロールを止めずに言う。

「ひどいコードだなぁ。こりゃ」
「一見動いてるけど、誰も中身が追えなくなるやつだよ、これ」
「これじゃ、どこを直しても他に影響出そうで怖いだろ?」

若手は焦りながら、コードの内容を説明しようとするが──

師匠:「ソースコードで説明するな。“WHATで説明しろ”って言っただろう?」

一瞬、言葉に詰まった。

若手:「……WHATって、なんでしたっけ……?」

師匠:「“何をしたいのか”だよ。それが設計の出発点なんだよ。コードはその手段にすぎない」

言われてみれば、自分は機能の処理やUIの操作の話ばかりしていた。

画面に書いたコードが、何のためにあるのか。
どこで意味を持ち、どう伝わるべきか。
それを考えていなかった。

若手はコードを見つめながら、ぽつりとつぶやく。

若手:「……全部“処理の話”ばっかりしてた気がする……」

師匠はグラスを置き、ふと笑ってこう言った。

師匠:「ちなみに俺、Reactのことは全く知らないんだけど」
若手:「……えっ!?」

いや、使う言語知らなくて、設計ってできるの?

次回へ続く


次回の記事予告

ここまでお読みいただき、ありがとうございました。
本記事では、AIを使って開発を進める中で直面した「設計不在」の怖さと、それを乗り越えるために必要な“伝わる設計”の視点について紹介しました。

次回は、師匠から教わった設計の基本――「STS設計(入力・変換・出力)」というシンプルで強力な考え方を軸に、実際にReactアプリの構造を改善していくプロセスを紹介します。

もし、AIの出力をそのまま使ってコードが混乱してきた方、自分の設計に不安を感じている方には、きっと役立つ内容になるはずです。ぜひご期待ください!


また、今回紹介した内容をより実践的に学びたい方には、以下のUdemy講座もおすすめです。

Udemyコース(8,800円 → クーポンで割引中)

▶️ AIとC#で極める!クリーンコードの技法(限定クーポン付き)

  • C#でクリーンコードと設計力を身につける実践講座
  • ChatGPTの活用方法や、伝わるコードの考え方を解説

出版書籍『あきらめない者たち』

▶️ Amazonで見る

  • 技術の基礎からやり直すために、なぜ一歩勇気を振り絞れたのかのノンフィクション作品です。
7
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
10

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?