メインフレームの「守護神」:PL/IのONユニットでゼロ除算を優雅にさばく
こんにちは。IBMメインフレームの世界へようこそ。
JavaやCOBOLの経験がある方にとって、PL/Iは少し「古風で気難しいプログラミング言語」に見えるかもしれませんね。確かに、パンチカード時代から続く独特の文法には驚かされることも多いでしょう。
でも、安心してください。PL/Iは、システムが予期せぬ事態に陥ったとき、「プログラムを強制終了させるのではなく、いかにして安全に着陸させるか」を考えるための、非常に強力な道具を備えています。
今日は、その代表格である「ON ZERODIVIDE」について、現場の知見を交えて紐解いていきましょう。
—
そもそも「ONユニット」って何?
JavaやC#の `try-catch` ブロックはご存知ですよね?例外が発生したその場所を囲い込むスタイルです。
一方、PL/Iの「ONユニット」は少し考え方が違います。これは「ある特定のエラーが起きたら、システム全体でこの作法(ONユニット)を実行しなさい」とあらかじめ登録しておく仕組みです。
いわば、プログラムの「守護神」を配置しておくイメージですね。
基本的な書き方
/i
/ メインプログラムの構造 /
DEMO_PROC: PROCEDURE OPTIONS(MAIN);
/ ゼロ除算が発生した時のハンドラーを登録 /
ON ZERODIVIDE BEGIN;
PUT SKIP LIST(‘警告: ゼロによる除算が検知されました!’);
/ ここでフラグを立てて処理をスキップさせるか、終了させるかを判断 /
END;
/ 通常の演算処理 /
DCL (A, B, C) FIXED DEC(5);
A = 10;
B = 0;
C = A / B; / ここで「守護神」が発動する /
END DEMO_PROC;
—
現場で直面する「ゼロ除算」の現実
メインフレームの基幹システムでは、データは生き物です。外部から来るファイルの中に、本来入るはずのない「0」が紛れ込んでいて、計算時に突然パニックになる……なんてことは、残念ながら日常茶飯事です。
そんな時、単にプログラムを異常終了(アベンド)させるだけでは、後続のジョブが止まり、夜間バッチの締め切りに間に合わなくなるという悲劇が起こります。
継続か、停止か? 現場の判断基準
ONユニット内で最も重要なのは、「このエラーから回復して処理を続けるか?」という判断です。
1. 回復して続行する場合:計算結果を強制的にゼロまたは最大値に置き換えて、次のレコードへ進みます。
2. 完全に停止する場合:整合性が取れないデータである以上、中途半端に処理せず、ログを吐いて異常終了させます。
後者の場合、単に `STOP;` を書くのではなく、`SIGNAL ERROR;` を使うのがプロの流儀です。これにより、意図的なエラーとして上位のジョブ制御(JCL)に正確な終了コードを伝えることができます。
—
初学者がハマりやすい「データ属性」の罠
PL/Iが「奇妙」と言われる理由の一つに、データ宣言の柔軟性があります。例えば `FIXED DEC(5)` という宣言。これは「5桁の固定小数点数」という意味ですが、もし計算結果が桁あふれを起こすと、ゼロ除算と同じく「例外」として扱われます。
- `FIXED BIN`: 計算速度が速い。バイナリ(二進数)演算用。
- `FIXED DEC`: 10進数計算。金額計算など「誤差が許されない」フィールドで必須。
「なぜかゼロ除算のONユニットが発動しないぞ?」と悩んだら、宣言した変数の型を確認してください。浮動小数点数(FLOAT)の場合、ゼロ除算が起きても「無限大」として計算が流れてしまうことがあり、例外ハンドリングが意図通りに動かないケースがあるんです。
—
まとめ:怖がらずに「守護神」を使いこなそう
PL/IのONユニットは、最初は慣れないかもしれませんが、一度仕組みを理解すると、これほど心強いものはありません。
- ONユニットは事後処理の予約である
- 例外が発生した箇所を特定するには `ONLOC` 関数を使うと便利
- データの属性(FIXED DECかFLOATか)を意識する
レガシーシステムの移行や改修では、こうした「エラーハンドリングの哲学」がシステム全体の堅牢性を左右します。最初は小さなテストプログラムから、わざとゼロで割ってみて、守護神がどう反応するか遊んでみてください。
メインフレームの海は広大ですが、一つひとつのキーワードを紐解けば、必ず道は見えてきます。また何か不明なことがあれば、いつでも聞きに来てくださいね。一緒にコードを読み解いていきましょう!
