コンテンツにスキップ

4-3. 演習問題


1-1. try / catch を使う主な目的として最も適切なのはどれか。

  • A. 実行中の問題を受け止め、どう扱うか決めるため
  • B. すべてのバグを自動で消すため
  • C. 変数名を短くするため

1-2. 空の catch ブロックが危険な理由として最も適切なのはどれか。

  • A. 問題を黙って隠してしまいやすいから
  • B. ループが速くなりすぎるから
  • C. Git の履歴が消えるから

1-3. 正常な処理開始や終了の記録として最も典型的なログレベルはどれか。

  • A. INFO
  • B. WARN
  • C. ERROR

1-4. throw の主な役割として最も適切なのはどれか。

  • A. 問題を呼び出し元へ伝えるために例外を投げる
  • B. 変数の値を 2 倍にする
  • C. ファイルを自動で保存する

1-5. finally ブロックが実行されるタイミングとして最も適切なのはどれか。

  • A. 例外が起きたときだけ
  • B. 例外が起きなかったときだけ
  • C. 成功・失敗にかかわらず最後に

1-6. ログへそのまま出さないほうがよい情報として最も適切なのはどれか。

  • A. 処理名
  • B. パスワード
  • C. エラーメッセージ

次の文章の空欄を埋めてください。

  1. 実行中に起きた問題を (   ) と呼ぶ。
  2. まず実行してみる処理を書く場所を (   ) ブロックという。
  3. 例外が起きたときの処理を書く場所を (   ) ブロックという。
  4. 成功・失敗にかかわらず最後に実行したい処理を書く場所を (   ) ブロックという。
  5. 何が起きたかを記録するメッセージを (   ) という。
  6. 明確な処理失敗を表す代表的なログレベルは (   ) である。
解答欄

3-1. なぜ正常系と異常系を分けて考える必要があるのか説明してください。

解答欄

3-2. 空の catch ブロックが危険な理由を説明してください。

解答欄

3-3. 調査しやすいログには、どのような情報を含めるとよいか説明してください。

解答欄

3-4. なぜログへパスワードやトークンを出してはいけないのか説明してください。

解答欄

ブラウザ上のプレイグラウンドで、例外処理とログを含む小さな JavaScript プログラムを動かしてみましょう。

① プレイグラウンドを開く

下のコードはそのまま実行できます。必要に応じて書き換えながら試してください。

実行プレイグラウンド
編集内容は自動保存されます / Ctrl+Enter でも実行できます
出力
「実行」を押すと、ここに結果が表示されます。

② コードを確認する

  • withdraw() の中で throw が使われていることを確認する
  • runDemo() の中で trycatchfinally が使われていることを確認する

③ 実行する

「実行」を押し、出力欄を確認する。

次のような表示が出れば成功:

[INFO] withdraw start { balance: 1000, amount: 200 }
[INFO] withdraw success { result: 800 }
[INFO] withdraw end
[INFO] withdraw start { balance: 1000, amount: 2000 }
[ERROR] withdraw failed: insufficient balance
[INFO] withdraw end
[INFO] withdraw start { balance: 1000, amount: 0 }
[ERROR] withdraw failed: amount must be positive
[INFO] withdraw end
  • 1 回目は成功ログが出ることを確認する
  • 2 回目は残高不足のエラーになることを確認する
  • 3 回目は金額不正のエラーになることを確認する
  • 3 回とも最後に [INFO] withdraw end が出ることを確認する

④ 値を変えてみる

※以下はそれぞれ別々に試し、1つ確認したら元のコードへ戻してから次を試す。

  • runDemo(1000, 2000)runDemo(1000, 500) に変え、成功へ変わることを確認する
  • runDemo(1000, 0)runDemo(1000, -10) に変え、どのメッセージになるか確認する

runDemo(1000, 500) に変えた場合、次のように成功ログへ変われば成功:

[INFO] withdraw start { balance: 1000, amount: 500 }
[INFO] withdraw success { result: 500 }
[INFO] withdraw end

runDemo(1000, -10) に変えた場合、次のように金額不正のエラーが出れば成功:

[INFO] withdraw start { balance: 1000, amount: -10 }
[ERROR] withdraw failed: amount must be positive
[INFO] withdraw end

問題1の解答(クリックで開く)

1-1. 正解:A. 実行中の問題を受け止め、どう扱うか決めるため

解説

  • A が正しい。例外処理の目的は、問題発生時にどう振る舞うかを決めることにある。
  • B は誤り。try / catch は万能なバグ消去装置ではない。
  • C は誤り。変数名の長さとは無関係である。

1-2. 正解:A. 問題を黙って隠してしまいやすいから

解説

  • A が正しい。空の catch はエラーが起きた事実を見えなくしやすい。
  • B は誤り。速度の問題ではない。
  • C は誤り。Git 履歴とは無関係である。

エラーが起きたときに無言で終わると、原因調査が非常に難しくなる。


1-3. 正解:A. INFO

解説

  • A が正しい。正常な開始・終了・進行状況には INFO がよく使われる。
  • B の WARN は注意状態である。
  • C の ERROR は失敗や例外向けである。

1-4. 正解:A. 問題を呼び出し元へ伝えるために例外を投げる

解説

  • A が正しい。throw は「このまま処理を続けられないので、問題として外へ伝える」という役割を持つ。
  • B は誤り。値を 2 倍にするのは計算処理であり、例外処理とは無関係である。
  • C は誤り。ファイル保存は I/O の処理であり、throw 自体の役割ではない。

throw を使うと、問題が起きた場所で無理に処理を続けず、catch や呼び出し元へ判断を委ねられる。


1-5. 正解:C. 成功・失敗にかかわらず最後に

解説

  • C が正しい。finally は成功時でも失敗時でも、最後の後片付けや終了ログを書きたいときに実行される。
  • A は誤り。例外時だけに限定されるわけではない。
  • B は誤り。正常終了時だけに限定されるわけでもない。

ファイルクローズや終了ログのように、「結果に関係なく必ず実行したい処理」を置くのが finally の典型的な使い方である。


1-6. 正解:B. パスワード

解説

  • B が正しい。パスワードは機密情報なので、ログへそのまま出してはいけない。
  • A の処理名は調査に有用である。
  • C のエラーメッセージも、内容を選べば有用な手掛かりになる。

ログは調査用に残ることが多いため、機密情報の扱いには特に注意が必要である。

問題2の解答(クリックで開く)
  1. 例外

実行中に起きた問題を表す。正常な流れから外れた状態として扱う。

  1. try

まず実行してみる処理を書く場所である。問題が起きる可能性のある処理を囲む。

  1. catch

例外が起きたときにどう扱うかを書く場所である。ログや回復処理をここへ書く。

  1. finally

成功・失敗にかかわらず最後に実行したい処理を書く場所である。

  1. ログ

プログラムの中で起きたことを記録するメッセージである。調査や監視で役立つ。

  1. ERROR

明確な処理失敗や例外を示す代表的なレベルである。

問題3の解答例(クリックで開く)

3-1. 正常系と異常系を分ける理由

正常に進む処理と、問題が起きたときの処理は目的が違うため、分けて考えたほうが整理しやすい。 すべてを 1 本の流れに詰め込むと、どこで何が起きたか分かりにくくなる。 例外処理を分けることで、失敗時の動きを明示でき、保守もしやすくなる。


3-2. 空の catch が危険な理由

エラーが起きても記録も通知もされず、そのまま問題が隠れてしまうからである。 開発者は「なぜ動かないのか」を追えず、利用者も原因不明の失敗だけを見ることになる。 そのため、少なくともログを残す、または上位へ伝える必要がある。


3-3. 調査しやすいログに必要な情報

処理名、対象 ID、入力値の要約、成功か失敗か、エラーメッセージなどがあると調査しやすい。 単に failed と書くだけでは、何が失敗したのか分かりにくい。 その時の文脈が分かるログほど、後から役立つ。


3-4. 機密情報をログへ出してはいけない理由

ログは開発者や運用担当者が読むために残ることが多く、長期間保存される場合もある。 そこへパスワードやトークンを出すと、情報漏えいの危険が高まる。 調査に必要な情報と、出してはいけない情報を区別することが重要である。

問題4の解答例(クリックで開く)

③ 実行結果の例

[INFO] withdraw start { balance: 1000, amount: 200 }
[INFO] withdraw success { result: 800 }
[INFO] withdraw end
[INFO] withdraw start { balance: 1000, amount: 2000 }
[ERROR] withdraw failed: insufficient balance
[INFO] withdraw end
[INFO] withdraw start { balance: 1000, amount: 0 }
[ERROR] withdraw failed: amount must be positive
[INFO] withdraw end

1 回目は正常に出金できるので success が出る。 2 回目は残高不足、3 回目は不正な金額なので ERROR が出る。 finally に書いた withdraw end は、3 回とも必ず出力される。


以下は、④で元のコードから 1 か所ずつ別々に変更した場合の、変更箇所に関する出力の抜粋である。


④-1. runDemo(1000, 500) に変えた場合

[INFO] withdraw success { result: 500 }

残高 1000 に対して 500 の出金は有効なので、エラーではなく成功ログが出る。 条件の違いによって、例外になるか正常終了になるかが変わることを確認できる。


④-2. runDemo(1000, -10) に変えた場合

[ERROR] withdraw failed: amount must be positive

マイナス金額も amount <= 0 に当てはまるため、金額不正として扱われる。 つまり「残高不足」よりも前に、「入力値として成り立つか」がチェックされている。


コードの流れを図で見る

runDemo 開始
[INFO] start を出す
withdraw を実行
├─ 成功 → success を出す
└─ 失敗 → catch で error を出す
finally で end を出す

このように、例外処理とログを組み合わせると、「何が起きたか」と「最後まで後片付けしたか」を見えるようにできる。