ILE-RPGにはサブ・ルーチンに代わるプロシージャーが搭載された。
サブ・ルーチンとはメイン・ルーチンの一部であり
メイン・ルーチンの処理順序の変更に過ぎないが
プロシージャーはサブ・ルーチンとは処理は良く似ているが
実行スタックはメイン・ルーチンの上に位置する全く別の
処理である。
昔、AS/400掲示板にある開発者が「課長に今の社内システムの
サブ・ルーチンをすべてプロシージャーに書き換えるように
言われて困っています。」との書き込みがあったが
その上司の方は先見の明があったと評価されるべきであろう。
サブ・ルーチンのすべてをプロシージャーに書き換えるというのは
極端であるがRPGを近代化させるにはそれくらいやっても
よいだろう。
サブ・ルーチンとプロシージャーは次のように違いがある。
サブ・ルーチン | プロシージャー | |
---|---|---|
特性 | メイン・ルーチンの一部 | メイン・ルーチンとは別のスタック |
変数 | グローバル変数 | ローカル変数 |
結果 | なし | あり |
パラメータ | なし | あり |
[解説]
他の開発言語として VBA, VisuaBASIC, VC++ などの開発経験のある方であれば
「関数」という概念は理解できると思うがRPGのプロシージャーはこの他の開発言語の
関数とほぼ同じ機能である。
今ではないが昔はBASICにもサブ・ルーチンがあったが今ではない。
(1)カプセル化
大きな違いはサブ・ルーチンはメイン・ルーチンと変数も共有している。
プログラム全体で共通して使える変数のことをグローバル変数と呼ぶ。
これに対してプロシージャーではプロシージャー内で定義した変数は
プロシージャー内のみだけで有効であってメイン・ルーチンからは
プロシージャーの変数を参照することはできない。
このようにプロシージャー内だけの閉じた環境の変数を
ローカル変数と呼んでいる。
プロシージャーはローカル変数だけを使って定義すると
プロシージャーそのものはメイン・ルーチンからは独立したビジネス・ロジックとなる。
このような独立化のことをカプセル化と呼ぶ。
プロシージャーはカプセル化しているため独立したビジネス・ロジックであり
WRKACTJOBで見てわかるようにプロシージャーそのものがひとつのスタックとなって
実行される。
(2)結果を戻す
サブ・ルーチン自体は結果を戻す機能はないがプロシージャーは結果の値を
戻すことができる。
(3)パラメータは更新されない
IBM i ではCLPやRPGのパラメータ値も更新すると呼出し側にも更新したパラメータ値が
戻されることが一般的であるので呼び出された側のパラメータを変更すると
呼出し側に更新されて戻るものと思いがちであるが、これはIBM iが特殊であり
一般的にはパラメータ値は更新されて戻ることはない。
プロシージャーも然りであってプロシージャー内部でいくらパラメータ値を
更新したとしても呼出し側にパラメータ値が更新される戻ることはない。
ただしパラメータをポインタで渡した場合は受け取り側と送り手のポインタ値が
同じ、ということはメモリ空間内で同じ場所を更新することになるので
この場合はパラメータも更新される。
このポインタによるパラメータの受け渡しを可能にするために
RPGもポインタを扱えるようになった。
RPGがポインタを扱えることによってプロシージャーのパラメータの受け渡しだけでなく
RPGの処理はかなり柔軟なものに進化した。
(4)再利用性
オブジェクト指向という言葉を聞いたことがあるかも知れないが
サブ・ルーチンを再利用しようとするとソース・レベルでインクルードするしか
方法がない。
ソース・レベルのインクルードであれば元のソースに変更があれば
それを利用しているプログラムはすべて再コンパイルする必要がある。
オブジェクト・レベルでインクルードされている場合は
それを参照している上位のプログラムは元のオブジェクトに変更があっても
上位のプログラムを再コンパイルする必要はない。
i5/OSもこの再利用をベースに作られているのでOSのバージョン・アップが
あってもユーザー・プログラムは再コンパイルする必要はないのは
このためである。
… 次回はこの再利用の方法についてくわしく解説する。