HTTPサーバーとWeb開発

72. RPG# 入門bP

ここからのシリーズでは RPG# による Web開発手法を紹介しよう。
RPG# とは潟Iフィスクアトロが提唱する新しいWeb開発のための RPG言語である。
RPG# はイベント駆動型 の RPG 言語であり、従来の RPGソースのように
メイン・ルーチンは持っていない。
HTML という GUI画面をインターフェースとしているのでエンド・ユーザーが
ボタンを押した、などの事象(イベント) に対する演算を記述するだけである。
RPG# は、また HTMLドライバー という HTML とのゲートウェイによって
HTML を DSPF のようにとらえて外部記述によって RPG の READ/WRITE 命令だけで
HTML に対する入出力を行うこともできる。
編集コードや編集語やフィールド属性も HTML に記述することができる。
つまり HTML を DSPF のように完全に外部記述ファイルとして見なすことができるのである。
RPG# の詳細は別途、「RPG#読本」を参照していただくとして
( 「RPG#読本」は潟Iフィスクアトロから入手することができる。くわしくはこちらで )
RPG# は eStduio によってボタン操作だけであっという間に Wizard 生成することが
できるが、ここでは動作原理を学習するためにあえて手動によって RPG# を
作成する方法を紹介する。

ここでの「こんにちは、皆さん」という文字列と 128,000 という数字表記は
変数であり、RPG# として作成された WEB001 という CGI (プロクラム) によって
出力されるものとする。
HTML は非常に簡単なもので次のとおりである。

----------------------------------------------------------------------
<HTML>
<HEAD></HEAD>
<BODY>
<span name=MSG alt="22O">######################</span>
<br>
数量は <span name=SURYO alt="7S0" EDTCDE(J)>#,###,####</span>です。
<br>
</BODY>
</HTML>
----------------------------------------------------------------------

この HTML は System i の IFS に /AS400-NET.USR/PROJECT/WEB001/DSPHEAD.HTM
として登録しておく。つまりこの HTML の名前は DSPHEAD.HTM という名前である。

変数 MSG は span タグによって

<span name=MSG alt="22O">######################</span>

として登録されており、変数の属性は alt="22O" として 22バイトのオープン・フィールドである。
出力イメージは ### .... # として 22個の # で表されている。

数字の SURYO というフィールドも span タグによって

<span name=SURYO alt="7S0" EDTCDE(J)>#,###,####</span>

として定義されている。数字の表示には EDTCDEEDTWORD も指定することができる。
この HTML テンプレートをブラウザで表示すると次のように表示される。

先の出力結果の HTML イメージと、ほぼ同じである。
このように HTMLテンプレートが CGI ソースとは完全に分離されていることは
非常に重要な意味を持つ。

- ビジネス・ロジックとビューの完全分離ができるので

話はやや逸れてしまうが、もし CGI ソースや別の XML 等に HTMLイメージが混在してしまうのであれば
開発や保守は結果のHTML を想像または設計しておいてから再びロジックに組み込むという難解な
作業となってしまう。
開発の際は HTML出力イメージを重い浮かべることはできても、数年経過した後や他人による保守は
到底、無理である。
しかし他社製品や PHP, JSP では混在化されており保守となるとノイローゼになってもおかしくないほどの
複雑な工程を強いられてしまうことになる。

さて話を戻して上記の HTML を出力する RPG# のソースはとてもシンプルであり
下記のようになる。

--------------------------------------------------------------------------------
0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/) DFTNAME(WEB001)        
0002.00 F********** RPG# 入門bP ********************************************* 
0003.00 FWEB001H   CF   E             SPECIAL PGMNAME('ASNET.COM/HTMLDVR')      
0004.00 F                                     PLIST(HPARM)                      
0005.00 F                                     INFDS(INFDSF)                     
0006.00 F********************************************************************** 
0007.00  /COPY ASNET.USR/QRPGLESRC,PROTOTYP5#                                   
0008.00 D HTM_FILE        S             10A   INZ('WEB001H   ')                 
0009.00 D HTM_LIB         S             10A   INZ('*LIBL     ')                 
0010.00 D HTM_DIR         S            128A   INZ('/AS400-NET.USR/PROJECT/-     
0011.00 D                                     WEB001')                          
0012.00 D HELLO_WORLD     C                   CONST(' こんにちは、皆さん。 ')   
0013.00 D*( ファイル情報データ構造 )                                            
0014.00 D INFDSF          DS                                                    
0015.00 D                              512A                                     
0016.00 D  HTM_RECORD       *RECORD                                             
0017.00 D*( プログラム状況データ構造 )                                          
0018.00 D INFDSP         SDS                                                    
0019.00 D                              512A                                     
0020.00  /COPY ASNET.USR/QRPGLESRC,HPARM                                        
0021.00 *********************************************************               
0022.00 P EVENT           B                   EXPORT                            
0023.00 *********************************************************               
0024.00 D                 PI                                          
0025.00 P                 E                                           
0026.00 *********************************************************     
0027.00 P BEGIN           B                   EXPORT                  
0028.00 *********************************************************     
0029.00  * 最初の画面を出力します。                                   
0030.00 D                 PI                                          
0031.00 C                   MOVEL(P)  HELLO_WORLD   MSG               
0032.00 C                   Z-ADD     128000        SURYO             
0033.00 C                   WRITE     DSPHEAD                         
0034.00 P                 E                                           
0035.00 *********************************************************     
0036.00 P END             B                   EXPORT                  
0037.00 *********************************************************     
0038.00  * 最後の処理を記述します。                                   
0039.00 D                 PI                                          
0040.00 C                   CLOSE     WEB001H                         
0041.00 P                 E                                           
--------------------------------------------------------------------------------

結論から解説すると値をセットして HTML を出力しているのは、

0031.00 C                   MOVEL(P)  HELLO_WORLD   MSG               
0032.00 C                   Z-ADD     128000        SURYO             
0033.00 C                   WRITE     DSPHEAD   

のわずか 3行のステップだけである。
また、このプログラム・ソースを見てもどこにも製品独自の命令もないことが
おわかりであろう。

0003.00 FWEB001H   CF   E             SPECIAL PGMNAME('ASNET.COM/HTMLDVR')

で定義されている ASNET.COM/HTMLDVR というプログラムが HTMLドライバーである。
WEB001H という名前の DSPF に対する READ/WRITE 命令が実行されると
OS400 は ASNET.COM/HTMLDVR というプログラムを呼び出して、それに制御を渡して
実行する。つまり、

0033.00 C                   WRITE     DSPHEAD 

が実行されるときは DSPF : WEB001HWRITE されるのではなく、
HTMLドライバー : ASNET.COM/HTMLDVR が呼び出されるのである。
HTMLドライバーは WRITE DSPHEAD の命令によって DSPHEAD に定義されている
フィールド名と各々の値を知って、それらを HTML テンプレートに更新してから
ブラウザへ出力を戻すのである。
HTMLドライバーは呼び出されたときに初めて DSPF: WEB001H のオブジェクト構造を
即座に調べてフィールド情報や編集や妥当性検査の情報もリアルタイムに検索する。
HTMLドライバーが DSPF オブジェクトを高速で即座に検索する技術は過去の TONAKAI によって
培われた弊社の高度なアーキテクチャーでもある。

さて DSPF: WEB001H は、いつのまに生成されたのであろうか ?
実は RPG# のコンパイルは CRTRPGMOD ではなく CRTWEBMOD という弊社提供のコンパイラーによって
行う。
CRTWEBMOD とは簡単に言えば、 CRTDSPF + CRTRPGMOD である。
CRTWEBMOD によって HTMLソースから WEB001H という CGI名 + 'H' という名前の形式の DSPFソースが
ライブラリー :ASNET.USR の DSPF: QDSPSRC に一時的に生成されて CRTDSPF が実行される。
CRTWEBMOD は HTML の span タグを検索して、それを DSPF のフィールド情報に変換するのである。
この DSPFソースの内容を RPG# のプログラマーが感知する必要は一切、ないがどのような
ソースが生成されているのかを紹介しよう。

-----------------------------------------------------------------------------------
0001.00      A*****************************************************************    
0002.00      A*  HTML RECORD-BUFFER  :  2009 年 11 月 01 日  12:56:27         *    
0003.00      A*****************************************************************    
0004.00      A*%%     THIS IS A TEMPORARY SOURCE FILE GENERATED FROM HTML          
0005.00      A*%%     BY CRTWEBMOD , ENTERPRISE SERVER VER 5.1                     
0006.00      A*%%     DO NOT CHANGE THIS SOURCE FILE.                              
0007.00      A*                                                                    
0008.00      A                                      DSPSIZ(24 80 *DS3)             
0009.00      A                                      MSGLOC(24)                     
0010.00      A                                      PRINT                          
0011.00      A*/AS400-NET.USR/PROJECT/WEB001/DSPHEAD.HTM                           
0012.00      A          R DSPHEAD                                                  
0013.00      A            MSG           22O  O  1  2                               
0014.00      A            SURYO          7Y 0O  1  2EDTCDE(J)                      
-----------------------------------------------------------------------------------

DSPF ソースを生成するのであれば、24 * 80 の制限が付きまとうのではないかと考える読者も
いると思うが、実はこの DSPF は 24 * 80 の制限を受けることない。
24 * 80 の制限は表示上の制約であって
RPG# で使用する DSPF のフィールドの定義は

0013.00      A            MSG           22O  O  1  2
0014.00      A            SURYO          7Y 0O  1  2EDTCDE(J)

で表されているように、すべて 1行目 2桁目として定義されている。
CRTDSPF では警告とはなるが 正常に CRTDSPF は実行されて DSPFオブジェクトを生成することが
できる。

RPG# では DSPF を単なるレコード・バッファーとして使用しているだけなので
このようにバッファーとしてのフィールドであれば、いくつでも定義することができるのである。
表示する必要がないのですべて 1行目2桁として定義されて 80桁をオーバーすることはない。
しかしレコード上のフイールド毎のバッファー・エリアはしっかり正常に確保されているのである。

RPG# ソースに戻って解説を続ける。

0001.00 H NOMAIN BNDDIR('ASNET.COM/MAIN') DATEDIT(*YMD/) DFTNAME(WEB001)

で示されているように NOMAIN としてこのRPG にはメイン・ルーチンは存在しない。
しかし RPG# のメイン・モジュールによって最初に 「BEGIN」という
プロシージャーが呼び出されて実行される。

0026.00 *********************************************************
0027.00 P BEGIN           B                   EXPORT             
0028.00 *********************************************************
0029.00  * 最初の画面を出力します。                              
0030.00 D                 PI                                     
0031.00 C                   MOVEL(P)  HELLO_WORLD   MSG          
0032.00 C                   Z-ADD     128000        SURYO        
0033.00 C                   WRITE     DSPHEAD                    
0034.00 P                 E  

この BEGIN プロシージャーが今回の演算の目的のすべてである。
また最後には「END」という名前のプロシージャーが呼び出されることが
決まりごとになっている。

0035.00 *********************************************************
0036.00 P END             B                   EXPORT             
0037.00 *********************************************************
0038.00  * 最後の処理を記述します。                              
0039.00 D                 PI                                     
0040.00 C                   CLOSE     WEB001H                    
0041.00 P                 E  

RPG# ではイベント処理を記述するための「EVENT」という名前のプロシージャーも
必要となるがここでは何もイベントは記述されていない。

0021.00 *********************************************************
0022.00 P EVENT           B                   EXPORT             
0023.00 *********************************************************
0024.00 D                 PI                                     
0025.00 P                 E 
【 コンパイル 】

コンパイルは先に説明したように CRTWEBMOD という名前のモジュール作成のための
コマンドを使って次のように行う。

CRTWEBMOD QTEMP/WEB001 SRCFILE(PGMRLIB/QRPGLESRC) AUT(*ALL)

ビルドは CRTPGM コマンドを使ってビルドするがメイン・モジュールには
ASNET.COM/MAIN というモジュールを指定する。

CRTPGM CGIBIN/WXEB001 MODULE(ASNET.COM/MAIN QTEMP/WEB001) ACTGRP(*NEW) AUT(*ALL)
【 実行 】

ブラウザの URL 欄に http://(IPアドレス)/cgi-bin/WEB001.PGM と打鍵して
Enterキーを押すだけで次のように実行結果を得ることができる。

【 まとめ 】

RPG# はとてもシンプルであり、簡単である。
HTML に span タグを定義しておいて RPG# では READ/WRITE だけの入出力であり、
CRTWEMOD + CRTPGM だけでコンパイルして実行することができる。

シンプルであるということは複雑な大規模開発にも容易に対応することができて
保守も極めて簡単で誰でもすることができる。
Web開発というと WebSphere や別の PCサーバーを用意したり特殊なスクリプト言語を
学習したり講習会に出席したりするという難解な製品が多く、ユーザーもまた
Web開発は大変だというイメージが定着させられている。
Web開発といってもインターフェースが HTML に代わるだけだというシンプルな
発想が RPG# である。
肩に力を入れる必要はないし、なぜ他社製品がそのように回りくどい手法を
IBM ユーザーに薦めるのか不明である。
肩の力を抜いて普通に Web開発するのが RPG# である。