7日目のゴールと今日のテーマ
7日目は「この ToDo アプリを、自分の言葉で“設計として説明できるようになる日」です。
ここまでであなたは、
- 状態管理(state)でアプリの“今”を表現し
- 配列+オブジェクトでタスクをモデル化し
- 再描画ロジック(render)で「state → 画面」の一方向を作り
- 追加・完了・削除・フィルタ・編集まで設計してきました。
今日はそれらをまとめて、
- 設計を“言語化”する
- 「もし機能を足すなら?」を設計目線で考える
- 自分が身につけたパターンを整理する
ところまで行きます。
コードを書くというより、「設計を説明できる自分」になる日です。
この ToDo アプリの「設計」を言葉で説明してみる
状態管理 state の設計
まず、アプリの中心にあるのが state です。
const state = {
// ビジネスデータ:アプリが扱う全タスク
tasks: [
// { id: number, title: string, done: boolean }
],
// UI 状態:どのフィルタが選ばれているか
// "all" | "active" | "active" | "completed"
filter: "all",
// UI 状態:どのタスクが編集中か(なければ null)
editingTaskId: null,
};
JavaScriptここで大事なのは、
- 「アプリが本当に扱いたいデータ」は tasks
- 「画面の見せ方に関する状態」は filter と editingTaskId
という分離です。
この分離ができていると、
- データの変更(タスク追加・完了・削除)
- 表示の変更(フィルタ切り替え・編集モード)
を頭の中で整理して考えられます。
タスクのデータ構造
タスクはオブジェクトで表現しています。
{
id: 1,
title: "牛乳を買う",
done: false,
}
JavaScriptここに「期限」「優先度」「メモ」などを足しても、
設計として破綻しません。
- id:一意な識別子(完了・削除・編集のターゲット)
- title:ユーザーが見る名前
- done:完了状態(フィルタの条件にも使う)
この「意味のあるプロパティ名を持つオブジェクトの配列」という形は、
ToDo に限らず、ほぼすべての CRUD アプリの基本パターンです。
再描画ロジックの設計:「state → 画面」の一方向
render の役割
render はアプリの「画面更新の司令塔」です。
function render() {
renderTaskList();
updateFilterButtons();
updateTaskCount();
}
JavaScriptここでのルールはシンプルです。
- render は state を読んで画面を作り直すだけ
- state を書き換えるのは、addTask / toggleTaskDone などの“状態変更関数”だけ
このルールを守ることで、
- 「画面が変になるときは、state が変なはず」
- 「state が正しければ、render は正しい画面を作るはず」
という前提が成り立ちます。
デバッグするときの“心の支え”になります。
タスク一覧の描画
function renderTaskList() {
tasksContainerEl.innerHTML = "";
const visibleTasks = getVisibleTasks();
if (visibleTasks.length === 0) {
const emptyEl = document.createElement("div");
emptyEl.textContent = "タスクがありません。新しいタスクを追加してみましょう。";
emptyEl.style.color = "#777";
emptyEl.style.fontSize = "12px";
tasksContainerEl.appendChild(emptyEl);
return;
}
visibleTasks.forEach((task) => {
const rowEl = renderTaskRow(task);
tasksContainerEl.appendChild(rowEl);
});
}
JavaScriptここでのポイントは、
- 「何を表示するか」は getVisibleTasks が決める
- 「どう表示するか」は renderTaskRow が決める
という役割分担です。
フィルタと配列操作の設計
フィルタ条件をオブジェクトで持つ
const filters = {
all: (task) => true,
active: (task) => !task.done,
completed: (task) => task.done,
};
function getVisibleTasks() {
const predicate = filters[state.filter] || filters.all;
return state.tasks.filter(predicate);
}
JavaScriptここでの設計のキモは、
- フィルタ条件を if 文でベタ書きしない
- 「名前付きの条件」として filters に集約する
というところです。
新しいフィルタ(例:高優先度だけ)を追加したくなったら、
filters.highPriority = (task) => task.priority === "high";
と書いて、ボタンを 1 つ足せば済みます。
既存のロジックを壊さずに拡張できる——これが「設計が強い」ということです。
追加・更新・削除の配列パターン
タスク追加:
function addTask(title) {
const trimmed = title.trim();
if (!trimmed) return;
const newTask = {
id: nextId++,
title: trimmed,
done: false,
};
state.tasks.push(newTask);
render();
}
JavaScript完了切り替え(イミュータブル寄り):
function toggleTaskDone(id) {
state.tasks = state.tasks.map((task) => {
if (task.id !== id) return task;
return { ...task, done: !task.done };
});
render();
}
JavaScript削除:
function deleteTask(id) {
state.tasks = state.tasks.filter((task) => task.id !== id);
render();
}
JavaScriptここであなたがもう持っている感覚は、
- 追加=配列に 1 件足す
- 更新=条件に一致する要素だけ中身を変えた新しい配列を作る
- 削除=条件に一致しない要素だけ残した新しい配列を作る
という「配列操作の 3 パターン」です。
これは今後、どんなアプリを作るときにも使い回せる“武器”になります。
編集機能と「モード管理」の設計
編集モードを state で持つ
state.editingTaskId = null;
JavaScript編集開始:
function startEditTask(id) {
state.editingTaskId = id;
render();
}
JavaScript編集終了:
function finishEditTask() {
state.editingTaskId = null;
render();
}
JavaScriptここでの本質は、
- 「今どのタスクが編集モードか」も state の一部
- 行側は「自分の id と editingTaskId が一致しているか」で表示を切り替える
という構造です。
行の表示モードと編集モード
function renderTaskRow(task) {
const rowEl = document.createElement("div");
rowEl.className = "task-item";
const isEditing = state.editingTaskId === task.id;
if (isEditing) {
renderTaskRowEditing(rowEl, task);
} else {
renderTaskRowDisplay(rowEl, task);
}
return rowEl;
}
JavaScriptこの「モードを state で管理し、描画側はそれに従うだけ」というパターンは、
フォームバリデーション編でも出てきた、かなり重要な設計パターンです。
「もし機能を足すなら?」を設計目線で考える
例1:優先度を追加するなら
やりたいこと:
- タスクに priority(”high” | “medium” | “low”)を持たせる
- 「高優先度だけ表示」フィルタを追加する
設計として必要な変更は、
- タスクオブジェクトに
priorityを追加 - 追加時の newTask に
priority: "medium"などを入れる - filters に
highPriority条件を追加 - フィルタボタンを 1 つ追加(data-filter=”highPriority”)
これだけで済みます。
state の構造も、render の構造も壊れません。
例2:期限切れタスクを赤く表示するなら
やりたいこと:
- タスクに dueDate を持たせる
- 今日より前のタスクは赤字で表示する
設計としては、
- タスクオブジェクトに
dueDateを追加 renderTaskRowDisplayの中で「期限切れかどうか」を判定してクラスを付ける
だけで済みます。
state の構造はそのまま、
「見せ方」だけを変えればいい設計になっています。
こうやって「機能追加を頭の中でシミュレーションしてみて、
既存の設計がどれだけ耐えられそうか」を考えるのが、
設計力を育てる一番のトレーニングです。
7日目のまとめ:あなたがこの 7 日間で手に入れたもの
ToDo アプリ【設計力強化編】で、あなたが身につけたのは単なる「ToDo の作り方」ではありません。
- アプリの“今”を表現する state の設計
- 配列+オブジェクトでデータをモデル化する感覚
- 「state → 画面」の一方向データフロー
- 追加・更新・削除の配列操作パターン
- フィルタを条件オブジェクトとして持つ設計
- モード(編集中など)を state で管理する考え方
- render を「何度呼んでも安全な読み取り専用の関数」として扱う姿勢
これらは全部、
フォームバリデーションアプリともつながっているし、
今後作るどんなアプリにもそのまま持ち込める“設計の型”です。
ここから先は、
- この ToDo を自分なりに改造してみる
- 別の題材(メモ帳、買い物リスト、習慣トラッカー)で同じ設計を試す
- React / Vue などのフレームワークで「同じことをコンポーネントでやる」
みたいな方向に進めます。
最後に一つだけ聞きたいのは、
「この ToDo アプリ、どこが一番“自分の好きな設計”だと感じた?」
そこに、あなたのセンスが一番強く出ています。
そこを意識して伸ばしていくと、設計はどんどん自分のものになっていきます。

