4-3. 演習問題
問題1:選択問題
Section titled “問題1:選択問題”1-1. try / catch を使う主な目的として最も適切なのはどれか。
- A. 実行中の問題を受け止め、どう扱うか決めるため
- B. すべてのバグを自動で消すため
- C. 変数名を短くするため
解答と解説
正解:A
- A が正しい。例外処理の目的は、問題発生時にどう振る舞うかを決めることにある。
- B は誤り。
try/catchは万能なバグ消去装置ではない。 - C は誤り。変数名の長さとは無関係である。
1-2. 空の catch ブロックが危険な理由として最も適切なのはどれか。
- A. 問題を黙って隠してしまいやすいから
- B. ループが速くなりすぎるから
- C. Git の履歴が消えるから
解答と解説
正解:A
- A が正しい。空の
catchはエラーが起きた事実を見えなくしやすい。 - B は誤り。速度の問題ではない。
- C は誤り。Git 履歴とは無関係である。
エラーが起きたときに無言で終わると、原因調査が非常に難しくなる。
1-3. 正常な処理開始や終了の記録として最も典型的なログレベルはどれか。
- A.
INFO - B.
WARN - C.
ERROR
解答と解説
正解:A
- A が正しい。正常な開始・終了・進行状況には
INFOがよく使われる。 - B の
WARNは注意状態である。 - C の
ERRORは失敗や例外向けである。
1-4. throw の主な役割として最も適切なのはどれか。
- A. 問題を呼び出し元へ伝えるために例外を投げる
- B. 変数の値を 2 倍にする
- C. ファイルを自動で保存する
解答と解説
正解:A
- A が正しい。
throwは「このまま処理を続けられないので、問題として外へ伝える」という役割を持つ。 - B は誤り。値を 2 倍にするのは計算処理であり、例外処理とは無関係である。
- C は誤り。ファイル保存は I/O の処理であり、
throw自体の役割ではない。
throw を使うと、問題が起きた場所で無理に処理を続けず、catch や呼び出し元へ判断を委ねられる。
1-5. finally ブロックが実行されるタイミングとして最も適切なのはどれか。
- A. 例外が起きたときだけ
- B. 例外が起きなかったときだけ
- C. 成功・失敗にかかわらず最後に
解答と解説
正解:C
- C が正しい。
finallyは成功時でも失敗時でも、最後の後片付けや終了ログを書きたいときに実行される。 - A は誤り。例外時だけに限定されるわけではない。
- B は誤り。正常終了時だけに限定されるわけでもない。
ファイルクローズや終了ログのように、「結果に関係なく必ず実行したい処理」を置くのが finally の典型的な使い方である。
1-6. ログへそのまま出さないほうがよい情報として最も適切なのはどれか。
- A. 処理名
- B. パスワード
- C. エラーメッセージ
解答と解説
正解:B
- B が正しい。パスワードは機密情報なので、ログへそのまま出してはいけない。
- A の処理名は調査に有用である。
- C のエラーメッセージも、内容を選べば有用な手掛かりになる。
ログは調査用に残ることが多いため、機密情報の扱いには特に注意が必要である。
問題2:穴埋め問題
Section titled “問題2:穴埋め問題”次の文章の空欄を埋めてください。
- 実行中に起きた問題を ( ) と呼ぶ。
- まず実行してみる処理を書く場所を ( ) ブロックという。
- 例外が起きたときの処理を書く場所を ( ) ブロックという。
- 成功・失敗にかかわらず最後に実行したい処理を書く場所を ( ) ブロックという。
- 何が起きたかを記録するメッセージを ( ) という。
- 明確な処理失敗を表す代表的なログレベルは ( ) である。
解答と解説
- 例外
実行中に起きた問題を表す。正常な流れから外れた状態として扱う。
- try
まず実行してみる処理を書く場所である。問題が起きる可能性のある処理を囲む。
- catch
例外が起きたときにどう扱うかを書く場所である。ログや回復処理をここへ書く。
- finally
成功・失敗にかかわらず最後に実行したい処理を書く場所である。
- ログ
プログラムの中で起きたことを記録するメッセージである。調査や監視で役立つ。
- ERROR
明確な処理失敗や例外を示す代表的なレベルである。
問題3:記述問題
Section titled “問題3:記述問題”3-1. なぜ正常系と異常系を分けて考える必要があるのか説明してください。
解答と解説
正常に進む処理と、問題が起きたときの処理は目的が違うため、分けて考えたほうが整理しやすい。 すべてを 1 本の流れに詰め込むと、どこで何が起きたか分かりにくくなる。 例外処理を分けることで、失敗時の動きを明示でき、保守もしやすくなる。
3-2. 空の catch ブロックが危険な理由を説明してください。
解答と解説
エラーが起きても記録も通知もされず、そのまま問題が隠れてしまうからである。 開発者は「なぜ動かないのか」を追えず、利用者も原因不明の失敗だけを見ることになる。 そのため、少なくともログを残す、または上位へ伝える必要がある。
3-3. 調査しやすいログには、どのような情報を含めるとよいか説明してください。
解答と解説
処理名、対象 ID、入力値の要約、成功か失敗か、エラーメッセージなどがあると調査しやすい。
単に failed と書くだけでは、何が失敗したのか分かりにくい。
その時の文脈が分かるログほど、後から役立つ。
3-4. なぜログへパスワードやトークンを出してはいけないのか説明してください。
解答と解説
ログは開発者や運用担当者が読むために残ることが多く、長期間保存される場合もある。 そこへパスワードやトークンを出すと、情報漏えいの危険が高まる。 調査に必要な情報と、出してはいけない情報を区別することが重要である。
問題4:ハンズオン
Section titled “問題4:ハンズオン”withdraw 関数に2つのバリデーションTODOを実装し、例外処理の流れを確認せよ。
取り組む内容
Section titled “取り組む内容”amount <= 0のとき"amount must be positive"のエラーを投げるamount > balanceのとき"insufficient balance"のエラーを投げる- 実行し、3つの
runDemo呼び出しのログが期待通りになることを確認する
確認したいポイント
Section titled “確認したいポイント”finallyは成功・失敗どちらでも必ず実行されることを確認する- バリデーションの順番(0以下チェック → 残高不足チェック)が結果に与える影響
runDemo(1000, -10)に変えると何番目のエラーになるか
解答と解説
③ 実行結果の例
[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 end1 回目は正常に出金できるので 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 を出すこのように、例外処理とログを組み合わせると、「何が起きたか」と「最後まで後片付けしたか」を見えるようにできる。