[OutSystems]ODC Associate Developerのサンプル問題について解説 1/3(#1-#5)

ODC Associate DeveloperはODC向けのエントリレベルの認定試験。
2023/10時点では、ODC向けの認定はこれだけ。

試験情報のPDFと一緒にダウンロードできるサンプル問題を解説する。
全部で15問で、この記事では1問目-5問目が対象。

他の問題については以下を参照
[ODC Associate Developerのサンプル問題について解説 2/3(#6-#10)](https://qiita.com/jyunji_watanabe/items/5b0ea065e0f4dfa6c57d)
[ODC Associate Developerのサンプル問題について解説 3/3(#11-#15)](https://qiita.com/jyunji_watanabe/items/51807993534abbb9b82b)

サンプル問題は、
https://www.outsystems.com/learn/certifications/
の、「Associate Developer (ODC) 」項目のリンク「Exam Details」でダウンロードできる資料から。「Sample Exam」がついている方のファイルが該当する。
ここでは2023/10にダウンロードしてきたファイルを使って解説していく。
サンプル問題は英語しかなかったので、この解説は英語版を見ながら書いている。

各問題のタイトルは、Details Sheet日本語版のトピック名で、問題に対応していそうなものを選んでいる。

# 1 データリレーション
ER図を見ると、PersonMovieRole Entiyは、Person EntityとMovie Entityの多対多関係を表すためのもの。
PersonMovieRoleがPersonRoleIdを持っているので、PersonMovieRoleとPersonRoleは1対多の関係。

選択肢を見ていく
A. 〇：PersonMovieRole Entityの1レコードはMovieId属性を1つしか持たないので、関連付けられるMovieレコードも1つのみ
B. 〇：PersonMovieRole EntityはPersonRoleIdを属性として持っている。そのため、複数のPersonMovieRoleレコードが同じPersonRoleレコードを参照し得る
C. ×：Movie EntityはGenreIdでMovieGenre Static Entityを参照している。MovieGenreを参照する属性が他にないので、Movie1レコードが持つMovieGenreは1つのみ
D. 〇：PersonとMovieそれぞれのIdを属性に持つEntityを仲立ちにすることで成立する、多対多の関係。よってPerson:Movie=M:Nであり、Person1レコードは複数のMovieレコードと関連しうる

問題は正しくないものを聞いているので、選択肢Cが正解。

# 2 Aggregate
Email属性が「@outsystems.com」で終わるものみを返すFilter条件を選択する問題。

後方一致を示す場合「属性名 like "%@outsystems.com"」が正解。
部分一致を行うのが「like」で、その位置にはどの文字が来てもいいことを表すのが「%」。

よって選択肢Cが正解。

# 3 画面でのデータ取得
FetchプロパティがOnly on Demandに設定されているAggregateの取得が開始されるのはいつか？　という問題。

FetchプロパティはデフォルトがAt start。このときはScreenのInitializeの後に動き始める（ドキュメントから引用した下図参照）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/aa61b4c6-ecdf-984c-5398-45d5eae74e14.png)
（ODCの公式ドキュメント：[Screen and block lifecycle events > Lifecycle stages > On opening the app](https://success.outsystems.com/documentation/outsystems_developer_cloud/building_apps/user_interface/screen_and_block_lifecycle_events/#on-opening-the-app)より　2023/10/07　引用）

それに対して、Only on Demandにした場合、明示的にRefresh Dataでリクエストされたときにのみデータ取得が行われる。OutSystems 11のドキュメントだが、[Aggregateを使用して非同期のデータ取得を実装する](https://success.outsystems.com/ja-jp/documentation/11/developing_an_application/use_data/query_data/implement_asynchronous_data_fetching_using_aggregates/)が参考になる。

よってロジックによって明示的にトリガーされたときにのみAggregateが実行されるとする選択肢Bが正解。

ちなみに、選択肢AはScreenのOnReady Event、CはOnRender Eventの説明。

# 4 クライアントアクションとサーバーアクション
Logicタブ > Client Ationsの下に作成したClient Actionで、Functionプロパティ=Yesのものはどこで使えるか、という問題。

まず、基本として、Client ActionはServer Actionからは呼べない。よって選択肢Aは×。
Logicタブの下に作られたClient Actionは他のClient Action (Screenの下に作られたもの、Logicタブの下に作られたもの双方）から呼べる。また、Function=Yesにしておけば、Screen上のWidgetの式内で呼べる。

よってこの両方に言及している選択肢Cが正解。

# 5 フォームの検証
ODCのドキュメントで、Formの仕組みを説明しているものは見つからなかったが、動作を確認する限り、OutSystems 11のFormと基本的には同じ仕組みのように見える。よって、OutSystems 11の知識を前提に説明する。

Formを配置した詳細画面で、データベースへの保存を行うためのボタンをクリックした。
カスタムバリデーションは行っていない、つまり以下の図のようなEntityをドラッグ＆ドロップして自動生成した画面の保存ロジックと同様のロジックだと思われる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/377eb15c-d507-b09a-0b61-0eff49fccff5.png)

この場合、最初のIfで、Form1.Valid=Trueであれば保存が行われる。
独自にForm内のWidgetのValidを設定しない（＝カスタムバリデーションを行わない）場合、自動で行われるBuilt-Inのバリデーションのみが行われる。

Built-Inのバリデーションは、Is Mandatory（必須入力の項目で未入力のものが無いか）のチェックやWidgetに紐づけている変数と入力した値（型に合わない入力が無いか）のチェックが行われ、どれか1つでも引っかかると、親となるFormのValid=Falseとなる。

このような基礎的なバリデーションに引っかかるようでは、サーバーにデータを送って本格的なバリデーションを行う価値が無い状態なので、問題文のForm.Validをチェックするのはよいことか？　という質問の答えはYes。

ここで選択肢はAとCに絞られる。
CはYesの後で、Built-Inバリデーションは型チェックを行わないと書いてあるが、上に書いたように行うので誤り。

選択肢Aが正解。