PL/Iの「PACKAGE」を制する者は、大規模バッチの保守を制す
メインフレームの現場で長く戦っていると、「なぜこのソースはこんなに手続きが入り組んでいるのか」と頭を抱えることはないだろうか。特に、レガシーなPL/Iソースで`PACKAGE`ステートメントの境界を理解せずにパッチを当てようとすると、意図せぬリンクエラーや、デバッグ不可能なスコープ外参照の罠に足を取られることになる。
今回は、我々メインフレーム技術者が避けては通れない、`PACKAGE`ブロックの正しい解釈と、外部参照制御の「現場の作法」について深掘りしよう。
1. PACKAGEとは何か:コンパイル単位の「防波堤」
PL/Iにおける`PACKAGE`は、単なるソースコードの入れ物ではない。これは「名前の生存範囲(スコープ)を画定する防波堤」だ。
従来の古いPL/Iプログラムでは、`PROCEDURE`の中に`PROCEDURE`を入れ子にし、すべての変数がグローバルに近い状態で共有されていたものも多い。しかし、現代的なメインフレーム開発において、`PACKAGE`を適切に使用することで、意図しない変数汚染を防ぎ、モジュール間の結合度を下げることができる。
特に重要なのは、`PACKAGE`の外に公開するシンボルを`EXPORT`し、それ以外を`INTERNAL`に隠蔽するという設計思想だ。
2. 実践的なコーディング例:外部参照と内部制御
百聞は一見に如かず。実際に、VSAMファイルを読み込み、サブプロシージャで加工するような典型的なバッチ処理の構造を見てみよう。
1
/ —————————————————————— /
/ モジュール名: MYSUB01 /
/ 説明: VSAMデータ加工用パッケージ /
/ —————————————————————— /
MY_PACKAGE: PACKAGE EXPORTS(PROCESS_RECORD);
/ 内部変数: このパッケージ内からのみアクセス可能 /
DCL WORK_BUFFER CHAR(80) STATIC INITIAL(”);
/ 外部公開用プロシージャ: 呼び出し元からアクセス可能 /
PROCESS_RECORD: PROCEDURE(IN_REC) OPTIONS(REENTRANT);
DCL IN_REC CHAR(80) PARM;
/ 内部プロシージャの呼び出し /
CALL VALIDATE_DATA(IN_REC);
/ VSAM書き込み等の処理をここに記述 /
END PROCESS_RECORD;
/ 内部専用プロシージャ: EXPORT指定がないため外部からは見えない /
VALIDATE_DATA: PROCEDURE(REC);
DCL REC CHAR(80) PARM;
IF INDEX(REC, ‘ERROR’) > 0 THEN DO;
/ ONユニットによるエラーハンドリングの例 /
SIGNAL ERROR;
END;
END VALIDATE_DATA;
/ コンパイル時のお作法: 組み込み関数の明示 /
DCL (INDEX, LENGTH) BUILTIN;
END MY_PACKAGE;
このコードの「現場的」ポイント
- EXPORTS句の明示: `PROCESS_RECORD`のみを外部に公開している。これにより、他のロードモジュールから不用意に`VALIDATE_DATA`をコールされる危険性を排除できる。
- OPTIONS(REENTRANT): 大規模バッチでは、プログラムの再入可能性(リエントラント)は必須条件だ。これを怠ると、マルチスレッド環境や複数の処理ループで予期せぬメモリ破壊を引き起こす。
- BUILTINの宣言: `INDEX`や`LENGTH`などの組み込み関数は、`DCL … BUILTIN`として宣言する癖をつけておこう。コンパイラが組み込み関数であることを正確に認識し、最適化の精度が向上する。
3. 外部シンボル解決の落とし穴
現場でよくあるトラブルは、「シンボルが未解決(Unresolved External)」というリンカエラーだ。
`PACKAGE`を使用している場合、呼び出し側の`CALL`文は、リンカ(IEWBLINKやBIND)に対して「このシンボルはどこにあるんだ?」と問いかける。もし呼び出し先が別の`PACKAGE`内にあるなら、`ENTRY`宣言の整合性が取れているか、そしてリンク時にそのモジュールが適切にロードライブラリに含まれているかを再確認してほしい。
デバッグのコツ
1. コンパイラリストの確認: コンパイル時に生成される「Cross Reference」リストを見る習慣をつけよう。どの変数がどのスコープで定義され、どこで参照されているかが一目瞭然だ。
2. ONユニットの活用: `ON ERROR`や`ON ENDFILE`を適切に配置し、スタックトレースをログに出力するようにコーディングする。特に`PACKAGE`内で例外が発生した際、どのプロシージャで止まったかを特定するのに役立つ。
最後に:レガシーを「保守可能なコード」へ
古いプログラムを改修する際、無理に`PACKAGE`化しようとしてソースをバラバラにするのは危険だ。しかし、新規作成や大幅な機能追加の際には、この`PACKAGE`構造を採用することで、コードの寿命は格段に延びる。
「動けばいい」という時代は終わった。我々メインフレーム技術者に求められているのは、「10年後、別の誰かがこのコードを読んだときに、即座に設計意図が伝わる」ような品質の維持だ。
次回のバッチ改修では、ぜひこの`PACKAGE`の境界線を意識して設計してみてほしい。君たちのコードが、次世代のエンジニアに称賛されることを願っている。

コメント