RPG

436. こんなRPGを書いてはいけないその(2)

この特約店の若きプログラマーは社内の指導を受けていないのか
上司が指導していないのかは不明だが根本的な誤りがいくつも見つかった。
_

■ SELECT文をIF文の代わりにしてはいけない

RPGマニュアルを見て書いたのかしれないが
RPGのIF文とSELECT文とは用途が全く異なるものである。
まさかこんな書き方をする人が現れるとは思わなかった。

IF文はご存知のとおり条件文であり条件の句を記述する。

     IF  *IN80 = *ON
     :
     ELSE
     :
     ENDIF

のような具合である。
 経験豊富なRPGプログラマーの方はほとんどの場合がIF-文であって
SELECT文を使ったことはほとんどないだろう。

一方、SELECT文は同じフィールド値が複数の値をとるときに
それぞれの処理を記述するのに使われる。

   SELECT
   WHEN  TYPE = '1'
   :
   WHEN  TYPE = '2'
   :
   OTHER
   :
   ENDSL

という具合でありここではフィールド : TYPEの取りうる値で条件を分岐しているのである。
 確かにどちらも条件分岐ではあるがIF-文の場合は一般的な条件の分岐を示し
SELECT-文は特定の変数のとりうる値による条件分岐を示すという性格と用途のちがいがある。
 従って読み手はSELECT-文が出てくればそういう前提としてプログラムを
解釈しようとする。ところがIF-文の意図を持って書かれた記述を
SELECT-文で書かれているので読み手は混乱するばかりである。

これは他の開発言語の siwtch-case文をRPGで表示したものである。
ところがこの特約店のプログラマーは

   SELECT
   WHEN *IN80 = *ON
    :
   WHEN TYPE = '1'
    :
   WHEN TKCODE = '0001'
    :
   ENDSL

という書き方をしていてこれでは読み手は混乱してしまう。
SELECTで分岐している条件が分岐の都度異なっているのは
何か意味があるのかと読み手は混乱していまう。
これはSELECT文を全く理解していないコーディンクでありしかも OTHER も
コーディングされていなかった。
switch-case文を学習した人ならわかるだろうが
必ずdefault分岐を書くように教育されているはずだ。
default分岐とはOTHERのことであリswitch-case以外の条件が
発生したときのことを書いておかないと例外エラーになる可能性が
あるからである。
defaultは switch-case文のはずしてはいけない基本である。
 
  このプログラマーが複雑な構造化プログラムを書くと一体どんな
プログラムが出来上がるのか想像すると怖くなる。
このようなSELECT文はもちろん見たことがないし
このプログラマーがお客さまに提供するプログラムをここまで
書く前に上司か先輩が指導すべきである。
一人でマニュアルを見ながら書いたようにも見えるが
プログラムの基礎がわかる人であれば IF文の代わりに
SELECTを書いたりはしないだろう。
RPGも含めてプログラム入門書でもどんなサンプル・ソースを
見ても必ずIF-文が最初に出てきているはずである。
覚えていないのか学習していないのか不明であるが
この人は基礎ができていない上にプログラマーには向いていない。
先輩や上司にも責任はあると思う。
このプログラマーは恐らくマニュアルを見ながら書いたのだから
結果が動作すれば良いというものではなく
正しい書き方になっているかぐらいは最初は検分して
指導してあげるべきである。
また本人も上司や先輩に閲覧して欲しいと報告すべきであるのは
当然でありそれによってこのプログラマーの将来が変わってくる。
まだ不慣れなプログラマーがこの投稿を読んでいたら
ぜひ最初のころは先輩に閲覧してもらうようお奨めする。

 _

■ *INZSRを知らないプログラマー

RPGサイクルを認めると *INZSRという特殊な名前のサブ・ルーチンを暗黙的に
使うことができる。(ただし H仕様書に NOMAINを宣言するとRPGサイクルは無視される)
*INZSRとは最初だけ実行される特殊なサブ・ルーチンである。
EXSR *INZSR のように明示的に呼び出す必要はない。
*INZSRで書かれたサブ・ルーチンの内容は自動的にいつも最初に実行される。
 
ところがこのプログラマーはそれを知らないらしく明示的に自分で
  次のように書いている。

   
    C*====================================================*                              
    C*                  MAIN                          *                              
    C*====================================================*                              
    C                   EXSR      @INTSR                                        初期処理 
    :                    :
   C*====================================================* 
    C* @INTSR            初期処理                         * 
    C*====================================================* 
    C     @INTSR        BEGSR                               
   C* 初期化                                                                 
    C                   Z-ADD     P@DAY         PHDYA                          
    C                   Z-ADD     P@DAY         PHDYB                          
    C                   Z-ADD     P@DAY         UKT051                         
    C                   Z-ADD     0             BK@TRA            5 0          
    C                   Z-ADD     0             BK@TRB            5 0          
    C                   Z-ADD     0             X                 2 0          
    C                   Z-ADD     99            WKCNT             2 0          
    C                   Z-ADD     0             WKFLG             1 0          
    C                   Z-ADD     0             WKKNA            10 0          
    C                   Z-ADD     0             WKKNB            10 0          
    C                   Z-ADD     0             PDDYA                          
    C                   Z-ADD     0             PDDYB                          
    C*                                                                         
    C                   ENDSR                                                  

のようにサブ・ルーチン @INTSR を作成して明示的にEXSR命令で最初だけの処理として呼び出していた。
_

■ RPGの初期設定を知らないプログラマー

 しかもこのプログラマーはRPGでは数字フィールドは自動的に0リセットされることを
しらないらしくご丁寧に

   C* 初期化                                                                 
    C                   Z-ADD     P@DAY         PHDYA                          
    C                   Z-ADD     P@DAY         PHDYB                          
    C                   Z-ADD     P@DAY         UKT051                         
    C                   Z-ADD     0             BK@TRA            5 0          
    C                   Z-ADD     0             BK@TRB            5 0          
    C                   Z-ADD     0             X                 2 0          
    C                   Z-ADD     99            WKCNT             2 0          
    C                   Z-ADD     0             WKFLG             1 0          
    C                   Z-ADD     0             WKKNA            10 0          
    C                   Z-ADD     0             WKKNB            10 0          
    C                   Z-ADD     0             PDDYA                          
    C                   Z-ADD     0             PDDYB  

として0リセットしていたがこれは全く不要である。
このプログラマーはRPGのフィールド値は起動時に自動的にクリヤーされることを
理解していないらしい。
他の言語: C言語や C++, VC++ などでは変数の初期値にはすべて 0xcd が埋められているので
いちいち初期化する必要があるがRPGの場合ではシステムが初期化してくれるので
プログラマーによる初期化は全く不要である。
だから経験の浅い人が作ってもRPGは正しく動作してしまうのである。
こんなに長い初期化がダラダラと続くと一般のRPGプログラマーが見ると
一体何のためにこんなことをしているのだろうと思ってしまう。
RPGの初期化について知らないプログラマーのほうがめずらしいからである。
小職もこんな初期化を見るのは初めてである。
  _
 

■ 99を最初とする不自然さ

最後にもう少しこの変わったプログラムの書き方に触れておこう。
初期化で

 C                   Z-ADD     99            WKCNT             2 0  

としているのは何のためかというとカウンター WKCNTが 99であればこれが最初であると
判断するためで後で

C* 1件目                                                                                
C     WKCNT         WHENEQ    99                                            1 件目       
C                   EXSR      @BANSR                                        領収証・ YSET
C                   Z-ADD     RYNO          PHNOA                           領収証番号   
C                   Z-ADD     UKT004        BK@TRA                          取引先退避   
C                   Z-ADD     *ZERO         WKCNT                                        

としてこれが最初であることを判定するためである。
( 先にも説明したようにこれは本来ならば

C                   IF        *IN99 = *ON

とすべきである。)

しかし最初が99であるとは他人がこのプログラムを見て違和感を感じてしまう。
最初はなぜ99が最初を意味するのかわからない。
そこでいろいろと探してみると初期化のサブ・ルーチンで最初に
99をセットしているのでああ、これが最初を意味するのだとようやくわかる。
しかしカウンターを1と比較するように次のように書いておくと
なるほどカウンターが1であれば最初だなと読み手はすぐに理解できる。
不要な調査は必要なくなる。
ここまで説明するまでもなく最初を99とするような人はほとんどいない。

C* 1件目                                                                                
C     WKCNT         WHENEQ    1                                            1 件目 
                     :

で十分でありこのほうが自然である。
最初の番号は 1であることは誰でも小学生のときから習っている。
最初の番号は99であると教えている学校はないはずだ。
 
プログラムは他人が見て不自然さや違和感を感じるような記述にしてはならない。
不自然さはバグを誘発してしまう。
このような書き方は何とか難しくしてやろうとする無用な意図を感じてしまう。
コーディングは自然で違和感のないわかりやすいプログラムを心がけるべきである。
コミュ力のない人ほど難しい言葉を使って喋ろうとするのと全く同じで
できないプログラマーのほど難しくプログラミングしようとする傾向にある。
できる人ほど肩の力が抜けた自然なプログラムを書くものだ。
プログラムはやさしく書くこと。これがまず第一の基本だ。

 _