JavaScript | ゼロからはじめるプログラミング、30日で基礎を学ぶJavaScript:Webページを操作できるようになる - Day21:関数分割

JavaScript JavaScript
スポンサーリンク

Day21 前半のゴール

ここまでで、DOM 操作・入力チェック・localStorage など、かなり多くのことを学んできました。
その結果、こう感じていないでしょうか。

「コードが長くなってきて、どこに何が書いてあるか分かりにくい」
「ちょっと直したいだけなのに、あちこち触ることになって怖い」

Day21 のテーマは、まさにそこを突破するためのものです。
キーワードは 関数分割(処理の整理)
大規模化の基礎になる、とても重要な考え方です。

前半では、

処理を分けるとはどういうことか
「1つの関数がやることを減らす」感覚
名前の付け方と「役割」の考え方

ここをしっかり掴みにいきます。


なぜ関数分割が必要になるのか

1つの関数に全部書くと何が起きるか

まずは、あえて「悪い例」から見てみます。

const button = document.getElementById("submitButton");
const input = document.getElementById("nameInput");
const message = document.getElementById("message");

button.addEventListener("click", () => {
  const value = input.value.trim();

  if (value === "") {
    message.textContent = "名前を入力してください。";
    message.style.color = "red";
    input.style.border = "2px solid red";
    return;
  }

  if (value.length > 10) {
    message.textContent = "名前は10文字以内で入力してください。";
    message.style.color = "red";
    input.style.border = "2px solid red";
    return;
  }

  message.textContent = `こんにちは、${value} さん`;
  message.style.color = "black";
  input.style.border = "1px solid #ccc";
  input.value = "";
});
JavaScript

一見すると「動く」コードです。
でも、1つの無名関数(addEventListener の中)に

入力値の取得
入力チェック(空・長さ)
エラーメッセージの表示
スタイルの変更
成功時の表示
入力欄のリセット

が全部詰め込まれています。

この状態だと、

チェック条件を増やしたい
エラー表示の見た目を変えたい
成功時の処理を少し変えたい

といったときに、同じ関数の中を何度もスクロールして探すことになります。
これが「小規模のうちはいいけど、大きくなると破綻する」典型パターンです。


関数分割の基本的な考え方

「やること」を小さな役割に分ける

関数分割の本質はとてもシンプルです。

「1つの関数に何でもかんでも書かない」
「1つの関数には、1つの役割だけを持たせる」

さきほどの例で言えば、
このあたりが「分けられそうな役割」です。

入力値を取得する
入力値をチェックして、エラーかどうか判定する
エラーを画面に表示する
成功時のメッセージを表示する
見た目(スタイル)を更新する

これらを関数として切り出していくと、
コードが「意味のかたまり」に分かれて、読みやすくなります。


例題:バリデーションを関数に分ける

まずは「チェックだけ」を関数にする

先ほどのコードから、「入力チェック」の部分だけを関数にしてみます。

function validateName(name) {
  if (name === "") {
    return "名前を入力してください。";
  }

  if (name.length > 10) {
    return "名前は10文字以内で入力してください。";
  }

  return null;
}
JavaScript

この関数は、

引数として name(文字列)を受け取る
エラーがあればエラーメッセージ(文字列)を返す
エラーがなければ null を返す

という「1つの役割」だけを持っています。

イベントハンドラ側をシンプルにする

この validateName を使って、イベントハンドラを書き直します。

button.addEventListener("click", () => {
  const value = input.value.trim();

  const errorMessage = validateName(value);

  if (errorMessage !== null) {
    message.textContent = errorMessage;
    message.style.color = "red";
    input.style.border = "2px solid red";
    return;
  }

  message.textContent = `こんにちは、${value} さん`;
  message.style.color = "black";
  input.style.border = "1px solid #ccc";
  input.value = "";
});
JavaScript

さっきよりも「何をしているか」が読み取りやすくなりました。

入力値を取得
validateName でチェック
エラーならエラー表示
エラーでなければ成功処理

という流れが、上から下に素直に読めます。


さらに分割:表示処理も関数にする

エラー表示と成功表示を分ける

まだイベントハンドラの中に「見た目の変更」が残っています。
これも関数にしてしまいましょう。

function showError(messageText) {
  message.textContent = messageText;
  message.style.color = "red";
  input.style.border = "2px solid red";
}

function showSuccess(name) {
  message.textContent = `こんにちは、${name} さん`;
  message.style.color = "black";
  input.style.border = "1px solid #ccc";
  input.value = "";
}
JavaScript

これを使ってイベントハンドラを書き直します。

button.addEventListener("click", () => {
  const value = input.value.trim();

  const errorMessage = validateName(value);

  if (errorMessage !== null) {
    showError(errorMessage);
    return;
  }

  showSuccess(value);
});
JavaScript

かなりスッキリしました。
この関数を読む人は、もはや「細かいスタイルの指定」を気にしなくてよくなります。


関数分割の効果を言語化する

読みやすさ・変更しやすさ・再利用性

ここまでの分割で、何が良くなったかを整理しておきます。

読みやすさ
イベントハンドラを読むだけで「処理の流れ」が分かる。
細かい条件やスタイルは、必要なときだけ関数の中身を見ればよい。

変更しやすさ
バリデーションルールを変えたいときは validateName だけを触ればよい。
見た目を変えたいときは showError / showSuccess だけを触ればよい。

再利用性
別のフォームでも「名前のチェック」をしたくなったら、validateName をそのまま使える。
エラー表示のスタイルを統一したいときも、showError を共通で使える。

これが「大規模化の基礎」です。
1つ1つの関数を小さく、役割をはっきりさせておくことで、
コードの量が増えても「破綻しにくい」構造になります。


関数名の付け方を深掘りする

「何をするか」が一目で分かる名前にする

関数分割をするときに、実は一番大事なのが「名前」です。
名前が悪いと、せっかく分割しても読みにくくなります。

良い例としては、

validateName
showError
showSuccess
loadTodos
saveTodos
applyTheme

など、「何をする関数か」が一瞬で分かる名前です。

逆に、よくない例は、

doProcess
handleData
func1

のように、意味がぼやけている名前です。
「この関数、何してるんだっけ?」と毎回中身を見ないといけなくなります。

関数名を考えるときは、

この関数は「何をする役割」なのか
その役割を、動詞+目的語で表現できないか

を意識してみてください。
これはプロの現場でもずっと使い続けるスキルです。


小さな例で「関数分割の前後」を比べる

分割前のコード

const button = document.getElementById("calcButton");
const inputA = document.getElementById("inputA");
const inputB = document.getElementById("inputB");
const result = document.getElementById("result");

button.addEventListener("click", () => {
  const a = Number(inputA.value);
  const b = Number(inputB.value);

  if (Number.isNaN(a) || Number.isNaN(b)) {
    result.textContent = "数値を入力してください。";
    result.style.color = "red";
    return;
  }

  const sum = a + b;
  result.textContent = `合計:${sum}`;
  result.style.color = "black";
});
JavaScript

分割後のコード

function parseNumber(value) {
  const num = Number(value);
  if (Number.isNaN(num)) {
    return null;
  }
  return num;
}

function showCalcError(messageText) {
  result.textContent = messageText;
  result.style.color = "red";
}

function showCalcResult(sum) {
  result.textContent = `合計:${sum}`;
  result.style.color = "black";
}

button.addEventListener("click", () => {
  const a = parseNumber(inputA.value);
  const b = parseNumber(inputB.value);

  if (a === null || b === null) {
    showCalcError("数値を入力してください。");
    return;
  }

  const sum = a + b;
  showCalcResult(sum);
});
JavaScript

分割後の方が行数は増えています。
でも、「どこで何をしているか」は圧倒的に分かりやすくなっています。

行数が少ない=良いコード、ではありません。
「意味のかたまりごとに分かれていて、読みやすいかどうか」が大事です。


Day21 前半のまとめ

前半では、関数分割の一番大事な感覚を扱いました。

1つの関数に何でもかんでも書かない
1つの関数には 1 つの役割だけを持たせる
バリデーション・表示・状態更新などを関数に分ける
関数名は「何をするか」が分かるように付ける

ここまでが「大規模化の基礎」です。
後半では、もう少し本格的な例(フォーム+localStorage+入力チェックなど)を題材に、
実際にどう設計していくかを一緒に分解していきます。

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