RPGの最初の学習で「RPGサイクル」に悩まされる人が多いようである。
これはレコード処理のメイン・ロジックを「RPGサイクル」が制御するためにメイン・ロジックが
隠蔽されてしまうため理解が困難になるようである。
しかしC言語の開発過程においても、C および C++ はWindowsメッセージの処理は
ユーザー自身が記述していたが VisualC++ではメッセージ処理は Microsoft社提供の
MFC(Microsoft Foundation Class)によって隠蔽されている。
MFCの開発者は今さらC++に戻る気はしないであろう。
「RPGサイクル」もこれと同じことでお決まりの処理は「RPGサイクル」に任せてしまってユーザーは
必要な最小限の処理だけを記述すれば良い。
RPGサイクルを使うことによってユーザー・プログラムはあたかもRPGサイクルのサブ・ルーチンで
あるかのような処理となる。
IBMが最近、RPGサイクルを推薦しなくなったのは他言語から移行した開発者にとって
理解する時間が必要だからであって、連続したバッチ処理や特に帳票印刷には
RPGサイクルはシンブルでかつバグの発生率を抑える効果を最大限に発揮する。
それではRPGサイクルを使わない場合とRPGサイクルを使った場合の比較の例をご紹介しよう。
- RPGサイクルを使わない初歩的な方法
- RPGサイクルは使わないが最適化された手法
- RPGサイクルを使った例
の3つの場合を紹介する。
プログラムは品種コード, 商品コードをアクセス・パス(キー) とする論理ファイルを読んで、
品種コード毎に改ページを行い、商品単価を品種コード毎に小計して、最後には
すべての単価の合計も印刷するプログラムである。
1. RPG005 : RPGサイクルを使わない初歩的な方法
0001.00 H Y/ 0002.00 F********** 品種別商品一覧表 ************************* 0003.00 FLSHOHNS IF E K DISK 0004.00 FHINSHU IF E K DISK 0005.00 FQPRINT O F 132 OF LPRINTER 0006.00 F***************************************************************** 0007.00 E HDR 1 1 32 見出し 0008.00 E DAR 2 10 0009.00 LQPRINT 66FL 62OL 0010.00 C****************************************************** 0011.00 C* 明 細 演 算 0012.00 C****************************************************** 0013.00 C MOVE *LOVAL BEFHNS 0014.00 C *LIKE DEFN SHSCOD BEFHNS 0015.00 C DO *HIVAL 0016.00 C SETOF 50 0017.00 C READ LSHOHNS 50 0018.00 C 50 LEAVE 0019.00 C*( 品種コードの切れ目 ) 0020.00 C SHSCOD IFNE BEFHNS 0021.00 C* ( 小計印刷 ) 0022.00 C BEFHNS IFNE *LOVAL 0023.00 C*----------------------------------------------------+ 0024.00 C SETON 43 | 0025.00 C EXSR OUTPUT | 小計印刷 0026.00 C*----------------------------------------------------+ 0027.00 C ADD SHOKEI GOKEI 90 0028.00 C Z-ADD0 SHOKEI 0029.00 C MOVE SHSCOD BEFHNS 0030.00 C END 0031.00 C SETOF 99 0032.00 C SHSCOD CHAINHINSHU 99 0033.00 C* ( 見出し印刷 ) 0034.00 C*----------------------------------------------------+ 0035.00 C SETON 41 | 0036.00 C EXSR OUTPUT | 見出印刷 0037.00 C*----------------------------------------------------+ 0038.00 C ADD SHTANK SHOKEI 90 0039.00 C END 0040.00 C*( 明細印刷 ) 0041.00 C*----------------------------------------------------+ 0042.00 C SETON 42 | 0043.00 C EXSR OUTPUT | 明細印刷 0044.00 C*----------------------------------------------------+ 0045.00 C ADD 1 KENSU 70 件数 0046.00 C END 0047.00 C*( 合計印刷 ) 0048.00 C*----------------------------------------------------+ 0049.00 C SETON 49 | 0050.00 C EXSR OUTPUT | 合計印刷 0051.00 C*----------------------------------------------------+ 0052.00 C SETON LR 0053.00 C****************************************************** 0054.00 C OUTPUT BEGSR 0055.00 C****************************************************** 0056.00 CSRN40 SETON 4041 0057.00 CSR EXCPT 0058.00 CSR OF SETOF 40OF 0059.00 CSR SETOF 414243 0060.00 CSR SETOF 444546 0061.00 CSR SETOF 474849 0062.00 CSR ENDSR 0063.00 OQPRINT E 206 41 0064.00 O UDATE Y 8 0065.00 O 14 ' 作成 ' 0066.00 O HDR,1 82 0067.00 O 128 'PAGE.' 0068.00 O PAGE Z 131 0069.00 O E 1 41 0070.00 O 10 ' 品種 コード' 0071.00 O SHSCOD 14 0072.00 O 22 ' 品種名 ' 0073.00 O HNSNAM 36 0074.00 O E 1 41 0075.00 O 10 ' 商品 コード' 0076.00 O 34 ' 商品名 ' 0077.00 O 68 ' 単価 ' 0078.00 O E 2 42 0079.00 O SHCODE 11 0080.00 O SHNAME 46 0081.00 O SHTANKJ 70 0082.00 O E 3 42 0083.00 O 50 '* 小計 *' 0084.00 O SHOKEIJ 70 0085.00 O E 1 49 0086.00 O 50 '** 合計 **' 0087.00 O GOKEI J 70 0088.00 O E 1 49 0089.00 O 40 ' 処理件数 ' 0090.00 O 57 '. . . . . . . . .' 0091.00 O KENSU 2 65 0092.00 ** HDR 0093.00 品種別商品一覧表
【 解説 】
READ
でファイル LSHOHNS
を LOOPして読み取って品種コードSHSCOD
が前に読んだ
レコードのSHSCOD
と異なるかどうかを絶えず検査して、異なっていてしかも、最初でない
場合だけに小計を出力するように自己制御しているCOBOL的な記述となっている。
これは例が品種コードだけの切れ目を検査するという簡単なものであるがレベルが
置き場コード、担当者コード、品種コード、… のように深い階層であれば大変な作業となる。
しかも小計と改ページが同時に起こるような場合とかの例外事項までをすべて考慮すると
なると、気が遠くなるばかりである。
演算の順序を見ても
となっており、これは素直は思考回路とは一致しないであろう。
メイン・アルゴリズムがこのようになっていると、ほんの少しを修正するだけでもたちまちバグの
発生要因となる。最初に記述する開発者にとって一見、わかりやすいものと写るのかも
知れないが、将来に渡る多くの危険分子を秘めているプログラムであると言わざるを得ない。
2. RPG006 : RPGサイクルは使わないが最適化された手法
0001.00 H Y/ 0002.00 F********** 品種別商品一覧表 ************************* 0003.00 FLSHOHNS IF E K DISK 0004.00 FHINSHU IF E K DISK 0005.00 FQPRINT O F 132 OF LPRINTER 0006.00 F***************************************************************** 0007.00 E HDR 1 1 32 見出し 0008.00 E DAR 2 10 0009.00 LQPRINT 66FL 62OL 0010.00 C****************************************************** 0011.00 C* 明 細 演 算 0012.00 C****************************************************** 0013.00 C DO *HIVAL 0014.00 C SETOF 50 0015.00 C READ LSHOHNS 50 0016.00 C 50 LEAVE 0017.00 C*----------------------------------------------------+ 0018.00 C SHOKEY KLIST | 0019.00 C KFLD SHSCOD | 0020.00 C KFLD SHCODE | 0021.00 C*----------------------------------------------------+ 0022.00 C SHOKEY SETLLLSHOHNS 0023.00 C*----------------------------------------------------+ 0024.00 C HNSKEY KLIST | 0025.00 C KFLD SHSCOD | 0026.00 C*----------------------------------------------------+ 0027.00 C SETOF 99 0028.00 C SHSCOD CHAINHINSHU 99 0029.00 C* ( 見出し印刷 ) 0030.00 C*----------------------------------------------------+ 0031.00 C SETON 41 | 0032.00 C EXSR OUTPUT | 見出印刷 0033.00 C*----------------------------------------------------+ 0034.00 C DO *HIVAL 0035.00 C SETOF 50 0036.00 C HNSKEY READESHSCOD 50 0037.00 C 50 LEAVE 0038.00 C*( 明細印刷 ) 0039.00 C*----------------------------------------------------+ 0040.00 C SETON 42 | 0041.00 C EXSR OUTPUT | 明細印刷 0042.00 C*----------------------------------------------------+ 0043.00 C END 0044.00 C* ( 小計印刷 ) 0045.00 C*----------------------------------------------------+ 0046.00 C SETON 43 | 0047.00 C EXSR OUTPUT | 小計印刷 0048.00 C*----------------------------------------------------+ 0049.00 C ADD SHOKEI GOKEI 90 0050.00 C Z-ADD0 SHOKEI 0051.00 C SHOKEY SETGTLSHOHNS 0052.00 C END 0053.00 C*( 合計印刷 ) 0054.00 C*----------------------------------------------------+ 0055.00 C SETON 49 | 0056.00 C EXSR OUTPUT | 合計印刷 0057.00 C*----------------------------------------------------+ 0058.00 C SETON LR 0059.00 C****************************************************** 0060.00 C OUTPUT BEGSR 0061.00 C****************************************************** 0062.00 CSRN40 SETON 4041 0063.00 CSR EXCPT 0064.00 CSR OF SETOF 40OF 0065.00 CSR SETOF 414243 0066.00 CSR SETOF 444546 0067.00 CSR SETOF 474849 0068.00 CSR ENDSR 0069.00 OQPRINT E 206 41 0070.00 O UDATE Y 8 0071.00 O 14 ' 作成 ' 0072.00 O HDR,1 82 0073.00 O 128 'PAGE.' 0074.00 O PAGE Z 131 0075.00 O E 1 41 0076.00 O 10 ' 品種 コード' 0077.00 O SHSCOD 14 0078.00 O 22 ' 品種名 ' 0079.00 O HNSNAM 36 0080.00 O E 1 41 0081.00 O 10 ' 商品 コード' 0082.00 O 34 ' 商品名 ' 0083.00 O 68 ' 単価 ' 0084.00 O E 2 42 0085.00 O SHCODE 11 0086.00 O SHNAME 46 0087.00 O SHTANKJ 70 0088.00 O E 3 42 0089.00 O 50 '* 小計 *' 0090.00 O SHOKEIJ 70 0091.00 O E 1 49 0092.00 O 50 '** 合計 **' 0093.00 O GOKEI J 70 0094.00 O E 1 49 0095.00 O 40 ' 処理件数 ' 0096.00 O 57 '. . . . . . . . .' 0097.00 O KENSU 2 65 0098.00 ** HDR 0099.00 品種別商品一覧表
【 解説 】
このプログラムは キー・リストによる READE
を効果的に使って上から下へと構造化された
処理をしているということでは評価に値するものである。
分類の数が増えたとしてもキー・リストの項目が増えるだけであって処理の構造はほとんど
変わることがないような拡張性のあるロジックに仕上がっている。
二重LOOPになっているので最初は違和感があるかも知れないがSFL
の出力にも
応用範囲が広い。
覚えておけば役に立つ手法である。
3. RPG007 : RPGサイクルを使った例
0001.00 H Y/ 0002.00 F********** 品種別商品一覧表 ************************* 0003.00 FLSHOHNS IP E K DISK 0004.00 FHINSHU IF E K DISK 0005.00 FQPRINT O F 132 OF LPRINTER 0006.00 F***************************************************************** 0007.00 E HDR 1 1 32 見出し 0008.00 E DAR 2 10 0009.00 LQPRINT 66FL 62OL 0010.00 I@SHOHIN 01 0011.00 I SHSCODL1 0012.00 C****************************************************** 0013.00 C *INL1 IFEQ '1' *INL1 0014.00 C****************************************************** 0015.00 C SETOF 99 0016.00 C SHSCOD CHAINHINSHU 99 0017.00 C* ( 見出し印刷 ) 0018.00 C*----------------------------------------------------+ 0019.00 C SETON 41 | 0020.00 C EXSR OUTPUT | 見出印刷 0021.00 C*----------------------------------------------------+ 0022.00 C END 0023.00 C****************************************************** 0024.00 C* 明 細 演 算 0025.00 C****************************************************** 0026.00 C*( 明細印刷 ) 0027.00 C*----------------------------------------------------+ 0028.00 C SETON 42 | 0029.00 C EXSR OUTPUT | 明細印刷 0030.00 C*----------------------------------------------------+ 0031.00 C ADD SHTANK SHOKEI 90 0032.00 C END TAG 0033.00 C* ( 小計印刷 ) 0034.00 C*----------------------------------------------------+ 0035.00 CL1 SETON 43 | 0036.00 CL1 EXSR OUTPUT | 小計印刷 0037.00 CL1 ADD SHOKEI GOKEI 90 | 0038.00 C*----------------------------------------------------+ 0039.00 C*( 合計印刷 ) 0040.00 C*----------------------------------------------------+ 0041.00 CLR SETON 49 | 0042.00 CLR EXSR OUTPUT | 合計印刷 0043.00 C*----------------------------------------------------+ 0044.00 C****************************************************** 0045.00 C OUTPUT BEGSR 0046.00 C****************************************************** 0047.00 CSRN40 SETON 4041 0048.00 CSR EXCPT 0049.00 CSR OF SETOF 40OF 0050.00 CSR SETOF 414243 0051.00 CSR SETOF 444546 0052.00 CSR SETOF 474849 0053.00 CSR ENDSR 0054.00 OQPRINT E 206 41 0055.00 O UDATE Y 8 0056.00 O 14 ' 作成 ' 0057.00 O HDR,1 82 0058.00 O 128 'PAGE.' 0059.00 O PAGE Z 131 0060.00 O E 1 41 0061.00 O 10 ' 品種 コード' 0062.00 O SHSCOD 14 0063.00 O 22 ' 品種名 ' 0064.00 O HNSNAM 36 0065.00 O E 1 41 0066.00 O 10 ' 商品 コード' 0067.00 O 34 ' 商品名 ' 0068.00 O 68 ' 単価 ' 0069.00 O E 2 42 0070.00 O SHCODE 11 0071.00 O SHNAME 46 0072.00 O SHTANKJ 70 0073.00 O E 3 42 0074.00 O 50 '* 小計 *' 0075.00 O SHOKEIJ 70 0076.00 O E 1 49 0077.00 O 50 '** 合計 **' 0078.00 O GOKEI J 70 0079.00 O E 1 49 0080.00 O 40 ' 処理件数 ' 0081.00 O 57 '. . . . . . . . .' 0082.00 O KENSU 2 65 0083.00 ** HDR 0084.00 品種別商品一覧表
【 解説 】
ファイル仕様書の記述が IF
ではなく IP (Input Primary) であることに注意。
RPGサイクルを使用する場合は IP
と指定すると READ
しなくても自動的にIP
として
指定したファイルが順に読み込まれてくる。
IS (Input Secondary)
としての指定した別のファイルがあれば IP のファイルのレコードを
すべて読み終えると次に IS
のファイルのレコードが読み込まれる。
マッチングを指定すると IP, IS を交互に読むことも可能である。
0010.00 I@SHOHIN 01 0011.00 I SHSCODL1
によって SHSCOD
の内容に変化があれば、標識 L1
が ON になる。
これは別の例で
I CODE01 L3 I CODE02 L2 I CODE03 L1
が指定されたとすると CODE02 や CODE03 に変化がなくても CODE01 にさえ変化が
あれば L3, L2, L1
はすべて ON になる。
つまり Ln
が ON になれば下位の Ln-1, Ln-2, ....
は すべてON になる。
このことがプログラマーが余計な例外データの場合を考慮しなくても済むようになっている
スグレモノであるといえる。
0033.00 C* ( 小計印刷 ) 0034.00 C*----------------------------------------------------+ 0035.00 CL1 SETON 43 | 0036.00 CL1 EXSR OUTPUT | 小計印刷 0037.00 CL1 ADD SHOKEI GOKEI 90 | 0038.00 C*----------------------------------------------------+ 0039.00 C*( 合計印刷 ) 0040.00 C*----------------------------------------------------+ 0041.00 CLR SETON 49 | 0042.00 CLR EXSR OUTPUT | 合計印刷 0043.00 C*----------------------------------------------------+
に見られる制御レベルに L1, L2, … LR で記述した行はレコードを最初に読み込んだときは
実行されない。次に読み込もうとしたデータが異なる品種コードであった場合に、はじめて
合計処理つまり一群のまとまりの終わりの処理としての記述を行うことになる。
このように演算をRPGサイクルでは 合計演算 と呼ぶが、合計演算では次のレコードの内容
はまだ読み込まれていない。例えば小計行に品種コードを印刷する必要がある場合であれば
最初の例であれば BEFHNS
という前のレコードのフィールド値を保管しておいて、これを印刷
する必要があるが、RPGサイクルでの合計演算ではまだフィールド値は次のレコードの
フィールド値には変わっていないのでSHSCOD
の値をそのまま印刷するだけでよい。
この結構便利な機能が最初は感覚的になかなか理解することができない。
処理自身は見ておわかりのとおりにRPGサイクルでは大変スマートでまとまりの良いものに
仕上がっている。
将来への拡張に備えても信頼性の高いプログラムになっている。