ゼロ除算の悪夢を制御せよ:PL/IにおけるONユニット活用の処方箋
メインフレームのバッチ処理において、最も避けるべきは「突発的なアベンド(異常終了)」だ。特に、数百万件のレコードを処理する基幹バッチの最中に、たった一件の不正データでプログラムが落ちた時の絶望感と言ったら……。
今日は、その代表格である「ゼロ除算(ZERODIVIDE)」をいかにスマートに、かつ確実にハンドリングするか、現場の知見を交えて伝授する。
—
1. なぜ「そのまま」にしてはいけないのか
初心者はよく、「入力データが0なら計算前にIF文で弾けばいい」と言う。もちろん、それは正しい。しかし、現場のシステムはそんなに単純じゃない。外部連携ファイルやVSAMから読み込んだデータが、何らかの理由で定義と異なる数値を持つことなど日常茶飯事だ。
IF文で全てを網羅しようとすれば、コードはネストの迷宮と化す。ここでPL/Iの真骨頂である`ONユニット`の出番だ。これは、例外が発生した瞬間に制御を奪い、異常終了を防ぐための最強の盾となる。
2. ON ZERODIVIDEの実践的な構造
まずは、標準的なコードの型を見てほしい。
/i
/ ================================================================= /
/ プログラムID: CALC001 /
/ 概要: VSAMレコードの除算処理とゼロ除算トラップの例 /
/ ================================================================= /
CALC_MAIN: PROC OPTIONS(MAIN);
/ — 定義部 — /
DCL DIVIDEND FIXED DEC(15, 2);
DCL DIVISOR FIXED DEC(15, 2);
DCL RESULT FIXED DEC(15, 2);
DCL ERROR_FLAG BIT(1) INIT(‘0’B);
/ — ONユニットの定義 — /
/ ゼロ除算発生時、このブロックに制御が飛ぶ /
ON ZERODIVIDE BEGIN;
PUT SKIP LIST(‘警告: ゼロ除算が発生しました。計算をスキップします。’);
ERROR_FLAG = ‘1’B;
/ GOTO文で処理フローを復帰させるのが定石 /
GOTO CALC_EXIT;
END;
/ — メイン処理ループ(概念) — /
/ ここではVSAMアクセスを想定したロジックの断片 /
DIVIDEND = 1000.00;
DIVISOR = 0.00; / ここで意図的にゼロを設定 /
RESULT = DIVIDEND / DIVISOR;
CALC_EXIT:
IF ERROR_FLAG THEN
/ エラー時の後処理をここに記述 /
PUT SKIP LIST(‘処理を正常に継続します。’);
ELSE
PUT SKIP LIST(‘計算結果: ‘ || CHAR(RESULT));
RETURN;
END CALC_MAIN;
3. 実務エンジニアが教える「ハマりどころ」
このコードを見て、「ONユニットの中にGOTOを書くのは汚い」と感じただろうか? だが、メインフレームの実務においては、「プログラムを落とさないこと」が正義だ。
ここで、トラブルシューティングの勘所をいくつか共有しておく。
- ONユニットの有効範囲を意識せよ:
ONユニットは、定義した場所からそのブロック(あるいは後続のブロック)全体に有効だ。しかし、不用意に広範囲に定義すると、どこで飛んだか分からなくなる。原則として、計算を行うブロックの直前で定義し、終わったら`REVERT`で解除するのがクリーンな設計だ。
- SIGNAL文によるテスト:
実機テストでゼロ除算を再現するのは難しい。そんな時は `SIGNAL ZERODIVIDE;` をコードに埋め込んで、強制的にONユニットが発火するかを確認する癖をつけよう。
- 戻り先の制御:
`GOTO`を使わずに処理を継続したい場合は、`FIXEDOVERFLOW`や`ZERODIVIDE`のONユニット内で計算結果にデフォルト値(0や999…)を代入する方法もある。しかし、バッチの監査ログを考えると、今回の例のようにフラグを立ててログを出し、処理をスキップさせるのが最も追跡しやすい。
4. 最後に:メインフレームの流儀
PL/Iが現代の言語と決定的に違うのは、ハードウェアの演算例外を言語仕様レベルでここまで綺麗にラッピングできる点だ。
「エラーが起きたら止まる」のは他言語の標準かもしれないが、メインフレームの世界では「エラーが起きても、何事もなかったかのようにバッチを完走させる」のがプロの仕事だ。ONユニットを使いこなすことは、システム全体の堅牢性を担保することに直結する。
次のバッチ改修では、ただIF文を並べるのではなく、この「盾」を正しく装備してコーディングしてみてほしい。もし不明点があれば、いつでも聞くように。我々メインフレームアーキテクトの仕事は、レガシーを「枯れた技術」ではなく「信頼の基盤」として守り抜くことなのだから。
