【PL/I学習|実務向け】PL/IにおけるSTRUCTUREメンバの解決順序と「完全修飾」の重要性

1. 導入:なぜこの解決順序を理解すべきか

メインフレームのレガシーシステム保守において、PL/IのSTRUCTURE(構造体)のメンバ参照は、バグの温床になりがちです。特に複数の構造体で同名のメンバが存在する場合、コンパイラがどの変数を「意図したもの」として選択するかという解決規則を知らなければ、データ破壊や誤った計算結果を引き起こします。「何となく動いている」コードを放置せず、PL/Iのスコープ解決ルールを正しく理解することは、堅牢なシステム運用に不可欠です。

2. 基礎知識:PL/Iのスコープ解決アルゴリズム

PL/Iには、メンバ名が重複した場合にどの変数を優先するかを決める「解決順序」が存在します。基本的には、現在参照している箇所から最も内側のレベル(最も近い親)から外側に向かって検索が行われます。しかし、複数の構造体が同じレベルに並んでいる場合、コンパイラは宣言順序や修飾の有無に基づいて決定を下します。これを「修飾の省略」と呼びますが、現代のプログラミング言語の感覚からすれば、これは極めて曖昧で「危険な仕様」です。

3. 実装/解決策:完全修飾名(Qualified Name)の原則

実務における解決策はシンプルです。「可能な限り、常に完全修飾名で記述する」こと、これに尽きます。例えば、構造体Aの中の変数IDを参照する場合、単に「ID」と書くのではなく、「A.ID」と記述します。もし構造体が階層化されているなら、「父.子.ID」のように、トップレベルの構造体名から記述するのが最も安全です。これにより、コンパイラによる推測を排除し、コードの可読性と保守性を劇的に向上させます。

4. サンプルプログラム

以下の例は、同名のIDを持つ2つの構造体が存在するケースです。コメント部で解説する「完全修飾」による参照を推奨します。

/ 構造体の定義 /
DCL 1 EMP,
      2 ID   CHAR(5),
      2 NAME CHAR(20);

DCL 1 DEPT,
      2 ID   CHAR(5),
      2 NAME CHAR(20);

/ --- 処理部 --- /

/ 悪い例:単にIDと書くと、コンパイラがどちらを指すか曖昧になる可能性がある /
/ ID = '100'; /

/ 良い例:完全修飾名で記述する /
EMP.ID = 'A001';  / EMP構造体のIDを明示的に指定 /
DEPT.ID = 'D999'; / DEPT構造体のIDを明示的に指定 /

PUT SKIP LIST('EMP ID:', EMP.ID);
PUT SKIP LIST('DEPT ID:', DEPT.ID);

5. 応用・注意点:現場で陥りやすいバグの回避策

現場で最も注意すべきは、既存の「省略された参照」が含まれるレガシーコードの移行です。現代の言語(JavaやC#など)に移行する際、PL/Iの曖昧な解決規則をそのまま変換ツールに任せると、ロジックが崩壊することがあります。

回避策として以下の3点を推奨します。
1. 解析ツールの活用:PL/Iアナライザ等を用いて、すべての省略されたメンバ参照を完全修飾名に展開する。
2. コードレビューの徹底:構造体のメンバ名に、あえてプレフィックス(例:EMP_ID, DEPT_ID)を付与する命名規則への変更を検討する。
3. コンパイラオプションの利用:もし環境が許せば、曖昧な参照を警告(Warning)として出力するコンパイラオプションを有効にし、ビルド時に検知する仕組みを構築してください。

「記述の省略」はコーディングの効率化ではなく、将来のバグ発生コストを高める要因であることを肝に銘じてください。

コメント

タイトルとURLをコピーしました