6日目のゴールと今日のテーマ
6日目は「設計を“他人が読んでもわかるレベル”まで磨き込む日」です。
ここまでで ToDo アプリは十分動いていますが、今日は
- 関数の分割と命名を見直して、読みやすさを上げる
- 状態管理(state)の扱い方を、より一貫した形に整える
- データ構造(配列+オブジェクト)の操作をパターンとして整理する
- 「バグりにくい書き方」を意識してコードを微調整する
という、「リファクタリング寄りの 1 日」にします。
新機能は最小限にして、その代わり“設計の精度”を上げていきます。
状態管理を「読みやすい形」に整える
state を“1カ所で定義しきる”という意識
今の state はだいたいこうなっています。
const state = {
tasks: [],
filter: "all",
editingTaskId: null,
};
JavaScriptここで大事なのは、「state に何があるか」が一目でわかることです。
6日目では、ここにコメントを足して“設計書”としての役割も持たせます。
const state = {
// アプリが扱う全タスク(ビジネスデータ)
tasks: [
// { id: number, title: string, done: boolean }
],
// 現在の表示フィルタ(UI 状態)
// "all" | "active" | "completed"
filter: "all",
// 現在編集中のタスク id(なければ null)
// 編集モードの管理用(UI 状態)
editingTaskId: null,
};
JavaScriptここでのポイントは、
「これはビジネスデータ」「これは UI 状態」という区別を
コメントで明示しておくことです。
自分の未来の自分にも、他人にも優しい設計になります。
関数の役割を“名前だけで伝わるように”する
「何をするか」が一瞬でわかる名前にする
今ある関数をざっと並べてみます。
addTask
toggleTaskDone
deleteTask
startEditTask
finishEditTask
updateTaskTitle
getVisibleTasks
render
renderTaskList
renderTaskRow
renderTaskRowDisplay
renderTaskRowEditing
updateFilterButtons
updateTaskCount
JavaScript6日目で意識したいのは、
- 動詞+目的語で「何をするか」がわかるか
- 「状態を変える関数」と「描画する関数」が名前から区別できるか
という点です。
例えば、getVisibleTasks は「見えるタスクを取得する」とわかるので良い名前です。renderTaskRow は「1 行分の DOM を作る」とわかるので、これも良いです。
逆に、もし doEdit や handleClick のような
「中身を見ないとわからない名前」があれば、startEditTask や onFilterButtonClick のように
“意図が伝わる名前”に変えていきます。
イベントハンドラを“入口”として整理する
イベントハンドラとロジックを分ける
今のコードでは、イベントリスナーの中に
ロジックが直接書かれている部分があるかもしれません。
例えば:
addButtonEl.addEventListener("click", () => {
addTask(taskInputEl.value);
taskInputEl.value = "";
});
JavaScriptこれは悪くないですが、6日目では
「イベントハンドラも関数として名前を付ける」ことをやってみます。
addButtonEl.addEventListener("click", onAddButtonClick);
taskInputEl.addEventListener("keydown", onTaskInputKeyDown);
function onAddButtonClick() {
addTask(taskInputEl.value);
taskInputEl.value = "";
}
function onTaskInputKeyDown(event) {
if (event.key === "Enter") {
addTask(taskInputEl.value);
taskInputEl.value = "";
}
}
JavaScriptここでの重要ポイントは、
- イベントハンドラは「UI の入口」
- ビジネスロジック(addTask など)は「状態を変える役」
と役割を分けていることです。
これにより、「どこから state が変わるのか」が追いやすくなります。
配列操作を“パターン化して意識する”
追加・更新・削除をそれぞれパターンとして見る
タスク追加:
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 パターン”として頭に入れておくことです。
この 3 つのパターンを意識しておくと、
別のアプリ(メモ帳、ユーザー一覧、商品リストなど)でも
まったく同じ考え方で設計できます。
再描画ロジックを“安心して呼べるもの”にする
render は「副作用のない読み取り専用」に近づける
render の中身はこうでした。
function render() {
renderTaskList();
updateFilterButtons();
updateTaskCount();
}
JavaScriptここで大事なのは、
- render の中で state を書き換えない
- render の中で「新しいイベントリスナーを無限に追加しない」
という 2 点です。
タスク行の描画でイベントリスナーを付けていますが、
毎回 innerHTML = "" で中身を消してから作り直しているので、
古い DOM とリスナーは破棄されます。
この構造なら、render を何度呼んでも「増殖」はしません。
6日目では、「render は何度呼んでも安全」という前提を
自分の中でしっかり意識しておきましょう。
これが崩れると、一気にバグりやすくなります。
小さなリファクタリングで“読みやすさ”を上げる
例:タスク行の描画を少しだけ整理する
今の renderTaskRowDisplay は、
タイトル・完了ボタン・編集ボタン・削除ボタンを
一気に組み立てています。
ここを、さらに小さく分けることもできます。
function renderTaskRowDisplay(rowEl, task) {
const titleEl = createTaskTitleElement(task);
const actionsEl = createTaskActionsElement(task);
rowEl.appendChild(titleEl);
rowEl.appendChild(actionsEl);
}
function createTaskTitleElement(task) {
const titleEl = document.createElement("div");
titleEl.className = "task-title";
if (task.done) {
titleEl.classList.add("done");
}
titleEl.textContent = task.title;
return titleEl;
}
function createTaskActionsElement(task) {
const actionsEl = document.createElement("div");
actionsEl.className = "task-actions";
const toggleButton = document.createElement("button");
toggleButton.textContent = task.done ? "未完了に戻す" : "完了";
toggleButton.addEventListener("click", () => {
toggleTaskDone(task.id);
});
const editButton = document.createElement("button");
editButton.textContent = "編集";
editButton.addEventListener("click", () => {
startEditTask(task.id);
});
const deleteButton = document.createElement("button");
deleteButton.textContent = "削除";
deleteButton.addEventListener("click", () => {
deleteTask(task.id);
});
actionsEl.appendChild(toggleButton);
actionsEl.appendChild(editButton);
actionsEl.appendChild(deleteButton);
return actionsEl;
}
JavaScriptここでのポイントは、
- 「1 関数 1 役割」に近づける
- 関数名だけで「何を作っているか」がわかる
という読みやすさです。
もちろん、やりすぎると関数が増えすぎて逆に読みにくくなるので、
「自分が読みやすいバランス」を探すのも大事な経験です。
6日目のまとめと、明日へのつなぎ
6日目は、機能追加よりも「設計の精度を上げる」ことに集中しました。
あなたが今日やったのは、
state を“設計書”としてコメント付きで整理すること。
関数名と役割を見直して、「名前だけで意図が伝わる」形に近づけること。
イベントハンドラとビジネスロジックを分けて、入口をはっきりさせること。
配列操作(追加・更新・削除)を 3 パターンとして意識し直すこと。
render を「何度呼んでも安全な読み取り専用の関数」として扱うこと。
これは全部、「中級から上級に上がるための筋トレ」です。
明日(7日目)はいよいよ総仕上げとして、
この ToDo アプリを「自分の言葉で説明できる」ように整理する。
もし機能を 1 つ足すなら、どこをどう変えるかを設計してみる。
“設計力強化編”として、学んだパターンを振り返る。
という 1 日にしていきます。
今日は、コードを眺めながら
「この設計、けっこういいじゃん」と思えるところと、
「ここはまだモヤっとするな」というところを
自分なりに見つけてみてください。
その感覚が、次の一段上のあなたを連れてきます。

