この前のブログ記事では、ORDAのエンティティが constructor を持てるようになり、エンティティのインスタンス化が完全なオブジェクト指向のアプローチに従うことができるようになったことを発見しました。
それだけではありません。別のブログ記事では、複数実装される ORDAデータイベントの中で最初のイベント、touched イベントを紹介しました。
クライアントアプリケーションとサーバーの間でアクションが行き来している間に、constructor と touched イベントがいつ、どこでトリガーされるかを正確に知りたいですか?
このブログ記事ではそれを詳細に説明いたしますので、読み進めてください!
constructor と touched イベントについてまだご存知ない場合は、上記のブログ記事をまずお読みください。どのように実装すべきかが説明されています。
HDI: ORDAのコンストラクターと touchedイベントの実行タイミング
始める前に
これらの2つの機能は、包括的で強力かつ最適化されたORDA抽象化レイヤーの一部です。記憶を新たにするためには、このブログ記事とこのブログ記事をお読みください。
ORDAデータモデルクラスでは、データは、ストラクチャーで定義された Entityクラスのインスタンスであるエンティティを通して処理されます。
ORDA は複数の種類のアプリケーションで使用できます:
- クライアント/サーバー (C/S) アプリ
- Qodlyアプリ
- REST API を使用するアプリ
- リモートデータストアを使用するアプリ
どこで?
以下の表は constructor と touched イベントがどこで実行されるかをまとめています:
| 実行場所: | C/S (1) | Qodly ページ (2) REST API (3) リモートデータストア (4) |
|---|---|---|
| コンストラクター | クライアント | サーバー |
| touchedイベント |
localキーワードの場合: クライアント |
サーバー |
(1): プロジェクトは 4D Server 上でデプロイされ、ネットワーク接続を介してリモートの 4Dクライアントがアクセスします。データ操作は、クライアントまたはサーバーのいずれかで実行できます。
(2): プロジェクトは 4D Server 上でデプロイされ、Webクライアントは Webブラウザーを介してアクセスします。Qodlyアプリはプロジェクトの REST API を消費します。
(3): 外部アプリケーションは、標準的な RESTリクエストを使用して、4Dアプリケーションの REST API を利用できます。
(4): 4Dアプリケーションは、1つ以上のリモートデータストアに接続して、複数のデータソースにアクセスすることができます。この場合、リモートデータ操作の処理するために ORDA が使用されます。
いつ?
このブログ記事の残りの部分では、constructor と touched イベントがいつ実行されるかに焦点を当てていきます。
最適化とパフォーマンス上の理由から、新しいエンティティがインスタンス化されたときに即座に constructor が実行されるとは限りません。touched イベントについても同様で、属性が更新されたときにも即座に実行されるわけではありません。
各アプリケーションタイプごとの詳細を見ていきましょう。
スタンドアロンアプリ
スタンドアロンアプリでは、プロジェクトはローカルディスクに保存されます。ネットワーク接続はデータアクセスに必要ないため、すべてのデータ操作はローカルで即座に実行されます。
すべてがシンプルで簡単です。constructor と touched イベントは、新しいエンティティがインスタンス化されたとき、または属性値が変更されたときに即座にトリガーされます。
rest api
このケースも単純です。エンティティに対するすべてのアクションは、サーバーへのRESTリクエストを介して実行されるため、constructor と touched イベントの両方が、リクエストが実行されるとすぐにサーバー上でトリガーされます。
クライアントサーバーアプリ
コンストラクター
新しいエンティティがクライアント上でインスタンス化されると constructor がクライアント上で実行されます。
これは、属性に割り当てられた初期値がクライアントに即座に表示されることを意味します。その後、そのエンティティが関与する関数 (例: エンティティをパラメーターとして受け取る関数) が呼び出されたとき、サーバーは、クライアント上で初期化された属性を持つエンティティを受け取ります (1)。
この関数は ORDA API または ORDAデータモデル関数のいずれかである場合があります。
(1)ORDA関数は常にサーバー上で実行されることを覚えておいてください。

touchedイベント
デフォルトでは、touched イベントはサーバー上で実行されますが、local キーワードを使用すると、代わりにクライアント上で実行することができます。
local キーワードを使用しない場合:
この例で使われている apply() 関数は、クライアント上で行われたエンティティ更新をサーバー側と同期するためだけのダミー関数です。

local キーワードがある場合:

qodly アプリ
新しくインスタンス化されたエンティティや変更された属性をサーバーが認識するとすぐに、constructor と touched イベントの両方がサーバー上で実行されます。
レンダリングされると、Qodlyページは Webブラウザーで実行されますが、サーバーサイドのロジックが必要なアクションが発生するたびに、REST API を介して4Dサーバーにリクエストが送信されます。
コンストラクター
標準アクションCreate を使用して新しいエンティティをインスタンス化する場合:

これはフロントエンドでローカルに発生します。そのため、コンストラクターはすぐに実行されません。コンストラクターは、サーバーが新しくインスタンス化されたエンティティを検出した時点で実行されます。
この例で使われている apply() 関数は、クライアント上で行われたエンティティ更新をサーバー側と同期するためだけのダミー関数です。

注記:
フロントエンドが標準アクション Create で新しいエンティティをインスタンス化し、コンストラクターで使用するより先に属性の値を設定した場合、その値はコンストラクターがサーバーで実行されたときに上書きされません。

一方、エンティティがサーバー側の関数によってインスタンス化された場合、コンストラクターはサーバー上で直ちに実行されます。返される Qodly ソース (エンティティ) には、コンストラクターによって初期化された属性が含まれます。

touchedイベント
touched イベントは、サーバーが変更された属性値を検出するとすぐにサーバー上でトリガーされます。
この例で使われている apply() 関数は、クライアント上で行われたエンティティ更新をサーバー側と同期するためだけのダミー関数です。

リモートデータストアを使用するアプリ
リモートデータストアの使用は、REST API を使用してリクエストを内部的にトリガーするため、Qodly アプリとほぼ同じように動作します。ローカルの 4Dアプリケーション上で新しいエンティティがインスタンス化された場合、それをサーバーが認識したときに constructor が実行されます。
touched イベントについても同様です。ローカルの 4Dアプリケーションでエンティティが更新された場合、エンティティ属性の変更をサーバーが検出したときに touched イベントが実行されます。
例1
ProductsEntity クラスに、次の constructor が実装されています:
Class extends Entity
Class constructor()
This.creationDate:=Current date()
This.comment:="Automatic comment"
ローカルの 4Dアプリケーションで、次のコードが実行されます:
var $connect:={hostname: "127.0.0.1"}
var $remote : 4D.DataStoreImplementation
var $product : 4D.Entity
var $status : Object
$remote:=Open datastore($connect; "demo")
// コンストラクターはまだ実行されていません
// creationDate と comment 属性は空です
$product:=$remote.Products.new()
// ここで save() がサーバーで実行されるため、コンストラクターが実行されます
// サーバーは、これが新しくインスタンス化されたエンティティであることを検出します
// creationDate と comment 属性が設定されます
$status:=$product.save()
例2
ProductsEntity クラスに touched イベントと apply() 関数が実装されています:
Class extends Entity
Function event touched comment($event : Object)
This.comment:=Uppercase(This.comment)
exposed Function apply() : cs.ProductsEntity
return This
ローカルの 4Dアプリケーションで、次のコードが実行されます:
var $connect:={hostname: "127.0.0.1"}
var $remote : 4D.DataStoreImplementation
var $product : 4D.Entity
$remote:=Open datastore($connect; "demo")
$product:=$remote.Products.all().first()
// comment 属性は大文字になっていません
$product.comment:="New comment"
// apply() 関数がサーバーで呼び出されるため
// touched イベントがトリガーされ
// comment 属性が大文字になります
$product:=$product.apply()
添付の HDI で、これらの例を実際に試してみてください!
