Professional Web Developer (OutSystems 11)のサンプル問題についてメモ 1/3(#1-#5)

**2020/5/11 1の問題を再検討して、結論としてサンプル問題の回答と同じ答えにたどり着きました。該当部分に追記しています。**

最近、Professional Web Developer (OutSystems 11)のサンプル問題が15問公開されました。
（たぶんOutSystemsの試験では初めて）

折角なので、各問題をチェックしてどの資料を確認すれば回答できるのかコメントしていきます。
実際に自分で解いてみると、Professional試験で要求されている知識のレベルがわかると思います。

この記事では、1問目-5問目までについて。
[6問目-10問目](https://qiita.com/jyunji_watanabe/items/53e42d5cabe4c6221368)
[11問目-15問目](https://qiita.com/jyunji_watanabe/items/93720bcb9df704ea599e)

# OutSystems 11 Professional Web Developer Certification
OutSystemsの試験は、Associate->Professional->Expertの3段階です。
Professionalの試験を受けるためには、いずれかのバージョンでWebアプリケーションのAssocciateの試験に合格しておく必要があります。
この試験は、Professionalレベルの、Traditional Webアプリケーションの知識を認定するもの。
試験は選択式で70%正解すれば合格。
詳しくは、以下の、「Exam Details (.pdf)」でダウンロードできる資料から。サンプル問題もそこにあります。
https://www.outsystems.com/learn/certifications/

なお、サンプル問題には回答だけで解説はありません。

# 1 EntityのIndex
実はこの問題だけ、まだ正解に至る経緯がわかっていません。ちょっと頭を冷やして考え中です。

問題は、EntityのIndex。Entityの背後にはRDBのテーブルがあるので、RDBのIndexの知識が必要です。
問題の設定では、AggregateのFILTERSにLastName->FirstNameの順番で指定しています。
それに対して、以下3パターンのINDEXのどれが最もパフォーマンスをあげるか？　という問題

1. FirstName
2. LastName
3. FirstName->LastName

検索条件で同じ順番でインデックスを作らないと機能しないから、「2」かと思ったのですが、回答は「3」。
理由は今調べています。わかったら追記予定です……。

（2020/5/11 追記)
SQL Serverを手元のコンピュータでテストしてみました。

材料として

- SampleName Table
    - FirstName列
    - LastName列
    - インデックス：Firstname 昇順、LastName昇順
    
を用意した上で、以下のクエリで検索し、推定実行計画を確認。インデックススキャンされますね。ということは、「3」の選択肢が指定列数が多いことから、一番効率的ということになりそうです。

```sql
SELECT [FirstName],[LastName]
  FROM [SampleName]
  WHERE LastName = 'a' AND FirstName = 'b'`
```

![qProfessionalSample1_2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/fc0bb9a9-a90f-42d4-69d1-50e67aadc434.png)


# 2 Entity間の参照とDelete Rule
この動画の真ん中あたり：
[データリレーションのモデリング](https://www.outsystems.com/ja-jp/learn/lesson/1770/modeling-data-relationships)

OutSystemsのEntityは他のEntityのId型（例えば、Customer Entityであれば、Customer Identifier型）のAttributeを持つことで、そのEntityへの参照を持ちます。

- 自分のIdとして、他のEntityのId型のAttributeを持つと　1:1の参照
- 自分の(Id以外の)Attribnuteとして、他のEntityのId型のAttributeを持つと　1:多の参照
- 2つのEntityそれぞれのId型のAttributeを持つと、多:多の参照

他のEntityのId型のAttributeには、Delete RuleというPropertyがあります。参照しているレコードの削除に対してどう振る舞うかを定義します。

- Ignore：何もしない
- Protect：参照先レコードを実際に参照しているレコードが参照元のEntityに残っている限り、参照先レコードを削除できないようにする
- Delete：参照先レコードが削除されるとき、そのレコードを参照しているレコードも一緒に削除されるようにする

# 3 SQLとAggregateの違い
Action Flowに配置できるDB操作用の2つのツールSQLとAggregateの知識が必要な問題。
この問題は、Performance Best Practicesを良く読んでおくと答えられます。

## クエリの最適化
Aggregateについては、コンパイル時に、クエリ結果の利用状況をチェックし、必要な列だけ取得する最適化の機能があります。
つまり最適化を言っている選択肢はSQLではなくAggregateを指している。
SQLでは最適化は自分でクエリを書くことで実現します。

以下のページでいくつか記載している箇所があります。
[パフォーマンスのベストプラクティス - クエリ](https://success.outsystems.com/Documentation/ja-jp/Best_Practices/Performance_Best_Practices/Performance_Best_Practices_-_Queries)
例：「すべてのエンティティアトリビュートを取得する必要がない場合は、Get呼び出しをAggregateに置き換えてIdentifierパラメータを使用することを検討します。プラットフォームはクエリを最適化し、必要なアトリビュートを取得します。」

## Max RecordsのSQLとAggreagteの違い
これも同じPerformance Best Practicesに記述があります。
[最大レコード数は常に必要数に合わせる](https://success.outsystems.com/Documentation/ja-jp/Best_Practices/Performance_Best_Practices/Performance_Best_Practices_-_Queries#.E6.9C.80.E5.A4.A7.E3.83.AC.E3.82.B3.E3.83.BC.E3.83.89.E6.95.B0.E3.81.AF.E5.B8.B8.E3.81.AB.E5.BF.85.E8.A6.81.E6.95.B0.E3.81.AB.E5.90.88.E3.82.8F.E3.81.9B.E3.82.8B)

ちなみに、Max Records Propertyは以下の位置
![qProfessionalSample1_1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/32d69987-d3e4-c6ef-8b0d-411914161e90.png)


違いを書いておくと、

- AggreagteのMax Records：DBから取得するデータのレコード数を制限するようにSQL文が自動で書き換えられる
- SQLのMax Records：SQL文自体は書き換えられないため、DBからはこの制限以上のレコード件数が帰ってくる可能性がある。プロパティの設定値はアプリケーションレベルで機能する

## Cache in Minutes
このプロパティは、SQLにもAggregateにもあります。
実行結果をFront-Endサーバーのメモリ内に記憶しておきます。
有効期限内の同じアクセスにはDBに問い合わせずに、メモリから返るため処理時間が早くなることが期待できます。

# 4 ViewState
これもPerformance Best Practicesの知識問題。

## ViewStateとは
これは、OutSystemsではなく、現時点でその基盤テクノロジーとして利用されているASP.NETの要素です。
ユーザーに返すHTML内にUIの状態を埋め込んでおくものです。開発者が特に何かしなくても勝手に行われます。
HTML内に埋め込んでおいて、次のサーバーリクエスト時にそこから以前の状態をメモリに復元します。
つまり、HTTP通信の際に通信にViewState内のデータがついていってしまいます。
そのため、あまり大きなデータをおいておくと通信量が大きくなり、処理速度にも影響してきます。

## Preparation内のクエリ結果をScreen Actionで触るとViewStateが重くなる
ここでPerformance Best Practicesです。
[画面アクションでPreparationデータを使用することは避ける](https://success.outsystems.com/Documentation/ja-jp/Best_Practices/Performance_Best_Practices/Performance_Best_Practices_-_User_Interface#.E7.94.BB.E9.9D.A2.E3.82.A2.E3.82.AF.E3.82.B7.E3.83.A7.E3.83.B3.E3.81.A7Preparation.E3.83.87.E3.83.BC.E3.82.BF.E3.82.92.E4.BD.BF.E7.94.A8.E3.81.99.E3.82.8B.E3.81.93.E3.81.A8.E3.81.AF.E9.81.BF.E3.81.91.E3.82.8B)

Preparationで用意したデータをScreen Actionで利用する（例えばButton Clickなど）と、そのデータがViewStateに保存されてしまいます。すると、SubmitのときもAjax Submitのときも、このデータが通信にのってサーバとブラウザ間で行き来することになります。特に大きなデータをクエリしているときなどに問題が大きい。

ではどうするか？　というとIdだけを利用し、Screen Actionでは必要なデータを再検索することですね。

# 5 JavaScriptの定義
## ExpressionへのJavaScript記述は注意が必要
以下に記述がありました。
[Avoid inline JavaScript or inline style](https://success.outsystems.com/Documentation/Architecture_Dashboard/Code_Patterns/Best_Practices/Avoid_inline_JavaScript_or_inline_style)

Escape Cotent=NoにしたExpressionにJavaScriptを記述するのは手軽である反面

- 他のScreenで再利用できない
- ページサイズが増えるのでパフォーマンス上の問題がある
- 別ファイルに切り出さないためにキャッシュされない
- 手軽に記述できることからドキュメントされない傾向にある

ということから、絶対ダメというわけではないが、Expressionに書くとしてある選択肢はとりあえず△ですね。他に○がなければ検討する。

## JavaScript Property
Module/Screen/Web BlockのJavaScriptで定義したJavaScriptは実は独立したJavaScirptファイルとしてページ実行時に読み込まれています。
以下の動画（英語のみ）の8:50くらいのスライドに書いてあります。
[Top front-end techniques for OutSystems](https://www.outsystems.com/learn/lesson/1123/top-front-end-techniques-for-outsystems)

問題になるのは、ModuleレベルのJavaScript Propertyに書いてしまうと、全てのScreen実行時に読み込まれてしまうことです。
問題の設定では定義するJavaScript関数は1画面でしか使わないそうなので、これではいかにも無駄ですね。