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

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

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

この記事では、11問目-15問目までについて。

[1問目-5問目](https://qiita.com/jyunji_watanabe/items/2dba13380f3f7401201e)
[6問目-10問目](https://qiita.com/jyunji_watanabe/items/53e42d5cabe4c6221368)

# 11 長時間実行するバッチの設計
OutSystemsでバッチを実現する仕組みであるTimerにはTimeout（デフォルト20分で分単位)があります。
処理中に、Timeoutに到達してしまうとエラーとなり、DB処理はロールバックされ、一定時間後にリトライです。
この問題を避けるため、推奨される設計パターンがあります。

パフォーマンスのベストプラクティスに記述があります。
[タイマーおよびバッチジョブの長期実行を避ける](https://success.outsystems.com/Documentation/ja-jp/Best_Practices/Performance_Best_Practices/Performance_Best_Practices_-_Logic#.E3.82.BF.E3.82.A4.E3.83.9E.E3.83.BC.E3.81.8A.E3.82.88.E3.81.B3.E3.83.90.E3.83.83.E3.83.81.E3.82.B8.E3.83.A7.E3.83.96.E3.81.AE.E9.95.B7.E6.9C.9F.E5.AE.9F.E8.A1.8C.E3.82.92.E9.81.BF.E3.81.91.E3.82.8B)
「タイマーロジック内に明示的なタイムアウトを追加します。このロジックでは、タイムアウトに達したときに必要なアクションを行って現在の処理を適切に終了し、処理の現在のステータスを保存して処理が再開したときに停止時点からの処理をシームレスに続行できるようにします。実行の最後に、タイマー自体に対するウェイクタイマーアクションでタイマーを終了します。」

つまり推奨されている解決策では、
1. ロジック中に（TimerのTimeout値より確実に短い）タイムアウト時間を設定する
2. 進行管理用Entityを作る。例えば、100万件のデータを処理するとき、対象レコードのIDのみを進行管理用Entityに登録するなど
3. 進行管理用Entityをループして対象データを順番に処理していく
4. ループの中でTimer開始からの経過時間をカウントし、1で定めたタイムアウト時間に達していたら、進行管理用Entityに状況を記録して次回は続きから処理できるようにする。最後にWake\<Timer名\> Actionで同じTimerを起動させる

問題の実装例では、「進行管理用Entityに状況を記録して次回は続きから処理できるようにする。」に対応する部分がありません（D）

# 12 OutSystems環境内のDBと外部の別DBの結合について
これも、パフォーマンスのベストプラクティスです。
[リンクされた複数のサーバーにまたがる結合を実行しない](https://success.outsystems.com/Documentation/ja-jp/Best_Practices/Performance_Best_Practices/Performance_Best_Practices_-_Queries#.E3.83.AA.E3.83.B3.E3.82.AF.E3.81.95.E3.82.8C.E3.81.9F.E8.A4.87.E6.95.B0.E3.81.AE.E3.82.B5.E3.83.BC.E3.83.90.E3.83.BC.E3.81.AB.E3.81.BE.E3.81.9F.E3.81.8C.E3.82.8B.E7.B5.90.E5.90.88.E3.82.92.E5.AE.9F.E8.A1.8C.E3.81.97.E3.81.AA.E3.81.84)

OutSystems内に定義されたEntityと外部DBのEntityを結合させると、外部DBのデータを全件取得してから結合が行われ、非効率です。
よって直接結合しているB,Cは不可ですね。
Dは一端ローカルに持ってきているのはいいんですが、メモリに保存しています。すると、OutSystems内のEntityとRDBの機能では結合できずにロジックを書くことになりますね。代わりに、Aの方法でOutSystemsに必要なデータをコピーしたEntityを用意すれば、直接結合できるます。

# 13 Publishしようとしたら、他人の変更内容と衝突があった場合のService Studioの挙動
難しいことを聞いているわけではないですが、細かいですね。
2つに絞るまでは簡単ですが、急に聞かれても、試験の場で自信を持って回答するのは難しい。

# 14  セキュリティー
直接聞かれているのは、SQL Injectionです。通常、AggregateやSQLを使ってクエリするとOutSystemsがSQL Injectionを防いでくれます。
しかし、SQLに渡すParameterのExpand Inline=Yesにすると、この防御が効かなくなります。
SQL文を作るときに、渡したパラメータを(エスケープせずに)結合するためです。

Expand Inine=Yesにしなければ、Prepared Statementによる防御が有効になります。
[SQLインジェクションに関する警告](https://success.outsystems.com/Documentation/ja-jp/11/Reference/Errors_and_Warnings/Warnings/SQL_Injection_Warning)

選択肢BはAnonymousユーザーに更新系操作を許可するのはセキュリティ上問題がありますが、それはSQL Injectionではないですね。
ログイン画面でHTTPSを有効にしないとセキュリティ上問題ですが、これもSQL Injectionではない。

# 15 Encode**ビルトイン関数
[EncodeJavaScript](https://success.outsystems.com/Documentation/11/Reference/OutSystems_Language/Logic/Built-in_Functions/Text#EncodeJavaScript) のドキュメントを確認してみましょう。

「この関数はJavaScriptリテラルで使用される文字列のエンコードを行うのみであるため、関数自体はクロスサイトスクリプティング（XSS）やJavaScriptインジェクションの脆弱性に対する保護を提供しません。」

いかにもJavaScriptスクリプトを安全にエスケープしてくれそうに見えますが、ドキュメントにはっきりとその目的では使えませんと書いてあります。単に「JavaScriptの文字列」として渡す文字列をエスケープしてくれるだけです。

他のEncode**系ビルトイン関数みんな同様の特徴があるので注意してください。