Try-Catchコードブロックをご紹介!

throw()コマンドを実装し、Try(Expression)キーワードの導入に続き、4Dのエラー処理システムの次の進化として、Try-Catchコードブロックを導入しました!

4D 20 R5 からは、新しいTryCatchEnd 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エラーダイアログボックスが表示されないように保護するためには、TryEnd tryキーワードでコードブロックを囲むことでそれを保護できます。
エラー処理は必須というわけではありませんが、あると良いでしょう。そこで、End tryキーワードの前にCatchキーワードを挿入することで、CatchキーワードとEnd tryキーワードの間に、複数行にエラー処理コードを書くことができるようになりました。このやり方は他の言語でも一般的なもので、長いメソッドや関数を読みやすくします!

Tryコードブロックの実行中にエラーが発生しなかった場合、コードはCatchコードブロック(もしあれば)をスキップし、End tryキーワードの後のコードの実行を続けます。
しかし、Tryコードブロックのどこかの行でエラーが発生した場合、その後の実行は以下のようになります:

  1. カレントエラー処理メソッドがインストールされていても、そのエラー処理メソッドは呼び出されません。
  2. 4Dのエラーダイアログボックスは表示されません。
  3. エラーは現在のエラースタックに追加されます。
  4. コードの実行は直ちにCatchコードブロックに切り替わります。Catchキーワードがない場合、コードの実行は対応するEnd tryキーワードの直後へとスキップされます。

 

現在の実行コンテキストにエラー処理メソッドが定義されておらず、Catchコード・ブロックの実行中にエラーが発生した場合には、4Dのエラーダイアログボックスが表示されるという点に注意してください。しかし、Try(式)または入れ子になったTryCatchコードブロックを使用して、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コードブロックと合わせることで効果的に使うことができます。ただしその際のエラー処理の優先順位に注意してください:

  1. Try(式)。これは、単一行に対してエラーをチェックできるため、最も正確な方法です。
  2. TryCatchコードブロック。1行ごとのエラーチェックが不要と考える場合は、この方法が最適です。
  3. ON ERR CALLコマンドにデフォルトのオプションであるek localを指定することで、現在のプロセス/ワーカーにおいて今後実行されるコードで、管理されていないエラーを検出することができます。
  4. ON ERR CALLコマンドにek globalおよびek errors from componentsオプションを指定することで、エラー処理メソッドがインストールされていないか、あるいはコードとして書かれていない場合でもエラーを検出することができます。

 

Try(式)またはTry-Catchコードブロックを使用してエラー処理をコーディングする主な利点は、次のとおりです:

  • エラーを発生させるコードのできるだけ近くにエラー処理を配置する。
  • エラー処理コード内でローカル変数を使用する

 

これで、エラーを思い通りに処理するための手札が開発者の手元にすべて揃ったことになり、よりコードを安全にすることができます!

私たちは、ユーザーに最高の体験を提供するよう努力しています。4Dフォーラムであなたの意見やコメントを共有することをお勧めします。あなたのフィードバックは、私たちがあなたのニーズを理解し、私たちの製品とサービスを継続的に改善するのに役立ちます。
それでは良いコーディングを!

Avatar
- プロダクトオーナー - Damien Fuzeauは、2019年2月に4D Productチームに参加しました。プロダクトオーナーとして、ユーザーストーリー(ユーザーが期待する新機能とその使用法)を書き、それを具体的な機能仕様に変換することを担当しています。また、実装された機能が顧客のニーズを満たしているかどうかを確認することも彼の役割です。ナント大学のソフトウェア工学科を卒業。前職の会社では最初は開発者として(1997年に4Dを発見)、後にエンジニアリングマネージャーとソフトウェアアーキテクトとして、23年以上勤務しました。この会社は、4DのOEMパートナーであり、現在は数千のユーザーと数百のサーバーに向けて4Dベースのビジネスソフトを展開しています。ですから、Damienは、多言語環境での4D開発・導入に慣れています。