2015.05.27
Jon Paris 著

10進数データ・エラーの死!

注: この記事に記載のコードはここからダウンロードできます。

いろいろな場面で我々は 10 進数データ・エラーに遭遇してきました。 それらが最も厄介な点は、エラーを検出した時点でリカバリーができなくなっているということです。もっと正確に言えば、実質的にリカバリーができないということです。しかしながら、データ構造入出力の利点の 1 つとして、10 進数データ・エラーを回避できることができるのです。本稿では、それがどのように、またなぜ機能するかをお見せします。

このヒントに関連するコード・パッケージには、異なるシナリオをデモンストレーションする 3 つのテスト・プログラムが入っています。最初は、防御がない単刀直入な RPG プログラムです。このプログラムは、ファイルをループで読み取り、10 進数データ・エラーに遭遇します。2 つ目は、 DS I/O の基本的な使用を示すためのものです。それでもエラーはありますが、微妙に異なっています。3 つ目のプログラムは、そうしたエラーに対して完全に防御するようプログラム拡張する方法をデモンストレーションしています。お使いのシステムにソース・コードをインストールする方法については、Readme.txt ファイルをご覧ください。

10 進数データ・エラーの処理の難しさに加えられる要因の 1 つは、エラーが READ 命令または CHAIN 命令で発生する可能性があり、どのフィールドにエラーがあるか正確に判断するのが難しくなっているという点です。これは、データをバッファーから内部変数に移動している際に、システムがエラーを検出するために発生します。DS I/O を使用する場合、レコード全体がまるで大きな文字フィールドであるかのように移動されます。言い換えれば、数値データは区別されないということです。数値フィールドが区別されないので、エラーを起こすことはあり得ません。3 つのプログラムの違いがわかるよう、それぞれの実行プロセスを見てゆきましょう。

まず、プログラム DATAERRS1 の該当部分です。

技術情報019

このプログラムを実行すると、2 番目のレコードを読み取る際に、エラーを受信します。F1 を使用してエラーの実際の詳細を確認すると、READ に関連付けられたコンパイラーが生成したラインの 1 つで、エラーが発生したことがわかります。デバッグでプログラムを実行すると、これはより明らかになります。プログラムを実行するよう指示する (オプション G) と、同様のエラーが 3 番目のレコードで発生するのがわかります。両方の場合で、どのフィールドでエラーがあるのか判断するのは問題があり、唯一有効なオプションはプログラムをキャンセルすることです。

では、プログラム DATAERRS2 を実行します。

技術情報020

唯一の違いは、プログラムが DS を使用してレコードを受信していることです。10 進数データ・エラーがまだ発生していますが、今回は READ ではなく、total に入力値を追加しようとしているときに発生しているのがわかります。少なくとも、これは、エラーが発生しているフィールドを簡単に判断できるというメリットがあります。同様に、再度 G オプションを指定すると、次のエラーは、 %DATE BIF を使用してデータを変換しようとしたときに発生します。データ処理に慣れている読者の方々なら、READ でエラーを回避したため、TEST 命令コードを使用して、変換と結果を条件付けることで、あらゆる変換エラーに対して防御できたであろうことがわかるでしょう。実際、3 つ目のプログラムで日付によってその方法を使用します。

3 つ目のプログラムについて、エラーを制御できるよう行われたソース・コードの変更について見てみましょう。

技術情報021

(A) は、レコードの受信に使用されたデータ構造の定義です。この DS を READ で使用しているため、入力フィールドが必要であることを指定する必要があります。レコードの入力および出力のレイアウトは、レコードの読み取り時、または書き込み時でも同じであると考える傾向があるため、これにそれほど多くの意味があるとは思えません。しかし RPG の観点からは違いがある場合があり、具体的にする必要があります。

(B) では、MONITOR 命令コードを導入しました。これは、amount フィールドの 10 進数データ・エラーを捕捉しようとしているときに使用する方法です。モニター・ブロックを開始する場合、コンパイラーに MONITOR自体と、この例だけですが、最初の ON-ERROR 節の間にある命令で発生するあらゆるエラーを捕捉したいと命令しています。この場合、これを単一の addition 命令に制限しましたが、望めば、そうしたモニター・ブロックで、プログラム全体を囲むこともできます。

2 番目のレコードを処理しているときに 10 進数データ・エラーが発生する場合、MONITOR により、コンパイラーは ON-ERROR (C) に制御を渡します。この場合、汎用 ON-ERROR (具体的なエラー条件は参照しません) を使用したため、addition 命令中に発生するあらゆるエラーを捕捉します。例えば、数値オーバーフローが発生していたら、同じ応答を起動していたでしょう。発生する可能性があるさまざまな種類のエラーを区別する場合、何らかの特定の ON-ERROR が処理する特定の状況コードを指定する必要があります。ON-ERROR 直後のコードは、エラーが検出されるときに実行されます。このテスト・プログラムでおわかりのように、エラーは単に報告され、デフォルト値のゼロで無効な入力と置き換えています。

無効な日付の処理に、同じアプローチを使用できたでしょう。代わりに私は (D) にある TEST 命令コードを使用することにしました。この命令コードに慣れていない読者の方々には、YMD 形式の日付フィールドとして有効でない NumDate の値に遭遇した場合、%Error が設定されます。(E) で示すように、これは以降の日付処理を条件付けるために使用されます。
なぜ MONITOR ではなく TEST を使用するのでしょうか。私には、それは単にそのエラーが、どの程度発生しやすいかということに過ぎません。日付のエラーが頻繁に発生すると予測する場合、TEST を使用するのが最も意味があります。一方、エラーが極めて稀な場合、MONITOR のアプローチを使用します。

私にとって MONITOR の良い点の 1 つは、見当がつく命令のシーケンスを指定でき、潜在的なエラーを予測しなければならないことで中断されないことです。言い換えれば、あるプログラムで MONITOR ブロックに遭遇した場合、プログラマーが通常実施するよう期待されている一連の対処を即座に知るということです。ON-ERROR ブロックは、予測された潜在的なエラーおよび行われた是正措置を特定します。多くの場合、多数のコメントが与えてくれるよりも、該当のプログラマーが考えていることをより深く探ることができます。当然、他人の思考プロセスを探るとゾッとすることがありますが。

まとめると、DS I/O には多数のメリットがあります。だからといって、それがあなたのプログラムをより堅固にするわけではありません。プログラム記述の時代から発生したレガシーにいまだ奮闘し、10 進数エラーを日々処理している読者の方々には、データ構造入出力はお使いのツール・ボックスへの非常に価値ある追加機能と言えます。

Jon Paris: System i プラットフォームのプログラミングに関して世界で最も知識が豊富なエキスパートの 1 人。ずいぶん前からParisはSystem/38の経験を積んでいましたが、1987 年、IBM の Toronto ソフトウェア・ラボで System/38 および System/36 の COBOL コンパイラーに取り組みました。1988 年には、オリジナル AS/400s の COBOL/400 コンパイラーの作成にも取り組んでおり、RPG IV および CODE/400 開発ツールの主要開発者の1 人でした。1998 年に IBM を去り、自身の教育訓練会社を立ち上げ、今日まで System i プログラミングのエキスパートでもある妻の Susan Gantner とともに仕事をしています。Paris と Gantner は Paul Tuohy および Skip Marchesani とともに System i Developer の共同創立者であり、新しい RPG & DB2 Summit カンファレンスを主催しています。 Jon へのご質問は IT Jungle Contact ページから Ted Holt へお送りください。

完全にするために、以下のようなプリンター・ファイル定義があります。

ページトップ

ボタン