ORDA は、4D の新たな可能性の世界を開く重要な機能です。
パワフルなコードを書けるようにするため、私たちは ORDA を強化し続けています。ORDA によってアプリの開発やメンテナンスが容易になるだけでなく、エンドユーザーにとって素晴らしいパフォーマンスが発揮されるよう最適化されています。
4D 20 R10 では、インメモリデータイベントという新機能をご紹介できることを嬉しく思います。
典型的なユーザーフローでは、ユーザーが必要とするデータはメモリにロードされます。そして、ユーザーのアクションに応じて変更され、最後にユーザーが保存ボタンをクリックすると保存されます。
その際、インメモリデータが変更されたときに、ビジネスロジックがトリガーされるとしたらどうでしょう? 保存処理をおこなう前にデータの形式を整えたり準備したりして、データを保存可能な状態にすることができれば、とても便利です。
ORDA の touched イベント によって、これが可能になりました! そのメリットは非常に大きいといえるでしょう。
もっと知りたいですか? 続きをお読みください!
ORDA はすでにこのブログ記事で詳述した多くの側面をカバーしています。 ORDAの抽象化レイヤーはこれまで以上に強力になりました: ORDA は、メモリ上のデータのあらゆる変更に反応できるようになったのです。
ORDA では、読み取りアクション (たとえばクエリ) によってメモリにロードされたエンティティを通してデータが扱われることを思い出してください。
4D 20 R10 では、エンティティレベルイベントの概念を導入しています。touched イベントは、今後追加予定の一連のイベントの最初のもので、従来の 4Dコードには相当するものがないため、採用する価値があります。
touched イベントを使用すると、メモリ内でエンティティの属性値が変更された際に実行されるビジネスロジックのコードを中央集約化できます。
エンティティの属性が変更されたときにビジネスロジックをトリガーする
ユーザーフローの中で、インメモリデータの変更に反応して独自のビジネスロジックをトリガーし、ユーザーに表示される内容をリアルタイムで更新することができるようになりました。
エンティティを扱うとき、特定の属性に焦点を当て、その値が変更されたときにコードをトリガーすることができます。
以下は、この機能が特に役立ついくつかのユースケースです:
- データを大文字または小文字にする
- 同じデータモデル内の他の属性を更新する
例題1
以下の例題では、People エンティティが更新されています。title は先頭の6文字に切り捨てられ、lastname および city への入力は大文字になります。

以前は、各フォームオブジェクトで On Losing Focus ようなイベントを処理し、多くの場所で同じコードを記述する必要がありました。
今後は、touched と event キーワードを使って、特定の属性に対する touched イベント を実装できるようになりました。コードは適切な Entity クラスに集約化され、アプリケーションのあらゆる場所で属性値が変更されるたびにトリガーされます。
この例題では、PeopleEntityクラスのいくつかの属性について、touched イベントが次のように実装されています:
Class extends Entity
Function event touched title($event : Object)
This.title:=Substring(This.title; 1; 6)
Function event touched lastname($event : Object)
This.lastname:=Uppercase(This.lastname)
Function event touched city($event : Object)
This.city:=Uppercase(This.city)
例題2
この例題では、touched イベントを使用して、パフォーマンスに影響するかもしれない計算属性の使用を回避しています。レンタカーアプリの Booking データクラスでは、出発日と到着日が同じかどうかを知る必要があります。
その場合、次のような方法が考えられます:
exposed function get sameDay(): Boolean
return (This.departureDate = This.arrivalDate)
しかし、この計算属性に対するクエリはインデックスを使用できないため、最適化されていません。
そこで、sameDay 属性をデータクラスに作成し、departureDate および arrivalDate 属性に対して touched イベントを実装することで、sameDay 属性を最新の状態に保ちます:
Function event touched departureDate($event : Object)
This.sameDay:=(This.departureDate=This.arrivalDate)
Function event touched arrivalDate($event : Object)
This.sameDay:=(This.departureDate=This.arrivalDate)
いずれかの属性の変更でビジネスロジックをトリガーする
touched イベントはエンティティレベルでも実装することができ、その場合はいずれかの属性値の変更にともないイベントがトリガーされます。イベントにより提供される変更に関する情報は、デバッグやリアルタイムでのUI更新など任意の目的に利用可能です。
実装方法
Entity クラスに、イベントオブジェクトを引数として受け取る touched イベント関数を追加します。
たとえば、PeopleEntity クラスの例です:
Class extends Entity
Function event touched($event : Object)
ユースケース #1 – サイレントアップデートのデバッグ
アプリケーションにおいて、People エンティティが更新されようとしている場所を特定したい場合を考えてみましょう。touched イベント を実装し、内部にブレークポイントを置けば、呼び出し連鎖を確認できます。
以下の通り、簡単な updatePeopleプロジェクトメソッドが実行されたとします:
$people:=ds.People.all().first()
updateCivilInfo($people)
updateAddress($people)
デバッグウィンドウの呼び出し連鎖では、updatePeopleメソッドからupdateCivilInfoメソッドが呼び出され、イベントをトリガーしたことを確認できます。さらに、touched イベントオブジェクトから、変更された属性の名称を取得することができます:

ユースケース #2 – テキスト属性の大文字化
属性名に関わらず、属性がテキスト型であれば、属性値を大文字にしたい場合を考えてみましょう。
これは、次のコードで実現できます:
Class extends Entity
Function event touched($event : Object)
If (Value type(This[$event.attributeName])=Is text)
This[$event.attributeName]:=Uppercase(This[$event.attributeName])
End if
このコードは、アプリケーションのどこでも動作します:

お察しのように、touched イベントは頻繁に発生する可能性があります。つまり、パフォーマンスを維持するため、実装するコードは高速で軽量でなければなりません。上の最後の例は、データクラスの属性数が少ない場合に適切でしょう。
このイベントが C/S や 4D Qodly Pro でどのように動作するか、あるいはリモートデータストアを使用する際にどのように動作するかについては、こちらのブログ記事をご覧ください。
また、ドキュメントを確認し、HDI をぜひ試してみてください。
