メインフレームの守護者へ:VERIFY関数で「汚れたデータ」を弾き飛ばす鉄壁のバリデーション
システムアーキテクトとして長年、数千万行規模のレガシーコードと対峙してきたが、結局のところ、システムが死ぬ原因の8割は「想定外のデータ」だ。どんなに堅牢なVSAMのアクセスルーチンを書こうが、呼び出し元のプログラムがゴミデータを渡してくれば、結果は火を見るより明らか。
今日は、そんな「不正データ」を水際で食い止めるための、PL/Iの隠れた名脇役「VERIFY関数」について語ろうと思う。若手エンジニアがよくやる「一文字ずつループで回す」という泥臭い実装は、もう卒業だ。
—
VERIFY関数の本質的な意味
`VERIFY(string, reference)` は、実にシンプルだが強力な組み込み関数だ。
`string`(検査対象)の中に、`reference`(許可された文字セット)に含まれていない文字が最初に現れた位置(インデックス)を返す。
もし、すべての文字が許可されていれば、結果は「0」になる。この「0か、それ以外か」という単純な真理値が、バッチ処理の入り口でどれほど我々を救ってくれるか。
実務で遭遇する「数値フィールド」の罠
例えば、VSAMから読み込んだレコードの中に、「数字であるべき」フィールドがあるとしよう。桁数が多いからといって `PIC 9(10)` で受けておけば安心、というのは甘い。COBOLから遷移してきたデータや、外部インターフェースが吐き出すフラットファイルには、ご丁寧にも空白や制御コードが混入してくることがある。
これを `ON CONVERSION` で拾うのも手だが、処理が複雑化する。ここはやはり、プログラムの冒頭で `VERIFY` を使って「門前払い」するのが、最もメインフレームらしいエレガントな防衛策だ。
実践:妥当性検証のコードパターン
以下に、バッチ処理のメインプロシージャにおける、標準的かつ堅牢な実装例を示す。
1
/ PACKAGEはモジュール単位の論理分離に必須。コンパイルユニットの境界を明確にする /
TEST_VALIDATION: PACKAGE;
/ 妥当性検証を行うメインプロシージャ /
MAIN_PROC: PROCEDURE OPTIONS(MAIN);
DCL INPUT_REC CHAR(20) VAR;
DCL ALLOWED_CHARS CHAR(10) CONSTANT(‘0123456789’);
DCL ERROR_POS FIXED BIN(15);
/ VSAM入力想定:実際にはここに入出力ルーチンが入る /
INPUT_REC = ‘12345A7890’;
/
- VERIFYの真骨頂:
- 許可された文字セット(0-9)以外の文字があれば、その位置を返す。
- 0以外が返れば、それは即ち「不正なデータ」である。
/
ERROR_POS = VERIFY(INPUT_REC, ALLOWED_CHARS);
IF ERROR_POS ^= 0 THEN DO;
/
- 現場の知見:ログには「何が」ではなく「どこが」ダメなのかを正確に出せ。
- 後でダンプを追う時のストレスが雲泥の差になる。
/
PUT SKIP LIST(‘データ検証エラー:不正文字を検出しました’);
PUT SKIP LIST(‘エラー発生位置: ‘, ERROR_POS);
PUT SKIP LIST(‘該当フィールド: ‘, INPUT_REC);
/ 異常終了コードを返してJCL側のSTEPを落とすのが定石 /
SIGNAL ERROR;
END;
ELSE DO;
PUT SKIP LIST(‘データは正常です。処理を続行します。’);
END;
END MAIN_PROC;
END TEST_VALIDATION;
デバッグのコツと現場の鉄則
1. 空白を許容するか否かを明確にする:
もし数値項目に「右詰め空白」が許されるなら、`VERIFY(TRIM(INPUT_REC), ‘0123456789’)` と書くべきだ。`TRIM`を組み合わせることで、意図しない空白混入エラーを回避できる。
2. ONユニットとの併用:
`VERIFY` でチェックしきれない複雑な構造(例えば、特定の桁数以降はアルファベット不可など)は、`ON CONVERSION` ユニットを定義して、PL/Iのランタイムにエラーをトラップさせるのが王道だ。しかし、まずは `VERIFY` で「物理的に正しいデータか」を弾く。この二段構えが、堅牢なシステムの秘訣である。
3. 大文字記述の美学:
メインフレームのコンパイラは優秀だが、ソースコードの可読性は人間のためにある。`VERIFY` や `TRIM` のような組み込み関数は、他のエンジニアがパッと見て意図を理解できるよう、インデントとコメントを徹底してほしい。
最後に
「なぜPL/Iなのか?」と問われたら、私はいつも「制御の柔軟性と、ハードウェアに近いところでの型管理の厳格さ」と答える。`VERIFY` 関数一つとっても、その挙動を理解し、適切に使いこなすことで、深夜の呼び出しを何件減らせるか。
データは嘘をつかない。だが、データはしばしば「汚れている」。その汚れを、我々の書くコードでいかに綺麗に処理するか。それがシステムアーキテクトとしての矜持だ。
さあ、次のバッチ改修では、`IF` 文で長々と比較演算子を並べるのはやめて、この美しい関数を試してみてくれ。健闘を祈る。
