11日目のゴールとテーマ
11日目のテーマは「コードを“人が読める文章”にする」です。
ここまでで、あなたはもう「動くアプリ」を作れるようになっています。
今日からは一歩進んで、
コードをファイルごとに分ける感覚
コメントで“意図”を残す書き方
「未来の自分(と他人)」が読みやすい形に整える視点
を身につけていきます。
正直、「動くかどうか」だけなら今のままでも十分です。
でも、アプリを育てていくなら、「読みやすさ」「直しやすさ」が圧倒的に大事になってきます。
今日はその入口に、しっかり足を踏み入れます。
いまの main.js、ちょっと重くなってきていないか?
「1ファイルに全部」は最初は楽、あとでしんどい
タスクアプリの main.js を想像してみてください。
タスクの配列
render 関数
カウント更新
localStorage 保存・読み込み
イベント登録
フィルタ処理
一括削除
バグ取り用の console.log(もしかしたら残っている)
全部が1ファイルに詰まっている状態だと、
最初は「どこに何があるか覚えている」ので問題ありません。
でも、数日後に見返したとき、こう感じませんか?
「どこから読めばいいか分からない」
「イベントどこだっけ?」「保存どこだっけ?」とスクロールしまくる
これは、「情報が整理されていない」サインです。
今日はここを、少しずつ片付けていきます。
ファイルを分ける、という発想
「役割ごとに部屋を分ける」イメージ
コードを整理するときの基本は、「役割ごとに分ける」です。
家でいうと、
寝る部屋
ご飯を食べる部屋
仕事をする部屋
を分けるイメージです。
JavaScript でも同じで、
アプリの“状態”や“ロジック”を書く場所
画面を描く処理を書く場所
イベント(ユーザー操作)を書く場所
を、少しずつ分けていくと、頭の中がかなりスッキリします。
今日は、シンプルに「ファイルを2つに分ける」ところから始めます。
まずはファイルを2つに分けてみる
main.js と ui.js に分割する例
今、main.js に全部書いているとします。
これを、次のように分けてみます。
main.js
アプリの状態(tasks など)
ロジック(addTask, toggleTaskDone, deleteTask など)
保存・読み込み(saveTasks, loadTasks)
ui.js
画面描画(renderTasks, updateTaskCount)
イベント登録(クリックイベントなど)
まず、ui.js という新しいファイルを作ります。index.html の <script> を、次のように変えます。
<script src="main.js"></script>
<script src="ui.js"></script>
HTMLここで大事なのは、「読み込む順番」です。
main.js が先、ui.js が後です。
なぜかというと、ui.js の中から main.js の関数(addTask など)を呼びたいからです。
先に main.js を読み込んでおかないと、「そんな関数知らないよ」と言われてしまいます。
main.js に「アプリの心臓」を集める
状態とロジックをここに置く
main.js には、次のようなものを残します。
tasks 配列
currentFilter などの状態
addTask, toggleTaskDone, deleteTask, clearDoneTasks などのロジック
saveTasks, loadTasks などの保存系
filter や count などの“純粋な処理”
例えば、こんなイメージです。
let tasks = [];
let currentFilter = "all";
function addTask(title) {
if (title === "") {
alert("タスクを入力してください。");
return;
}
let task = {
title: title,
done: false
};
tasks.push(task);
updateViewAndSave();
}
function toggleTaskDone(index) {
if (index < 0 || index >= tasks.length) {
return;
}
tasks[index].done = !tasks[index].done;
updateViewAndSave();
}
function deleteTask(index) {
if (index < 0 || index >= tasks.length) {
return;
}
tasks.splice(index, 1);
updateViewAndSave();
}
function clearDoneTasks() {
let newTasks = [];
for (let i = 0; i < tasks.length; i = i + 1) {
if (!tasks[i].done) {
newTasks.push(tasks[i]);
}
}
tasks = newTasks;
updateViewAndSave();
}
function saveTasks() {
let json = JSON.stringify(tasks);
localStorage.setItem("tasks-data", json);
}
function loadTasks() {
let json = localStorage.getItem("tasks-data");
if (json === null) {
tasks = [];
return;
}
tasks = JSON.parse(json);
}
JavaScriptここで一つ気づいたかもしれません。updateViewAndSave() の中身は、画面のこともやっていますよね。
これは ui.js 側に置きたい処理です。
なので、updateViewAndSave の定義は ui.js に移し、
main.js からは「呼ぶだけ」にします。
ui.js に「画面まわり」を集める
DOM を触るのはここだけにする
ui.js には、次のようなものを置きます。
HTML 要素をつかむ処理(getElementById)
renderTasks(画面描画)
updateTaskCount(件数表示)
updateViewAndSave(render+カウント+保存)
イベント登録(ボタンのクリックなど)
例えば、こういう形です。
let taskInputElement = document.getElementById("task-input");
let addTaskButtonElement = document.getElementById("add-task-button");
let taskListAreaElement = document.getElementById("task-list-area");
let taskCountAreaElement = document.getElementById("task-count-area");
let showAllButtonElement = document.getElementById("show-all-button");
let showUndoneButtonElement = document.getElementById("show-undone-button");
let clearDoneButtonElement = document.getElementById("clear-done-button");
function updateViewAndSave() {
renderTasks();
updateTaskCount();
saveTasks();
}
function renderTasks() {
let items = buildTargetItems(tasks, currentFilter);
let html = buildTasksHtml(items);
taskListAreaElement.innerHTML = html;
}
function updateTaskCount() {
let total = tasks.length;
let undoneCount = 0;
for (let i = 0; i < tasks.length; i = i + 1) {
if (!tasks[i].done) {
undoneCount = undoneCount + 1;
}
}
let doneCount = total - undoneCount;
let text = "合計: " + total + "件 / 未完了: " + undoneCount + "件 / 完了: " + doneCount + "件";
taskCountAreaElement.textContent = text;
}
JavaScriptここで、「buildTargetItems」「buildTasksHtml」はどこに置くか問題が出てきます。
これは、「画面に何を表示するか」を決める処理なので、ui.js に置いてもいいし、
「配列を加工する純粋な処理」として main.js に置いてもいいです。
どちらが正解、というより、「自分がしっくりくる分け方」を試してみるのが大事です。
今日は、「DOM を触るのは ui.js だけ」という方針を意識してみてください。
コメントは「何をしているか」ではなく「なぜそうしているか」を書く
コードをそのまま説明するコメントは、ほとんど意味がない
コメントの話もしておきましょう。
初心者がやりがちなのは、こういうコメントです。
// タスクを追加する関数
function addTask(title) {
// タイトルが空かどうかをチェックする
if (title === "") {
// アラートを表示する
alert("タスクを入力してください。");
return;
}
// タスクオブジェクトを作成する
let task = {
title: title,
done: false
};
// tasks 配列に追加する
tasks.push(task);
// 画面を更新して保存する
updateViewAndSave();
}
JavaScript一見、親切そうに見えますが、
正直、ほとんどが「コードをそのまま日本語にしただけ」です。
コードを読めば分かることを、わざわざコメントに書いても、あまり価値はありません。
本当に価値があるコメントは、「なぜそうしているか」を説明してくれるコメントです。
「なぜ?」を説明するコメントの例
未来の自分が「そういうことか」と納得できるように
例えば、localStorage の保存処理に、こんなコメントを付けるのはアリです。
function saveTasks() {
// localStorage は文字列しか保存できないので、
// tasks 配列を JSON 文字列に変換してから保存する。
let json = JSON.stringify(tasks);
localStorage.setItem("tasks-data", json);
}
JavaScriptここでは、「JSON.stringify を使う理由」を説明しています。
コードだけ見ても「文字列にしてるんだな」は分かりますが、
「なぜ文字列にする必要があるのか」は、コメントがあると一瞬で理解できます。
もう一つ例を出します。
完了タスク一括削除のところ。
function clearDoneTasks() {
// 配列を直接削除していくとインデックスがずれてバグりやすいので、
// 未完了のタスクだけを集めた新しい配列を作ってから置き換える。
let newTasks = [];
for (let i = 0; i < tasks.length; i = i + 1) {
if (!tasks[i].done) {
newTasks.push(tasks[i]);
}
}
tasks = newTasks;
updateViewAndSave();
}
JavaScriptここでは、「なぜ新しい配列を作っているのか」を説明しています。
この“理由”は、コードだけだと読み取りにくいので、コメントの価値が高いです。
「ここはバグりやすい」と思うところにコメントを置く
未来の自分へのメモ書きとして使う
コメントは、「未来の自分へのメモ」として使うのが一番いいです。
例えば、「currentFilter を変えたら必ず renderTasks を呼ぶ必要がある」とします。
それを忘れると、表示モードが変わらないバグが出ます。
そういうところには、こう書いておくといいです。
showUndoneButtonElement.addEventListener("click", function () {
// フィルタを変えたら、必ず renderTasks を呼んで画面を更新する。
currentFilter = "undone";
renderTasks();
});
JavaScriptこのコメントは、「ここをいじるときは気をつけろよ」というサインになります。
他の人が読んだときも、「あ、この順番には意味があるんだな」と気づけます。
コードの“並び順”も読みやすさに効いてくる
「上から読んでいくと、自然に理解できる」並びにする
同じ内容でも、「どの順番で書くか」で読みやすさが変わります。
例えば、ui.js の中身をこういう順番にしてみます。
一番上に、DOM 要素の取得(getElementById)
次に、render や updateViewAndSave などの“表示系関数”
その下に、イベント登録
こうしておくと、ファイルを上から読んでいったときに、
「どの要素を触るのか」
「どう表示するのか」
「どんな操作があるのか」
という順番で自然に理解できます。
逆に、イベントがファイルのあちこちに散らばっていると、
「どこで何をしているのか」が分かりにくくなります。
小さなリファクタリングを1つやってみる
「名前を変える」だけでも立派な整理
リファクタリングというと、「大掛かりな書き換え」を想像しがちですが、
実は「名前を変える」だけでも立派なリファクタリングです。
例えば、次のような関数名があったとします。
function doUpdate() {
renderTasks();
updateTaskCount();
saveTasks();
}
JavaScript正直、「doUpdate」では何を更新しているのか分かりません。
これを、こう変えるだけで、読みやすさが一気に上がります。
function updateViewAndSave() {
renderTasks();
updateTaskCount();
saveTasks();
}
JavaScript名前を変えるだけなら、コードの動きは一切変わりません。
でも、「この関数は何をしているのか」が、名前だけで伝わるようになります。
11日目の課題として、「自分のコードの中で、名前がふわっとしている関数や変数を1つだけ、ちゃんとした名前に変えてみる」というのは、とても良い練習です。
11日目で一番大事な感覚
「コードは、自分だけのものじゃない」
今日のテーマは、技術的には地味かもしれません。
でも、エンジニアとしてはめちゃくちゃ重要な視点です。
コードは、未来の自分が読む。
もしかしたら、他の誰かが読む。
だから、「動けばいい」から「読める・直せる」に意識を上げていく。
ファイルを分ける
関数に名前を付ける
コメントで「なぜ」を残す
並び順を整える
こういう一つ一つの行為が、「プロっぽさ」に直結していきます。
11日目のまとめ
今日のキーポイントを短く整理すると、こうなります。
1ファイルに全部書くのではなく、「役割ごとにファイルを分ける」発想を持つ。
main.js に「状態とロジック」、ui.js に「画面とイベント」を置く構成を試してみる。
コメントは「何をしているか」ではなく「なぜそうしているか」を書くと価値が高い。
バグりやすい場所や、意図が伝わりにくい場所にだけ、ピンポイントでコメントを置く。
関数名・変数名・並び順を整えるだけでも、コードはぐっと読みやすくなる。
もし余裕があれば、
今まで書いてきたタスクアプリのコードを見直して、
「この名前、未来の自分が見て分かるかな?」
「ここ、なぜこうしているかコメントがあった方がよくない?」
「この処理、ui.js に移した方がスッキリしない?」
と、自分に問いかけてみてください。
その「ちょっと気持ち悪い」を拾って、1つずつ整えていくことが、
“天才っぽさ”ではなく、“ちゃんとしたエンジニアらしさ”を育ててくれます。

