JavaScript | 1 日 90 分 × 7 日アプリ学習:強化版カウンターアプリ(初級編)

JavaScript
スポンサーリンク

2日目のゴールと今日のテーマ

2日目のテーマは「昨日のカウンターを“ちゃんと設計された小さなアプリ”に近づけること」です。
1日目で、+1 / −1 / リセット / 0未満防止 までやりました。
今日はそこから一歩進めて、

複数ボタンを「用途別」にキレイに整理する。
数値管理を“1か所”にまとめてシンプルにする。
ちょっとした「拡張」にも耐えられる書き方を身につける。

を目指します。

機能としてはまだ同じです。
+1 / −1、リセット、0未満防止。
ただし「同じものを、より良い設計で書き直す」というのが今日のポイントです。


昨日のカウンターをもう一回、ざっくりおさらい

状態(state)と画面(view)を分ける考え方

1日目の重要ポイントはここでした。

「今の数値」は JavaScript の変数 count が本体。
画面の数字は、その count を“表示しているだけ”。

コードでいうと、こんな形でした。

let count = 0;

const counterEl = document.getElementById("counter");

function render() {
  counterEl.textContent = count;
}

render();
JavaScript

この「状態を変えたら、常に render を呼ぶ」という形は、
どんなアプリを作るときも使える基本パターンです。

ボタンごとにイベントを分けていた

1日目のイベント登録はこんな感じだったはずです。

const plusButton = document.getElementById("btn-plus");
const minusButton = document.getElementById("btn-minus");
const resetButton = document.getElementById("btn-reset");

plusButton.addEventListener("click", handlePlus);
minusButton.addEventListener("click", handleMinus);
resetButton.addEventListener("click", handleReset);
JavaScript

ここで大事なのは、

イベント登録の場所では「誰が何を担当するか」だけを書く。
実際の処理は handlePlus / handleMinus / handleReset の中にまとめる。

という“イベント分離”の考え方でした。


2日目のテーマ:「ロジックの重複」を減らす

そのまま書くと、ちょっと重複しがちなコード

例えば、1日目の処理はこんな感じだったと思います。

function handlePlus() {
  count = count + 1;
  render();
}

function handleMinus() {
  if (count === 0) {
    return;
  }
  count = count - 1;
  render();
}

function handleReset() {
  count = 0;
  render();
}
JavaScript

このままでも全然OKです。
ただ、よく見ると共通パターンがあります。

count を変える → render() を呼ぶ

これが、全部の関数で出てきています。
2日目では、この「パターン」を意識して、少し整理してみます。


数値の変更を「1つの関数」にまとめる

changeCount という“小さな専用関数”を作る

「count をどう変えるか」をまとめる関数を作ってみます。

function changeCount(delta) {
  const next = count + delta;

  if (next < 0) {
    return;
  }

  count = next;
  render();
}
JavaScript

ここでやっていることはこうです。

引数 delta(変化量)を受け取る。
次の値を next = count + delta で計算する。
もし next が 0 未満なら何もしない(return)。
OK なら count を next に更新して render を呼ぶ。

この関数は、「count を変えるときのルール」を全部持っています。
増やすときも、減らすときも、
「0 未満禁止」というルールはここで一括でチェックできます。

ボタン側は「どう変えたいか」だけを伝える

changeCount を使うと、ボタンの処理はこう書き換えられます。

function handlePlus() {
  changeCount(1);
}

function handleMinus() {
  changeCount(-1);
}

function handleReset() {
  count = 0;
  render();
}
JavaScript

ここでの設計のポイントは、

ボタン側は「何をしたいか(+1 or −1)」だけを指定する。
実際に数値を変えるロジックは、changeCount に集約される。

という役割分担になっていることです。


「0未満防止」をより“自然な場所”に置く

マイナスボタンだけが知っているのは、少し不自然

1日目のコードでは、こんな感じでした。

function handleMinus() {
  if (count === 0) {
    return;
  }

  count = count - 1;
  render();
}
JavaScript

これはこれで正しいのですが、
「0 未満禁止」というルールは、本当は「カウンター全体のルール」です。

今後、もし「−5」ボタンや「1 減らす関数」を別の場所から呼びたくなったら、
あちこちに同じ条件を書く必要が出てきます。

そこで、2日目では「0 未満防止」を changeCount の中に移しました。

function changeCount(delta) {
  const next = count + delta;

  if (next < 0) {
    return;
  }

  count = next;
  render();
}
JavaScript

こうすると、

handleMinus だけでなく、
「count を変えたいすべての処理」がこのルールの影響を受けます。

つまり、「ルールを1か所に閉じ込められている」状態です。
これが、ロジックをまとめる設計の気持ちよさです。


複数ボタンの「書き方のパターン」を意識する

1つ1つ書くパターン

今はこう書いています。

plusButton.addEventListener("click", handlePlus);
minusButton.addEventListener("click", handleMinus);
resetButton.addEventListener("click", handleReset);
JavaScript

この「1行1ボタン」パターンは、
ボタンが少ないうちは読みやすくて分かりやすいです。

2日目の段階では、この書き方でまったく問題ありません。
ただ、「同じ形が繰り返されているな」という感覚は持っておくと良いです。

無名関数で書くとどう見えるか(比較用)

イベント分離の大切さを実感するために、
あえて「全部その場で書くパターン」も見ておきます。

plusButton.addEventListener("click", () => {
  changeCount(1);
});

minusButton.addEventListener("click", () => {
  changeCount(-1);
});

resetButton.addEventListener("click", () => {
  count = 0;
  render();
});
JavaScript

これも動きます。
ただ、「処理がどこにまとまっているか」が見えにくくなります。

handlePlus / handleMinus / handleReset と分けておくと、
後から読み返したときに、

「ああ、+ボタンはここを見ればいいんだな」
「−ボタンのルールはここにあるんだな」

とすぐ分かります。

イベント分離は、「今」ではなく「未来の自分が読むとき」のためにやっている、と思ってください。


2日目の小さな発展:共通の「初期化関数」を作る

初期化(setup)を1か所にまとめる

今のコードは、おそらくこんな流れになっていると思います。

変数宣言。
DOM 要素の取得。
イベント登録。
render() を呼んで初期表示。

これを、「初期化関数」としてまとめると、少しだけ設計が一段階上がります。

function setup() {
  // 初期表示
  render();

  // ボタンイベント登録
  plusButton.addEventListener("click", handlePlus);
  minusButton.addEventListener("click", handleMinus);
  resetButton.addEventListener("click", handleReset);
}

setup();
JavaScript

ここでの意図はシンプルです。

「アプリを動かし始めるための処理」を setup に集めている。
ファイルの最後に setup(); とあることで、「ここからアプリが動き出すんだな」と分かる。

これも、「どこを見れば何が分かるか」をハッキリさせるための設計です。
小さいアプリだからこそ、こういう整理の練習がしやすいです。


2日目までの全体像をコードでイメージしてみる

全体を通して見たときの構造

説明してきた内容をざっくり一枚のイメージにすると、こうなります。

let count = 0;

const counterEl = document.getElementById("counter");
const plusButton = document.getElementById("btn-plus");
const minusButton = document.getElementById("btn-minus");
const resetButton = document.getElementById("btn-reset");

function render() {
  counterEl.textContent = count;
}

function changeCount(delta) {
  const next = count + delta;

  if (next < 0) {
    return;
  }

  count = next;
  render();
}

function handlePlus() {
  changeCount(1);
}

function handleMinus() {
  changeCount(-1);
}

function handleReset() {
  count = 0;
  render();
}

function setup() {
  render();

  plusButton.addEventListener("click", handlePlus);
  minusButton.addEventListener("click", handleMinus);
  resetButton.addEventListener("click", handleReset);
}

setup();
JavaScript

ここまで来ると、かなり「小さいけれど、設計されたアプリ」という雰囲気になっています。

状態(count)
表示(render)
数値変更ロジック(changeCount)
ボタンごとの役割(handlePlus / handleMinus / handleReset)
アプリ起動処理(setup)

という“役割の分解”が、ちゃんとコードに出ています。


2日目のまとめと、3日目へのつなぎ

今日やったことを、言葉で整理します。

count の変更ロジックを changeCount(delta) にまとめて、「増やす」「減らす」の共通部分を1か所にした。
0未満防止の条件を changeCount に集約し、「カウンター全体のルール」として持たせた。
イベント分離の意味(イベント登録と処理本体を分けること)を、1日目より一段深く理解した。
setup 関数で「初期表示+イベント登録」をまとめて、コードの全体構造を少し整えた。

3日目以降では、ここからさらに:

+5 / −5 のような追加ボタンを入れても、changeCount だけで対応できる形にする。
上限値(例えば 10 まで)を入れて、「増えすぎ防止」のロジックも追加する。
メインの count とは別に、「もう1つカウンターを増やしたらどう設計するか」を考えてみる。

といった方向で「強化版カウンター」として育てていきます。

最後に一つだけ。

今日の中で、「あ、これちょっとスッキリしたな」と感じたのはどこでしたか?
changeCount にロジックを集めたところか、setup で“アプリの入口”を作ったところか。
その「スッキリした感覚」が、設計のセンスの種です。
そこを意識しながら、3日目の強化に進んでいきましょう。

タイトルとURLをコピーしました