CL

161. CLPの開発を飛躍的に向上させる4つの方法

最新のCLPの開発をしているとCLPの開発が飛躍的に効率良くなった
原因が4つ挙げられるのでそれを記述したい。
読者もこれらの4つの項目を活用することによって
CLPの開発は飛躍的に良くなると思われるので
ぜひ参考にして頂きたい。
_

(1) *DEFINEDによる二重定義の活用

最初に頻繁に使われるというか必ず使うのが *DEFINEDによる
変数の二重定義である。
これはRPG の DS(=Data Structure)定義と原理は同じである。

             DCL        VAR(&PGMOBJLIB) TYPE(*CHAR) LEN(20)      
             DCL        VAR(&PGM) TYPE(*CHAR) STG(*DEFINED) +    
                          LEN(10) DEFVAR(&PGMOBJLIB)             
             DCL        VAR(&OBJLIB) TYPE(*CHAR) STG(*DEFINED) + 
                          LEN(10) DEFVAR(&PGMOBJLIB 11)          

これは &PGMOBJLIB = &PGM + &OBJLIB であることを表している。
&PGMOBJLIB と &PGM, &OBJLIBとは一体のものであるので
どちらを更新しても他方の変数値も同時に内部で更新される。

これをCLPの演算で

      CHGVAR &PGM %SST(&PGMOBJLIB 11)
      CHGVAR &OBJLIB %SST(&PGMOBJLIB 11 10)

とやるよりははるかにスマートである。
プログラムはやはり洗練されたものであれば品質が保証される。

(2) CLPサブルーチンの活用

_

CLPでもサブルーチンが使えることをご存知だろうか?
サブルーチンは ENDPGMの直前に記述する。
サブルーチンの呼出しは CALLSUBRで呼び出す。
サブルーチンの始まりは SUBR で始まって
ENDSUBRで終わる。
サブルーチンを途中で抜け出したい場合は
RTNSUBR で脱出することができる。
サブルーチンの結果は INT4 の変数で戻すことができる。
次の例では最初に行う演算をすべて INZSUBRという名前の
サブルーチンにまとめてある。
このようにサブルーチンは複数回の実行がなくても
要所、要所をサブルーチンとしてまとめておけば
CLPは非常に見やすくする。
これが CLPサブルーチンの効果である。
ただし CALLSUBR MAIN のようにすべてのサブルーチンを
ひとつにしてしまうような愚行は避けるべきである。
RPG でいきなり EXSR MAIN とするような人は
愚行という他はない。

 
 /*---------------------------*/
   CALLSUBR   SUBR(INZSUBR)    /*サブルーチンの呼出し*/
 /*---------------------------*/

          /******************************/             	
             SUBR       SUBR(INZSUBR)   /* 初期設定 */
         /******************************/             
              :
             RTNSUBR
              :
             ENDSUBR

(3) SELECT-WHEN 分岐の活用

 論理の分岐でIF文を多重に重ねてしまうと論理構造が
非常にわかりにくくなってしまう。
オーブン系のC言語などで使うSWITCH-CASE文を
今ではCLPでも使えるようになっている。

      SELECT
      WHEN (&FLD = 'A') DO
      ENDDO
      WHEN  (&FLD = 'B') DO
      ENDDO
       :
      OTHERWISE DO
      ENDDO
      ENDSELECT

のように記述する。OTHERWISE は記述しなくてもよい。
これによってCLPの論理構造は構造化されて非常に見やすくなり
保守も容易となる。
IF文を多用するよりはぜひSELECT文にまとめるべきである。
ILE-RPGの開発でも同じことである。

(4) CLPでのポインタの活用

_

CLPでポインタなど使うのかと思われるかも知れないが高度な構造化された
アプリケーションを開発しようとするとサービス・プログラムやIBM APIを
多用することは多い。
ボインタとは変数がメモリされる開始位置のことである。
よくポインタとは「番地」と表現している書籍があるがその本はそれ以上
読まないほうがよい。その著者はポインタの概念をよく理解していないからである。
ボインタの説明は「148.CLPでポインタを学習する(1)
サービス・プログラムなどからの戻り値はパラメータとして戻ってくる。
IBM iの開発をしているとCLPやRPGでパラメータを更新すると
呼び出した側にも値が戻ることが一般的なのでパラメータで普通に
戻り値を取得できると考えている人が多いと思うが実はRPGやCLPで
パラメータで戻すことができることが特殊であって他の言語では
そのようなことはできない。
他のC言語やVisualXXのような言語でパラメータは呼び出されたプログラムは
別のメモリ空間が変数の保管場所として確保されるので
呼び出された側のプログラムがいくらパラメータを更新したとしても
呼出し側に値を戻すことができない。
しかしパラメータをポインタで渡すと同一コンピュータ内の同じメモリの場所を
共有することになるので呼び出された側で更新して値は呼出し側に戻すことが
できる。
前置きの説明が長くなったがパラメータとしてポインタを渡せば値を戻すことが
できるのでサービス・プログラムやAPIの戻り値はポインタで定義されている。

従ってCLPでサービス・プログラムやAPIを多用する高度なCLPであれば
ポインタの使用はごく一般的なものである。
筆者が開発している製品でもほとんどのCLPでポインタを定義している。
_

さてポインタの使い方としては

(1)ある変数からその変数のポインタを定義する

(2)ポインタを基底とする変数を定義する

のふたつの方法がある。

(1)ある変数からその変数のポインタを定義する

              DCL        VAR(&PANELNAM) TYPE(*CHAR) LEN(10)           
              DCL        VAR(&PANEL_P) TYPE(*PTR) ADDRESS(&PANELNAM 0)

変数 &PANELNAM に対してこの変数のポインタを &PANEL_P として
定義する

(2)ポインタを基底とする変数を定義する

             DCL        VAR(&PTR) TYPE(*PTR)                   
             DCL        VAR(&STRING) TYPE(*CHAR) STG(*BASED) + 
                          LEN(32767) BASPTR(&PTR) 

ポインタ &PTR を定義してこのポタンを基底とする32767バイトの変数:&STRINGを
定義する。

 実際のAPIやサービス・プログラムの呼出しの方法は別の機会に説明するが
ソフトウェア会社としてプロとして開発するのであれば
CLPのポインタくらいは自由に使えるようにしておきたい。

JavaはC言語でポインタを苦手としいてる人が多いということで
ポインタの概念を無くしてしまったのだがそのため汎用性が無くなってしまい
今では衰退してしまった。
何でもやさしくすればいいというものではなくて必要なポインタという概念を
取ってしまうと言語として発達はできない。
ポインタを無くしたJavaでもポインタ・エラーが出るのは皮肉な話でもある。