throw()コマンドを実装し、Try(Expression)キーワードの導入に続き、4Dのエラー処理システムの次の進化として、Try-Catchコードブロックを導入しました!
4D 20 R5 からは、新しいTry、Catch、End tryキーワードを活用することで、エラー処理能力を強化することができます。
これらの新しいキーワードの実用的なアプリケーションを説明するために、請求書行を持つ請求書を作成する例を見てみましょう。この例では、これらの新しいキーワードの利点をダイレクトに強調します:
Function createInvoice($customer : cs.customerEntity; $items : Collection; $invoiceRef : Text) : cs.invoiceEntity
var $newInvoice : cs.invoiceEntity
var $newInvoiceLine : cs.invoiceLineEntity
var $item : Object
ds.startTransaction()
Try
$newInvoice:=This.new()
$newInvoice.customer:=$customer
$newInvoice.invoiceRef:=$invoiceRef
For each ($item; $items)
$newInvoiceLine:=ds.invoiceLine.new()
$newInvoiceLine.item:=$item.item
$newInvoiceLine.amount:=$item.amount
$newInvoiceLine.invoice:=$newInvoice
$newInvoiceLine.save()
End for each
$newInvoice.save()
ds.validateTransaction()
Catch
ds.cancelTransaction()
$newInvoice:=Null
ds.logErrors({\
message: "Invoice creation failed";\
errors: Last errors;\
customer: $customer.ID;\
invoiceRef: $invoiceRef;\
items: $items\
})
End try
return $newInvoice
この例の作成プロセスでは、開発者はエラーが具体的にどこで発生したかという正確な場所については気にしていません。単にエラーを記録し、無効なデータを作成しないようにしているだけです。
この関数は、顧客エンティティ、商品のコレクション、請求書の参照を引数として受け取ります。
トランザクションは、作成プロセス中のデータの整合性を保護するために、最初に開始されます。
すべての作成コードはTryコードブロックの中で保護されます。
請求書と請求書行がエラーなく作成されると、トランザクションはTryコードブロックの最後で検証されます。
しかし、エラーが発生すると、Tryコードブロック内でのエラー発生箇所に関わらず、Catchコードブロックが実行されます。そしてCatchコードブロックではトランザクションがキャンセルされ、カスタム関数によってエラーが記録されます。
Try-Catch コードブロックの詳細
コードブロックの実行で4Dエラーダイアログボックスが表示されないように保護するためには、TryとEnd tryキーワードでコードブロックを囲むことでそれを保護できます。
エラー処理は必須というわけではありませんが、あると良いでしょう。そこで、End tryキーワードの前にCatchキーワードを挿入することで、CatchキーワードとEnd tryキーワードの間に、複数行にエラー処理コードを書くことができるようになりました。このやり方は他の言語でも一般的なもので、長いメソッドや関数を読みやすくします!
Tryコードブロックの実行中にエラーが発生しなかった場合、コードはCatchコードブロック(もしあれば)をスキップし、End tryキーワードの後のコードの実行を続けます。
しかし、Tryコードブロックのどこかの行でエラーが発生した場合、その後の実行は以下のようになります:
- カレントエラー処理メソッドがインストールされていても、そのエラー処理メソッドは呼び出されません。
- 4Dのエラーダイアログボックスは表示されません。
- エラーは現在のエラースタックに追加されます。
- コードの実行は直ちにCatchコードブロックに切り替わります。Catchキーワードがない場合、コードの実行は対応するEnd tryキーワードの直後へとスキップされます。
現在の実行コンテキストにエラー処理メソッドが定義されておらず、Catchコード・ブロックの実行中にエラーが発生した場合には、4Dのエラーダイアログボックスが表示されるという点に注意してください。しかし、Try(式)または入れ子になったTry–Catchコードブロックを使用して、4Dのエラーダイアログボックスの表示を回避することもできます。
エラースタックについて
Tryコードブロックの最初の行が実行される前に、現在のエラースタックはクリアされます。新しいエラーを検出するために、実行前と実行後のエラースタックを比較する必要がないため、この動作はほとんどの場合において有益です。
したがって、Try-CatchコードブロックをCatchコードブロックに挿入し、エラースタック全体を取得したい場合は、この例のように、あらかじめコレクションに格納しておくことを忘れないでください:
var $errors : Collection
Try
throw(123; "一つ目のエラー")
Catch
$errors.push(Last errors)
Try
throw(456; "二つ目のエラー")
Catch
$errors.push(Last errors)
// $errors コレクションにはここまでに発生した2つのエラーが格納されている
End try
End try
グローバル・エラー処理と併用する
ON ERR CALLコマンドを使ったエラー処理は、現在でも有効です。Try(式)やTry-Catchコードブロックと合わせることで効果的に使うことができます。ただしその際のエラー処理の優先順位に注意してください:
- Try(式)。これは、単一行に対してエラーをチェックできるため、最も正確な方法です。
- Try–Catchコードブロック。1行ごとのエラーチェックが不要と考える場合は、この方法が最適です。
- ON ERR CALLコマンドにデフォルトのオプションであるek localを指定することで、現在のプロセス/ワーカーにおいて今後実行されるコードで、管理されていないエラーを検出することができます。
- ON ERR CALLコマンドにek globalおよびek errors from componentsオプションを指定することで、エラー処理メソッドがインストールされていないか、あるいはコードとして書かれていない場合でもエラーを検出することができます。
Try(式)またはTry-Catchコードブロックを使用してエラー処理をコーディングする主な利点は、次のとおりです:
- エラーを発生させるコードのできるだけ近くにエラー処理を配置する。
- エラー処理コード内でローカル変数を使用する
これで、エラーを思い通りに処理するための手札が開発者の手元にすべて揃ったことになり、よりコードを安全にすることができます!
私たちは、ユーザーに最高の体験を提供するよう努力しています。4Dフォーラムであなたの意見やコメントを共有することをお勧めします。あなたのフィードバックは、私たちがあなたのニーズを理解し、私たちの製品とサービスを継続的に改善するのに役立ちます。
それでは良いコーディングを!