メニューボタン
IBMi海外記事2018.10.11

RPGをリファクタリング(整理)する - 標識

Ted Holt著 著

プログラミングにおいて、標識が嫌だというコメントを時々耳にすることがあります。しかし、私は標識を嫌だとは思いません。私が借金をすることなくコンピューター サイエンスの学位を取得して卒業することができたのも、この何年もの間、私の家族の衣食住をまかなうことができたのも、標識がいっぱいのRPGのおかげだからです。標識にも、活躍したそれなりの良き時代があったことは言っておきたいと思います。ただ、今では、はるかに有用な、優れたプログラミング技法が使用できるようになっています。

定義済みの標識(標識変数ではなく)の使用をまったく無くすか、あるいは減らすようにコードをリファクタリングすることで、得られるメリットは非常に大きなものがあります。プログラムが使用している標識が少なければ少ないほど、そのプログラムを読み、理解し、修正し、デバッグするのがしやすくなります。この記事では、標識の使用を減らすための手法について、いくつか紹介して行こうと思います。

しかし、まずは、いくつかの用語の整理から始めます。ここでは、RPG IIIは、System/38で稼働したバージョンだけでなく、一般にRPG/400と呼ばれるネイティブなバージョンも意味するものとします。RPG IVは、普段、ILE RPGと呼ばれている、現行バージョンのRPGを意味するものとします。

  1. 未使用の標識を削除します。

当たり前すぎて言うまでもありませんが、手順その1は、設定されているものの、決して参照されない標識を識別して削除することです。コンパイラー リストでそれらが指摘されるため、これは簡単に行うことができます。以下は、RPG IIまたはRPG IIIプログラムからの出力行です。

C                     SETOF                     414243

以下は、コンパイラー リストの一部です。

Indicator References:
         INDICATOR  REFERENCES (M=MODIFIED D=DEFINED)
         LR         200M
         41         100M 300
 * 7031  42         100M
         43         100M 400

* QRG7031 Severity:  00   Number:    1                                
          Message . . . . :   The Name or indicator is not referenced.

コンパイラーは、未使用の標識42にメッセージID QRG7031のフラグを付けました。

  1. 標識の設定を変更するときは、後回しせずに、その時すぐにその標識の処理を行うようにします。

これは、30年程前、System/36のショップで働いていた頃にどこかで聞いたことです。ロバート・フロストの詩を引用すれば、そのためにどんなに大きな違いができたことかということになるでしょうか。この記事を読んで他に覚えておくべきことがなさそうだったら、この思慮深い忠告だけは覚えておいてください。

次のコード例では、標識21の使い方に注目してください。

C**                                             HILOEQ
C           BALDUE    COMP 250.00               21  21
   * * * 途中省略 * * * 
C   21                EXSR CALCDT             
   * * * 途中省略 * * *
C   21N22             MOVE 'Y'       LAST    1
    * * * 途中省略 * * *
O               21                          34 '*'

標識21はサブルーチンを呼び出し、変数への値の代入を条件付け、未払い残高フィールド(BALDUE)が250ドル以上のときはレポートでアスタリスクを出力します。標識が設定された場所とその標識を参照している場所との間には、数多くの演算行(おそらく数百行または数千行)および出力仕様書があります。

以下は、改善例です。

C           BALDUE    COMP 250.00               21  21
C                     MOVE *BLANK    BSTAT   1        
C   21                MOVE '*'       BSTAT
   * * * 途中省略 * * *
C           BSTAT     IFEQ '*'
C                     EXSR CALCDT                     
C                     END
   * * * 途中省略 * * *
C           BSTAT     IFEQ '*'
C     N22             MOVE 'Y'       LAST    1        
C                     END
   * * * 途中省略 * * *
O                         BSTAT     34                

BSTAT変数は、標識21の機能を継承します。BSTAT変数に値が割り当てられると、すぐに標識21は無関係になります。

ここからは、標識の完全な削除まであと1歩です。

C           BALDUE    IFGE 250.00
C                     MOVE '*'       BSTAT
C                     ELSE
C                     MOVE *BLANK    BSTAT
C                     ENDIF

私はO仕様書を使用しましたが、この置換手法は、外部記述プリンター ファイルおよび表示装置ファイルにも同様に適用できます。以下ではなく、

A          R DETAIL                    SPACEB(1) 
   * * * 途中省略 * * *
A  21                                34'*'

以下のようにします。

A          R DETAIL                    SPACEB(1)              
   * * * 途中省略 * * *
A            BSTAT          1A       34                       

私は、この手法を使用することにより、CHAIN、READ、READP、READE、READPE、READC、LOOKUPなどのそれぞれに、1つずつ番号付きの標識を使用した数多くのプログラムを書くことができるようになりました。

  1. RPG IVへ変換します(可能な場合)。

RPGソースの変換(CVTRPGSRC)コマンドは、RPG IIIからRPG IVへの変換を素早く処理します。RPG IVはすべてのRPGファミリー メンバーの中で最も強力であるため、より多くの標識置換の手法を自由に使用できるのも当然と言えるでしょう。最も使用頻度が高い命令コードの1つであるCHAIN命令について検討してみます。

RPG IIおよびRPG IIIでは、not-found条件を示すために「HI」の位置に結果の標識を使用します。

 ***                                            HILOEQ
C           VENDOR    CHAINAPVENDOR             75
C           *IN75     IFEQ *OFF

このプログラムをRPG IVへ変換した場合、標識の代わりに%FOUND組み込み関数を使用することができます。

C     VENDOR        CHAIN     APVENDOR        
C                   IF        %FOUND(APVENDOR)
  1. 少し時間を掛けてRPG IIまたはIIIをリファクタリングしてからでないと、RPG IVへ変換する価値が十分に得られない場合もあります。

たとえば、私はRPG IIまたはIIIでは数多くの条件付け標識を使いたくなりがちです。その理由はと言えば、RPG IVではC仕様書に条件付け標識のための場所は1つしかないから、ということに尽きます。以下がそれです。

C   31 48N17 
CANN55                MOVE 'X'       FACTR

以下よりも、リファクタリングしやすいかもしれません。

C   31       
CAN 48 
CANN17 
CANN55              MOVE      'X'           FACTR

あるいは、そうでないかもしれません。リファクタリングは1つのプロセスですが、プログラムをリファクタリングするための正しい方法は1つしかない、などということはありません。同じように有効な多くのやり方があります。

  1. 標識を削除することができない場合は、標識に自らの説明になるような名前を付けます。以下の代わりに、
If *In25;
   // Process account charges
EndIf;

以下を試してみてください。

dcl-c validAccount_25      const(25);

If *In(validAccount_25);
   // Process account charges
EndIf;

この点については、私の説明は必要ないでしょう。このテーマについては、Jon Parisが「An Indicator By Any Other Name」という記事(このサンプルはこの記事から堂々と借用させてもらっています)と「The New Basics: Indicators」という記事ですでに詳しく説明してくれているからです。

  1. RPG IIIおよびIVでは標識をデータのように扱うことができますが、RPG IIではそうすることはできません。ただし、近付くことはできます。

次のコードの標識33の使い方を見てください。

C**                                             HILOEQ
C           BCUSNO    CHAINCUST                 33
C   33                MOVE . . .
C   33                MOVE . . .
C   33                EXSR SUBREF 
C   33                MOVE . . .
C  N33                Z-ADD. . .

SUBREFが標識33を修正せず、SUBREFが呼び出すどのルーチンも標識33を修正せず、SUBREFが呼び出すルーチンから呼び出されるどのルーチンも標識33を修正しない(以下、際限なく続く)場合は、以下と等価になります。

C**                                             HILOEQ
C           BCUSNO    CHAINCUST                 33
C                     MOVE '0'       #IN33   1
C   33                MOVE '1'       #IN33
C           #IN33     IFEQ '1'
C                     MOVE . . .
C                     MOVE . . .
C                     EXSR SUBREF
C                     MOVE . . .
C                     ELSE
C                     Z-ADD. . .
C                     END

これは現在の標準からすれば素晴らしいコードではありませんが、遠い最終的な目標へ近付く1歩にはなるでしょう。私にとって目標といえば、モダンな自由形式演算仕様書ということになるでしょうか。

この記事を通して、組織で稼働している重要なコードをモダナイズするのに使用できる、いくつかの手法をご紹介できたのだとしたら喜ばしく思います。また、読者の皆様が所属されている組織では、業務を行うのに様々なソフトウェアを利用されていることと思われますが、この記事や、リファクタリングをテーマにした他の記事をお読みいただいたことで、そうしたソフトウェアもこの先まだ何年も使用を続けられるのだという希望を抱いていただけたのだとしたら、この上ない喜びです。

あわせて読みたい記事

PAGE TOP