ODCのアーキテクチャ設計の変更に備える（2023/10/18 UserGroup LT）

2023/10/18に開かれたOutSystems User Group Tokyoのイベント[OutSystems Connect: LTで繋がる技術者の夜！](https://usergroups.outsystems.com/events/details/outsystems-inc-tokyo-presents-outsystems-connect-ltdexi-garuji-shu-zhe-noye/)で行ったLTの内容にちょっと追記したもの。

# 要旨
ODCでは、O11からプラットフォームのアーキテクチャが変更されたため、ほぼマイクロサービス設計が強制される。

マイクロサービスの恩恵がいらない組織であっても。
（さほど複雑でないシステムはマイクロサービス化の恩恵を受けられないとよく言われる）

ODCの製品としてマイクロサービス化にあたって必要な手間を減らしてくれたとしても、依然としてマイクロサービスであることによる設計上の制約や困難がある。

そうした影響を軽減するために、開発標準や設計ガイドラインの整備が必要。

# アーキテクチャ設計に関連するODCの変更点
## 変更点①ModuleはAppとLibraryの2種類に整理された​
- OutSystems11ではモジュールは、Reactive Web App/Traditional Web/Mobile/Service/Library/Extensionなどがあったが、ODCではAppとLibraryに整理された
- App: OutSystems 11でいうEnd Userレイヤーモジュールに相当するものApp。App単位でコンテナに分離される
- Library: OutSystems11のFoundation Layerのモジュールに相当するものがLibrary。 Entityを含むことはできない。Libraryはコンテナにはならず、コンパイルされたものはLibraryを参照するAppのコンテナ内に格納される
- よってO11のCore Serviceモジュールに対応するものは必然的にAppになる

## 変更点②Applicationがない​
- O11で複数のモジュールの入れ物であり、リリースの単位であったApplicationが無くなった
- リリースは1App単位ずつ行う
- 開発環境でPublishをした段階でコンテナが準備されレジストリに登録されている。リリースはそのコンテナをコピーするだけなので高速

## 変更点③Appは弱い参照のみ公開できる​
- Appが公開する要素への参照はすべて弱い参照になり、実行時にはHTTPS通信を介して行われる
- Libraryが公開する要素を参照すると強い参照になり、呼び出しはメモリ内で行われる

## まとめると
UIを提供するのはApp
O11でいうCore Serviceのように、Entityを持ってActionを外部に提供するものもApp
1つのAppは1つのコンテナに分離される
⇒UIやサービスを提供するコンテナをAppとして作っていく
　Appがマイクロサービスに該当する

# ODCでのアーキテクチャ設計で注意する点
## アーキテクチャ設計の注意点①Architecture Canvasはそのままでは適用できない
恐らく、多くのOutSystems導入企業で、OutSystemsが提供していたArchitecture Canvasを利用したアーキテクチャ設計を標準やガイドとして採用しているのではないか。

- 現状、公式ドキュメントやコースを見る限り、Architecture Canvasは利用されない​
- ODCに合わせた設計ルールを確立する必要がある​
- ただし、公式ドキュメントやコースには、ODC向けの設計手順の解説はあるので、これを元に開発標準や設計ガイドラインを修正（まだなければ作成）することになる​
    - 基本的な流れやバリデーションルールは共通する部分が多い​

## アーキテクチャ設計の注意点②Roleの配置​
ODCでは、RoleをPublicにできない​。

- Roleを一か所で定義して各Appで共有する、ということができない​
- では、どうするかというと​
    - RoleをService Actionとして提供する（User Idを受け取って、RoleがGrantされているかどうかを返す）​
    - 同名のRoleを必要な全てのAppに作成し、必要なユーザーにはその全てのAppのRoleを割り当てる
- OutSystemsが公式の動画で進めているのは後者​（Service ActionはHTTPS経由でアクセスすることになるため、オーバーヘッドがあるから）

## アーキテクチャ設計の注意点③UIの配置​
マイクロサービスアーキテクチャではあるが、マイクロサービス毎にUIの一部（OutSystemsではBlock)を作成し、ページ内に組み上げる方法（よく言われるマイクロフロントエンド）はOutSystemsではとりにくい​。Blockの組み込みはPublishの段階で決まってしまうため、Blockを変更したり新たにページを組み込もうと思うと、親画面のリリースが必要になるため。

開発規模に応じ、以下のような構成になるのではないか​
- シングルApp構成：1つのApp内に全てのUIを詰め込む​
- モノリシックUI：複雑になったので機能を別のサービスに切り出すが、UIは1Appに収める
- ページ単位のマイクロフロントエンド：システムのメニューはLibrary内のBlockとして定義。メニューの一部（例えばトップレベルのメニュー）ごとに異なるAppを割り当てる​

## アーキテクチャ設計の注意点④サービスをまたがるトランザクション​
ここが、ODCがマイクロサービスを強制することによる問題点のうち、最大のものだと思う。

App間のI/FはHTTPS通信になる→トランザクションも当然別になる​
- UIからのリクエストで始まった一連の処理が複数のService Actionを読んでいる場合（下図①②③）​
- ある処理中に例外が発生すると、「そのサービスだけ」ロールバックされる​（下図③）
- それ以前に呼ばれていたService Actionの処理はコミットされたまま​（下図②）

 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/dfae280a-2dcc-18c2-be9c-08743b2cfa9e.png)

こういった問題に対応するのがSaga​
- Sagaというのは、複数のサービスにまたがるトランザクションを、ローカルトランザクションのつながりとして実現する方法​
- あるローカルトランザクションでエラーが発生したら、それより前にコミット済みの処理に対して、逆の処理を行うことで取り消す​
- よくあるSagaの説明では、ローカルトランザクションの連鎖にはMessage Brokerを使う（1つのローカルトランザクションが終わったら、対応するMessageを発行し、次のトランザクションはそれに反応する）​
- [OutSystemsの公式動画](https://learn.outsystems.com/training/journeys/architecture-patterns-581/distributed-transactions-patterns/odc/629)では、UIから直接呼ばれるServer Actionが各Service Actionの実行と（エラーの場合の）コミット済みトランザクションの取り消しを行うパターンが紹介されていた​。Sagaの実装方法としてはお手軽だが、OutSystems開発としてはだいぶ負荷が高い