すべてのユーザーに有用なIBM 7.1 ILE RPG機能拡張
新しいデータ構造体機能、プロシージャー定義オプションなど
7.1 の ILE RPG 機能拡張はあらゆるユーザーに大切なものを提供してくれます。手馴れた作業をさらに簡単にしてくれるような機能拡張もあれば、アプリケーションの設計方法を変えてくれるような機能拡張もあります。
配列の機能拡張
データ構造体の検索とソート 。
RPG でデータ構造体配列を定義できるようになった i 5.2 以来、我々が待ち望んでいたものがこれです。サブフィールドの 1 つをキーとして使用して、データ構造体配列を検索し、ソートできるようになりました。構文は array(*).key です。ここで、なぜアスタリスクが必要なのかと思うでしょう。式には複数のデータ構造体配列が存在する可能性があるため、アスタリスク (*) を使用してどの配列をソートまたは検索しているのか示します。
例えば、petInfo という配列があり、petInfo 配列に species、age、name、numFoods というサブフィールドがあり foods という配列サブフィールドがあるとしましょう。foods 配列自体は、type および amount というサブフィールドを持つデータ構造体です。
以下のように種が「fish」という配列エレメントを検索します。配列は「petInfo(*)」で、キーは「species」です。
elem = %LOOKUP('fish'
: petInfo(*).species
: 1
: numPets);
以下のように「kibble」というタイプが petInfo(3) の foods サブフィールドにある配列エレメントを検索します。配列は「petInfo(e).foods(*)」で、キーは「type」です。
elem = %LOOKUP('kibble'
: petInfo(3).foods(*).type
: 1
: petInfo(e).numFoods);
ペットの種でこの配列をソートする場合、配列は「petInfo(*)」で、キーは「.species」です。
SORTA petInfo(*).species
最初のペットの foods の配列を食物のタイプでソートする場合、配列は「petInfo(1).foods(*)」で、キーは「.type」です。
SORTA petInfo(1).foods(*).type
「これらの SORTA ステートメントは %SUBARR を使用しているはず」と考えていたら、自分を褒めてあげてください。その通りです。しかし、最初の例は簡単にしたいので、上記の 2 つの SORTA 例は正確には次のようになるはずです。
SORTA %subarr(petInfo(*).species
: 1
: numPets);
SORTA %subarr(petInfo(1).foods(*).type
: 1
: petInfo(1).numFoods);
データ構造体全体をソートする場合、各ペットごとに foods 配列をソートし、pet 列全体をソートします。foods 配列を量、メインの pet 配列を年齢でソートする場合は、以下のようになります。
for i = 1 to numPets;
SORTA %subarr(petInfo(i).foods(*).amount
: 1
: petInfo(i).numFoods);
endfor;
SORTA %subarr(petInfo(*).age
: 1
: numPets);
同じ配列を昇順と降順にソートする。
petInfo 配列を最も年齢が高い動物から降順にソートする場合はどうでしょうか。これは配列のさらに別の機能拡張を思い出させてくれます。同じ配列を昇順または降順にソートする機能です。今までは、ASCEND サブフィールドと DESCEND サブフィールドを使用して、昇順または降順にソートするよう配列を定義することはできましたが、SORTA の (A) エクステンダーまたは (D) エクステンダーを使用してソート順を制御することができます。この SORTA 命令は、最も年齢の高いペットから年齢の降順にエレメントをソートします。
SORTA(D) %subarr(petInfo(*).age
: 1
: numPets);
(A) エクステンダーと (D) エクステンダーも通常の配列に使用できます。例えば、会議の日程の配列があり、直近の会議からそれらを降順でソートする場合、以下のようになります。
SORTA(D) %subarr(meetings
: 1
: numMeetings);
ところが、パフォーマンスと便利さは両立しないものです。ASCEND キーワードか DESCEND キーワードをコーティングしていると、(A) エクステンダーまたは (D) エクステンダーを使用してソート順を変更することはできません。RPG では、昇順の配列を降順、またはその逆にソートすることはできません。配列に ASCEND キーワードまたは DESCEND キーワードをコーティングするメリットは 2 つあります。1) バイナリー・サーチはパフォーマンス面で利点があること、そして 2) 条件未満または条件以上の検索ができることです。昇順と降順両方で配列をソートして、さらに配列を検索したい場合は、どちらがより重要かを決める必要があります。条件以上または条件未満で配列を検索する場合は、ASCEND キーワードか DESCEND キーワードをコーディングする必要があります。バイナリー・サーチのパフォーマンス上の利点だけが必要な場合、(A) エクステンダーと (D) エクステンダーを使用してコーディングした場合の簡単さを犠牲にしても、実際のパフォーマンス・メリットが大きいかどうかを判断しなくてはなりません。バイナリー・サーチは逐次探索のわずか 10 分の 1 の時間で済むのですが、逐次探索に必要な時間がマイクロ秒単位だった場合、25 マイクロ秒と 2.5 マイクロ秒では、ご使用のアプリケーションにとってはさほど大きな違いはないのではないかと思います。
プロシージャー定義の機能拡張
オプションのプロトタイプ 。別の RPG モジュールから呼び出されていない場合、プロトタイプをコーディングする必要はなくなります。モジュールにローカルな (つまり、モジュールからエクスポートされていない) プロシージャーがある場合、プロトタイプをコーディングする必要はありません。コンパイラーはプロシージャー・インターフェース (PI) から内部プロトタイプを生成することができます。あるいは、PI がない場合は、コンパイラーは戻り値とパラメーターがない内部プロトタイプを生成できます。
また、別の RPG プログラムで呼び出されることがないプログラムを定義している場合は、プロトタイプはオプションです。例として、コマンドのコマンド処理プログラム (CPP)、WRKREGINF で有効にした出口点として呼び出されるプログラムや、アプリケーションのメイン CL プログラムで呼び出されるサブプログラムがあります。
プロトタイプをコーディングしない場合は、PR ではなく PI で EXTPROC キーワードまたは EXTPGM キーワードをコーディングできます。
コンパイラーでは、プロトタイプをコーディングする必要があるケースを検出できないため、いつプロトタイプが必要かを知るのはあなた次第です。幸い、ルールはシンプルです。どのプログラムまたはプロシージャーにもコンパイラーで明示的にコーディングされた、または生成されたプロトタイプが 1 つだけ必要です。誤ってモジュール A でプロトタイプのないプロシージャーをコーディングし、そのモジュールを (モジュール B 内ではプロトタイプがコーディングしている) モジュール B から呼び出すと、そのプロシージャーにプロトタイプが 2 つ存在することになります。最初のプロトタイプはコンパイラーで生成され、2 番目のプロトタイプはモジュール B でコーディングしたプロトタイプです。エラーを修正するには、いつもやっているようにプロトタイプを /COPY ファイルでコーディングし、定義しているモジュール A と呼び出しているモジュール B にプロトタイプをコピーします。こうすれば、コンパイラーは同じプロトタイプを使用して、プロシージャーとその呼び出し元がすべて正しいことを確認できます。
別の方法でルールを考えると次のようになります。複数の RPG モジュールが、定義している、または呼び出しているいずれかのプログラムまたはプロシージャーを参照している場合、/COPY ファイルでプロトタイプをコーディングし、それをすべての該当モジュールにコピーする必要があります。
A、C、または G を処理できるストリング・プロシージャーを作成する 。
このリリースでは、RPG は、英数字、UCS-2、グラフィック変数が相互作用する方法に関するルールは引き続き緩和されています。この作業は 6.1 で開始されましたが、5.3 と 5.4 については PTF で変更を入手することもできます。6.1 の変更では、明示的な変換組み込み関数がなくても、3 種類のストリングを割り当て、比較することができるようになりました。例えば、データベース・フィールド CUSTNAME のタイプが UCS-2、内部フィールド DEFAULT_NAME のタイプが英数字とします。5.3 に機能拡張を行う前に「if custname <> default_name」を使用してこれら 2 つのフィールドを比較しようとすると、RPG コンパイラーは、フィールドのタイプが違うと文句を言うでしょう。「if custname <> %ucs2(default_name)」とステートメントを指定して、%UCS2 組み込み関数を使用して DEFAULT_NAME を UCS2 に変換しなければならなかったでしょう。
CUSTNAME が以前にファイルで英数字フィールドであり、各国間データを処理するためそれを UCS-2 に変換していた場合、異なるタイプが共に使用されていた場合は必ず %UCS2、%CHAR、または %GRAPH 組み込み関数を追加して、RPG プログラムによるコンパイルに必要なすべての変更を行うのは、極めて難しかったことでしょう。
6.1 の機能拡張では、RPG コンパイラーは暗黙的に必要な変換を行うことができるため、データベース・フィールドのタイプが変更されたことに伴う RPG プログラムのコード変更の数は著しく少なくなります。
バージョン 7.1 では、パラメーターを渡すルールが緩和されています。3 種類のストリングのいずれかの VALUE キーワードまたは CONST キーワードでパラメーターを定義させるようパラメーターがプロトタイプ化されている場合、RPG コンパイラーでは、渡されたパラメーターは 3 種類のいずれかのストリングになることができます。データベース・フィールドのタイプを変更する場合に必要な変更をさらに簡単にする他に、3 種類のいずれのストリングも処理できる単一ストリング・プロシージャーを作成するチャンスが与えられます。
考え方としては、CONST UCS-2 パラメーターを使用して、UCS-2 戻り値を戻すプロシージャーを作成するということです。プロシージャーは UCS-2 でだけ動作しますが、どのストリング・タイプも渡すことができ、戻り値をどのストリング・タイプにも割り当てることができます。
例えば、テキストをセンタリングするプロシージャーがある場合、次のようにプロトタイプを定義します。
D center pr 200c varying
D text 200c const varying
次のように呼び出します。
D alpha_title s 100a
D ucs2_title s 100c
CCSID について、いくつかポイントを述べます。CCSID(*CHAR:*JOBRUN) キーワードは常に H 仕様でコーディングする必要がありますが、英数字と UCS-2 の間で変換している場合これは特に重要な点です。(Java メソッド間の呼び出しについて変換を行っている場合も重要です) 英数字フィールドの CCSID の RPG デフォルト値は、ジョブ CCSID に関連した混合バイト CCSID です。例えば、ジョブ CCSID が 37 の場合、RPG では英数字フィールドに 937 という CCSID があると想定します。H 仕様で CCSID(*CHAR:*JOBRUN) とコーディングすると、英数字データは実際のジョブ CCSID である 37 に存在すると想定されます。ジョブ CCSID が 65535 の場合、RPG ではジョブに関連付けられた「default job CCSID」が使用されます。
アプリケーションでグラフィック・フィールドを使用する場合、暗黙的変換を利用できるよう、CCSID(*GRAPH) H 仕様キーワードをコーディングする必要があります。CCSID(*GRAPH) キーワードのデフォルト値は CCSID(*GRAPH:*IGNORE) で、暗黙的変換を行うことはできません。
さらに多くの暗黙的変換を行う必要がある 。
RPG では、異なるストリング・タイプを共に使用する場合は %UCS2、%CHAR、または %GRAPH を使用した明示的変換が依然として必要な領域があります。例えば、異なるタイプ間の連結はまだ許可されておらず、複数のストリング・パラメーターを指定した組み込み関数でも、ストリング・パラメーターのタイプを同じにする必要があります。
ストリング操作プロシージャーを使いやすくする高速戻り値 。
一般的にプロシージャー型プログラミングの世界では、大きな戻り値は好ましくないと考えられています。大きな値を戻す場合のパフォーマンスは著しく低下することがあります。それは、多数のプログラマーがその代わりにパラメーターを通して戻り値を操作しなければならないと考えるほどです。呼び出しパフォーマンスを最適化する必要がある呼び出し元にとって、2 つのバージョンのプロシージャー (戻り値があるプロシージャーとパラメーターを使用するプロシージャー) を提供しているプログラムもあります。
パラメーターを使用するより、戻り値を使用するほうがはるかに便利です。パラメーターでは、呼び出し元はそのパラメーターの正しいタイプの一次変数を定義する必要があります。例えば、プロシージャー getFileData が 100,000 バイトの可変長値を戻しますが、パフォーマンス上の理由で、戻り値が参照渡しされたパラメーターを通して操作されるとします。その呼び出しをコーディングしている RPGプログラマーは、1,000 バイトの固定長変数で結果を保持していますが、プログラマーは、呼び出しを次へ渡し、呼び出し結果を保持することになっている 1,000 バイト変数に値をコピーするため、100,000 バイト可変長一時変数を定義しなければなりません。
getFileData(temp : other parms);
data = temp;
プログラマーが単純にプロシージャーを呼び出して、戻り値を目的の変数に割り当てる方がずっと便利でしょう。
data = getFileData(other parms);しかし、この場合プロシージャーが 1,000 バイト以下しか戻していない場合、プロトタイプ化された 100,004 バイトの戻り値全体を戻すと、かなり速度が遅くなる可能性があります。
ここで、パラメーターのパフォーマンスと値を戻すことの利便性を兼ね備える方法があります。プロトタイプと値を戻すプロシージャーの PI で RTNPARM キーワードを指定すると、コンパイラーは、戻り値を操作する別のパラメーターを指定するようプロシージャーを内部的に定義します。非常に大きな可変長ストリング変数を戻すようプロトタイプ化されているものの、実際には極めて小さな値を戻す場合が多いプロシージャーについては、RTNPARM を指定した場合のパフォーマンス上のメリットは目を見張るものがあります。
他のプログラミング言語が RTNPARM で定義された RPG プロシージャーと相互に作用している場合、「戻り値」を第 1 パラメーターにコーディングする必要があります。例えば、プロシージャーで 10A という戻り値と 5A というパラメーターが RTNPARM で定義されており、CL からプロシージャーを呼び出す場合、*CHAR 10 と *CHAR 5 という 2 つのパラメーターで CL を定義しなければなりません。
見方を変えると、RTNPARM を使用するという興味深い方法に行き着きます。ある CL プロシージャーで 2 つのパラメーター *CHAR 10 と *CHAR 5 を指定している場合、戻り値が 10A、パラメーターが 5A というプロシージャーとしてプロトタイプ化し、CL プロシージャーが 10A 値を戻しているかのように呼び出すことができます。私は、これが良いアイデアなのかどうか決めかねています。わかりにくいかもしれませんが、非常に便利でもあります。
パラメーターの序数をソフトコーディングする 。
RPG プログラマーがパラメーター・リストでパラメーターの序数を知らなければならないシナリオは 2 つ存在します。プロシージャーにオプション・パラメーターがあり、それらのオプション・パラメーターのいずれか 1 つが渡されたかどうか知りたい場合、プログラマーは %PARMS をパラメーター番号と比較します。オペレーショナル・ディスクリプターを受信するよう OPDESC キーワードを指定してプロシージャーをプロトタイプ化すると、プロシージャーはパラメーター番号をパラメーターの情報を戻す CEEDOD 関数に渡す必要があります。
これまで RPG プログラマーは、このパラメーター番号をハードコーディングしなければなりませんでした。何かをハードコーディングすると、エラーが発生しやすくなり、保守しにくいコードになることがあります。現在、RPG プログラマーは、新しい %PARMNUM 組み込み関数を使用してパラメーター番号をソフトコーディングできます。%PARMNUM のパラメーターは、そのパラメーターの名前です。「city」パラメーターが渡されたかどうか確認するため、%PARMS を %PARMNUM(city) と比較します。
RTNPARM では極めて重要な %PARMNUM の使用。
RTNPARM キーワードをプロシージャーにコーディングしてある場合、プロシージャーには非表示のパラメーターが別に存在し、そのパラメーターは第 1 パラメーターです。つまり、%PARMS はあなたの予想より 1 つ上位にあり、各パラメーターの序数は予想の数より 1 つ上にあります。例えば、CITY と PROVINCE という 2 つのパラメーターを指定したプロシージャーがあり、RTNPARM キーワードを指定している場合、CITY が第 2 パラメーターで、 PROVINCE が第 1 パラメーターです。しかし %PARMNUM(CITY) と %PARMNUM(PROVINCE) を使用する限り、心配には及びません。%PARMNUM(CITY) が 2 を戻すため、%PARMS との比較結果は正しくなります。CEEDOD への呼び出しは CITY パラメーターの情報を正しく戻します。
データ構造体の ALIAS 名のサポート
別名 (代替名とも呼ばれる) をデータベース・ファイルに指定してある場合、RPG データ構造体でそれらの名前を使用できるようになりました。ALIAS キーワードを指定した外部記述データ構造体を定義する、または ALIAS キーワードで定義されたファイルの LIKEREC データ構造体を定義する場合、RPG コンパイラーはサブフィールドの別名を使用します。
ファイルに ALIAS キーワードをコーディングできると喜び勇む前に、ファイルの ALIAS サポートは思うほど良くはないことを頭に入れておく必要があります。I 仕様および O 仕様が生成されていないファイル、つまりサブプロシージャー内で定義されたローカル・ファイル、または QUALIFIED キーワードで定義されたファイルの ALIAS しかコーディングできないのです。
つまり、単純にファイルを定義し、別名をスタンドアロン・フィールドとしてプログラムに組み込むわけにはいかないということです。別名はデータ構造体にしか見られません。しかし、入出力操作の結果フィールドでデータ構造体を使用したいなら、ALIAS キーワードをファイルまたはデータ構造体で使用するときに、次のようにコーディングすることができます。
read custrec custDs;
if custDs.company_name = 'ABC Electronics';
代わりに次のようにコーディングします。
read custrec custDs;
if custDs.cmpnam = 'ABC Electronics';
その他の機能拡張
スキャンし置き換える組み込み関数。
%SCANRPL は、ストリング中の検索値のすべての検索結果を見つけ、それらを別の値に置き換えます。
例えば、こうした値を持つストリングがあるとします。
'NAME not found. Create NAME and try again.'
NAME のすべての検索結果を見つけ、それらを MYFILE と置き換えるとします。次のように %SCANRPL を使用します。
new = %scanrpl('NAME' : 'MYFILE' : string);
// 'MYFILE not found. Create MYFILE and try again.'
RPG の %XLATE 組み込み関数同様、命令のスキャン段階の開始と長さを指定できます。結果生じるストリングには、あるストリングのすべてのテキストが含まれており、開始と長さの範囲内で置き換えが行われます。例えば、開始位置を 2 に指定すると、最初の「NAME」は %SCANRPL のスキャン段階では見つからないため、置き換えられません。
new = %scanrpl('NAME' : 'MYFILE' : string : 2);
// 'NAME not found. Create MYFILE and try again.'
新しい XML-INTO オプション 。
XML-INTO には datasubf と countprefix という新しいオプションがあります。これらのオプションは、約 1 年間 PTF により 6.1 で使用可能であったため、ここではお話しませんが、XML-INTO を使用する場合には、これらのオプションがどのように役立つか調べたいとあなたが思うのは当然だ、ということだけ述べておきます。
リスト・デバッグ・ビューを暗号化する。
この新機能は、SQL プリコンパイラーを含むすべての ILE コンパイラーでサポートされています。リスト・デバッグ・ビューをコンパイルする場合、DBGENCKEY (Debug Encryption Key) パラメーターでモジュールまたはプログラムの暗号キーを指定して、リスト・ビューを暗号化するよう要求できます。例を挙げます。
CRTRPGMOD qtemp/mymod DBGENCKEY('secret')
CRTSQLRPGI qtemp/pgm DBGENCKEY('abracadabra')
STRDBG コマンドを使用する場合、コマンド上で DBGENCKEY を直接指定するか、デバッガーがキーを要求するまで待つことができます。モジュールごとに異なるキーがあったり、すべてのモジュールが同一のキーを持っている場合があります。デバッガーが、すでに提供されたキーと同じキーを持つモジュールを見つけると、そのキーを二度と要求することはありません。
ソフトウェアをあなたのお客様に送信し、お客様先でデバッグを行う場合に、この機能は非常に便利でしょう。リスト・デバッグ・ビューを暗号化するというこの新機能が登場するまでは、お客様のシステムにデバッグ可能なコードを持たせないか、お客様にすべてのコードを見せて、あなたのプログラムでデバッグを開始するかのいずれかを選択するしかありませんでした。
今は、デバッグ可能プログラムをお客様に送信し、お客様があなたのコードを参照しようとすると、キーの入力を求められるようになりました。このキーはお客様は知りません。あなたがお客様先でプログラムをデバッグしている場合は、キーを知っているためリスト・ビューを表示できるようになります。
テラスペース・メモリーの割り当て。
従来、RPG はそのメモリー管理命令 %ALLOC、%REALLOC、および DEALLOC (ALLOC および REALLOC 命令コードも) に対して、「単一レベル・ストレージ」を採用していました。単一レベル・ストレージは 16MB のチャンクで提供されているため、RPG の命令を使用して割り当てることができる最大サイズは 16MB でした。H 仕様 ALLOC(*TERASPACE) キーワードを使用することで、RPG がテラスペースのストレージを使ってメモリー管理命令を実行できるようになりました。最大テラスペース割り当てサイズは 4 テラバイトです。
テラスペース・ストレージ・モデルで実行する。
RPG をテラスペース・ストレージ・モデルで実行できるようになりました。コマンドまたは H 仕様で STGMDL (*TERASPACE) を指定できます。また、CRTBNDRPG、CRTPGM、または CRTSRVPGM コマンドで STGMDL (*INHERIT) を指定して、*CALLER プログラムまたはサービス・プログラムにその呼び出し元のストレージ・モデルを継承するよう要求することもできます。
ほとんどの RPG プログラマーは、テラスペース・ストレージ・モデルの必要性に遭遇したことはありませんでしたが、遭遇したことのあるプログラマーにとって、テラスペースで実行できないのは欲求不満の種でした。
テラスペース・ストレージ・モデルで実行する理由の 1 つは、自動ストレージの制限がはるかに高く設定されているためです。単一レベル・ストレージ・モデルでは、単一プロシージャーの自動ストレージは最大で 16MB しかありません。サブプロシージャーに 16MB ストリングを定義するだけで、その制限に達してしまいます。さらにストレスが溜まるのは、呼び出しスタック上のすべてのプロシージャーの自動スタックが 16MB 制限であるということです。例えば、10MB の自動ストレージが必要なプロシージャーがあり、10MB の自動ストレージが必要な別のプロシージャーを呼び出すと、スタックの総自動ストレージ量は 20MB となり、呼び出しは失敗します。16MB 制限を超えているためです。テラスペースでは、制限は桁違いに高く設定されています。
テラスペース・ストレージ・モデルで実行するもう 1 つの理由は、テラスペース・ストレージ・モデルで実行するサービス・プログラムにリンクできるということです。C および C++ は、テラスペース・ストレージ・モデルで実行する場合に高速 8 バイト・ポインターを使用できるため、テラスペース・バージョンの関数は単一レベル・バージョンより著しく速く動作できます。
RPG はまだ 8 バイト・ポインターを使用する機能がないため、それがリンクする任意の C または C++ サービス・プログラムには、それらのパラメーターに 16 バイト・ポインターがなければなりませんが、関数内で 8 バイト・ポインターを使用することができます。
テラスペースに関する制限は、任意の 1 つの活動化グループがテラスペースまたは単一レベル・ストレージ・モデルいずれかで実行されるプログラムを複数持つことができるということです。単一レベル・ストレージ・モジュール・プログラム SLSPGM とテラスペース・ストレージ・モデル・プログラム TERAPGM 両方が活動化グループ MYACTGRP で実行するよう定義され、SLSPGM が最初に呼び出された場合、活動化グループは単一レベル・ストレージ・プログラムに制限されます。SLSPGM が TERAPGM を呼び出そうとすると、呼び出しは失敗します。同様に、TERAPGM が最初に呼び出され、SLSPGM を呼び出そうとすると、呼び出しは失敗します。活動化グループはテラスペース活動化グループとして作成されたためです。
ストレージ・モデルに関連して 1 つ分かりにくい変更があるのですが、それは CRTBNDRPG コマンドの ACTGRP パラメーターのデフォルト値が以前の QILE ではなく *STGMDL であるということです。CRTBNDCL は複数のリリースでこのように動作しました。ストレージ・モデルが *TERASPACE の場合、活動化グループのデフォルト値は QILETS になります。ストレージ・モデルが *SNGLVL または *INHERIT の場合、活動化グループのデフォルト値は現在のように QILE になります。
ストレージ・モデルの推奨事項 。
STGMDL(*INHERIT) で自分のモジュールを作成します。それは 7.1 のデフォルトで、モジュールをどのタイプのプログラムまたはサービス・プログラムにもバインドできるようになります。
STGMDL(*INHERIT) で自分の*CALLER サービス・プログラムを作成します。これで、サービス・プログラムを、どのタイプのプログラムまたはサービス・プログラムにもバインドできるようになります。
あなたのプログラムにどのストレージ・モデルを採用するかについては、推奨することは何もありません。それは、活動化グループについて判断する場合と同様に、アプリケーション固有の判断だからです。『ILE RPG Programmer's Guide』に、ストレージ・モデルの選択方法に関する情報が多少記載されており、『ILE Concepts』にはストレージ・モデルに関する情報が多数記載されています。
アプリケーションのストレージ・モデルに変更を加える前に、活動化グループについて完全に理解することを強くお勧めします。現在、同じ名前の活動化グループですべてのアプリケーションを実行していて、一部のアプリケーションをテラスペース・ストレージ・モデルで実行しようとした場合、テラスペース・プログラムには異なる活動化グループを使用する必要があります。2 種類の活動化グループでアプリケーションを実行すると、オーバーライドとコミットメント制御の範囲に関する問題が発生するおそれがあります。
Rational Open Access: RPG エディション
最後に Open Access について簡単に述べておきたいと思います。これだけで 1 つの記事にできるぐらい大きなトピックです。
Open Access の目的は、RPG プログラマーに RPG のよく知られている入出力操作を、プログラムやプロシージャーのインターフェースとして利用させることであり、それは、他の方法ではRPGが利用できないデバイスやリソースにアクセス可能にします。
Open Access ファイルでは、システムのデータ管理機能を使用するのではなく、ユーザー提供のプログラムまたはプロシージャー (「ハンドラー」とも呼ばれる) を使用して、その入出力操作を処理します。
Open Access の概念は RPG の SPECIAL ファイルの概念と似ています。SPECIAL ファイルもまた、ユーザー提供のプログラムを使用して入出力操作を処理しますが、SPECIAL ファイル・サポートは著しく制限されており、どちらかと言えば原始的です。SPECIAL ファイルは、順次 DISK ファイルに使用できる命令のみ使用でき、処理プログラムは操作に関する情報はほとんど受信せず、OPEN には 'O'、READ には 'R' などと単一文字しか受け取りません。処理プログラムは、 RPG プログラムにフィードバックをほとんど提供することができません。
対照的に、任意の RPG デバイス・タイプ (DISK、PRINTER、または WORKSTN) を Open Access ファイルとして定義することができます。Open Access ハンドラーは入出力操作について知る必要があるすべての情報を受信し、Open Access ファイルが通常のデータ管理ファイルであるかのように、RPG プログラムがシームレスに実行されるよう、必要なフィードバックをすべて提供します。
Open Access ファイルを定義する場合、RPG プログラマーは F 仕様で HANDLER キーワードを指定し、ハンドラーを見つけます。HANDLER キーワードのパラメーターは 'MYLIB/MYSRVPGM(myproc)' または 'MYSRVPGM(myproc)' の形式で、サービス・プログラムのプロシージャーを特定できます。'MYLIB/MYPGM' または 'MYPGM' の形式でプログラムを特定できます。HANDLER パラメーターは、ハンドラーの場所がわかっている場合は文字リテラルで、実行時に決定する場合は文字変数になることができます。また HANDLER パラメーターは、プロシージャー・ポインターまたはバインドされたプロシージャーのプロトタイプの名前の場合があります。
HANDLER キーワード以外は、RPG プログラムは通常通りコーディングされます。Open Access ファイルが WORKSTN ファイルの場合、RPG プログラマーは通常と同じように EXFMT または READC をコーディングすることができます。
Open Access の本当の魔法は入出力ハンドラーからもたらされます。ハンドラーは入出力データを受け取り、それを使用して任意のデバイスまたはリソースと相互作用を行います。
簡単な例を挙げると、ハンドラーを作成して IFS ファイルからの行を読み取ることができます。OPEN 命令については、ハンドラーは IFS ファイルを開きます。READ 命令については、ハンドラーは改行文字が見つかるまで IFS ファイルから文字を読み取り、入力バッファーにその行を戻します。CLOSE 命令については、ハンドラーは IFS ファイルを閉じます。RPG プログラムは単純にファイルの終わりになるまで、ファイルを読み取ります。RPG プログラマーの利便性を考え、ハンドラーのプロバイダーは大規模な可変長フィールドを持つデータベース・ファイルを定義するかもしれません。RPG プログラマーはそのファイルを使用して、Open Access ファイルを外部記述することもできます。ハンドラーをコーディングするプログラマーは、RPG プログラムとハンドラーがバッファーの性質について合意するよう、同じファイルから外部記述データ構造体を定義することもできます。これは、IFS ファイルに慣れた RPG プログラマーならハンドラーを作成できるほど簡単な例だと思います。
より複雑な例としては、すべての WORKSTN ファイルが Open Access WORKSTN ファイルになるよう変更されているアプリケーションがあります。すべての WORKSTN ファイルが Web ブラウザーで相互作用するには、同じハンドラーを使用します。このタイプのハンドラーは極めて複雑で、通常の RPG プログラマーでは作成できなさそうです。というより、このタイプのハンドラーは市販されるでしょう。実際、一部の企業では、まさに私がお話した内容を実行する驚くべき Open Access ハンドラーをすでに宣伝しています。
Open Access ファイルを使用するには、製品 5733-OAR のライセンスが必要です。
RPG コンパイラーとランタイムの PTF を使用して Open Access を 6.1 上でも使用できます。5733-OAR は 6.1 または 7.1 のいずれかにインストールできます。
7.1 が楽しみですか?
RPG 機能拡張の少なくとも1 つは、あなたに 7.1 マシンにアクセスできる日がくることを期待させたことと思います。すべての新リリースについては、これらの新しい RPG 機能拡張なしでやっていけるとはとても思えません。