【Outsystems】Google API連携用の外部モジュールの構成について

# はじめに
Outsystemsを使用したアプリケーション開発ではモジュールという一つの機能単位を基準にアプリケーションの構成を設計していく。
また各モジュールに機能を分化させ依存関係や開発の単位を考える際、Outsystemsが推奨するアーキテクチャ設計の考え方がある。
参考：[【Outsystems】モジュール・アーキテクチャ設計について](https://qiita.com/naitoyuma/items/212f6ea915d61b2ffbd5)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/244af690-acca-ea1b-7ca2-b37da087618d.png)

しかし、この考えに基づきアーキテクチャ設計を行おうとした際、やはり抽象的な話になってくるため何が正解か判断しにくかった。

そこで実際にOutsystems Forgeで提供されているGoogle API連携用コアサービスモジュール、またそれを使用したエンドユーザーモジュールがサンプルアプリの中身を見ながら設計方法の概要を掴みたいと考えた。

# サンプルアプリ:Google Components Demo
Forge：[Google Components Demo](https://www.outsystems.com/forge/component-overview/10274/google-components-demo)
※あらかじめGoogleCloudでAPIを作成しておく必要がある

### 機能の概要
- Google OAuth2.0を使用して認証を行う
- 開発者がGoogle Cloudで作成したAPIのClientID、ClientSecretをエンティティに保持する
- トークンはOutsystemsユーザーに紐づけたトークン用エンティティで保持しSessionのUserIdから取得する
- トークンの認可スコープはcalenderの操作、Driveのデータ取得、SpreadSheetの操作(かなり強力な権限)
- 認証後の各画面でログインユーザーのGoogle Calender、SpreadSheet、共有Driveデータの操作が可能

### アプリケーションとモジュールの依存関係
アプリケーション間の依存性や機能を確認しながら、キャンバスアーキテクチャに分類してみた

- エンドユーザー
Google Components Demoは４つのアプリケーションを参照してエンドユーザーに機能を提供するエンドユーザーサービスに分類した

- ファンデーション
3つのIntegrationサービスはGoogle APIへの各種リクエストを実行するHTTPメソッドを提供するが、モジュール固有のエンティティーなどは持たない。
外部サービスへの連携のためFandationに分類した

- コア
Authentication CoreサービスはGoogle OAuthの対象モジュール、ClientId、ClentSrcet、認可スコープなどの情報をエンティティで保存し、それらの情報に基づきGoogle APIからトークンを取得する。
トークンをシステムユーザーに紐づけてエンティティに保持する事でSessionIdと共に管理しIntegrationの各種機能の使用を認可する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/1df96c16-2a09-e3d2-ce57-608f54f0d490.png)

実際は上記のアプリケーションはそれぞれレイヤーに対応するモジュールを持っている
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/f603ef58-786c-8ac1-c5f1-c7552e54e456.png)

### 特に重要だと思ったポイント
- <b>コアレイヤーのAuthentication Coreモジュールが担当する機能範囲について</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/8bd0852d-7609-e392-1513-1c43effad86b.png)


Authentication CoreはモジュールタイプがReactive Webとなっており、画面UIに関連する機能も担当している。
具体的にはLogin画面に設置されることを想定したボタンUIや認証後、Google APIからのリダイレクトを受けるコールバック画面、またボタンクリック時のClientActionなどを持つ
- GoogleAPIに認証リクエストを送るトリガーボタンとクリック時のロジック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/bd9f0604-0c83-86f7-5cf9-d1a462517949.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/839c2d10-d1ea-aac6-24d3-d7d8b2af808e.png)
上記は認証処理を呼び出すモジュールがどの範囲の認可スコープを設定しているか、ClientSecretや紐づくUserは誰かなどの情報を取得し、GoogleAPIへのリクエストを作成している。


- 認証情報やOutsystemsユーザーなど各種リレーション図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/57a5638e-e5f1-fa39-ced4-f9798825338e.png)
Google APIを利用するための各種認証情報はEntityで管理される


Authentication Coreモジュールの機能は画面UI、ロジック、エンティティーといった役割を持ち、再利用をしない前提であればエンドユーザーモジュールしても十分な機能を担当していると感じた。
デモアプリでは、エンドユーザーモジュールであるGoogleComponentsDemoがこのコアモジュールを呼び出し画面UIの作成やロジックを実行している。

- <b>インテグレーションレイヤーの各種Integrationモジュールが担当する機能範囲について</b>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/1a3f4caa-97c8-607b-a11b-bdb40424b576.png)

上記のモジュールタイプはServiceタイプとなっていて画面UIについては担当していない。

Google APIを利用した外部へのリクエストや、リクエストを組み合わせた任意のアクションを提供する
- Google APIへのリクエスト(エンドポイントにリクエストを送るアクション)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/391c1e4c-37ac-a2b4-a26c-78d7c005c81a.png)
上記はGoogle Calenderを操作するためにGoogle API側が用意しているエンドポイントへのリクエスト

- Google APIへのリクエストを利用して作成した任意のアクション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/5af55173-54c4-9e3e-9348-8ff6ab128de2.png)
上記はGoogle Calender APIへのリクエスト、操作内容を使用したアクション

またGoogle APIの使用にはAuthentication Coreモジュールが管理する認可トークンが必要なため、各種モジュールが行う操作はAuthentication Coreの呼び出しが必要となる

- Google Components DemoモジュールのGetCalenderEventsアクション
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601137/9184579e-b3b7-9f25-6b1e-1a0f96b52f66.png)
上記はGoogleカレンダーの予定を取得するアクション
GoogleAuthenticationCoreモジュールのGetTokenでトークンを取得した後、GoogleCalendar_ISモジュールのGetCalendarEventでGoogleAPIにリクエストを投げている。

- <b>エンドユーザーモジュールが、インテグレーションモジュールを直接参照する事もある</b>

# まとめ
他にも色々気づいた事があったが、今度はこのGoogle連携モジュールを自分のアプリで使用しながらモジュール同士の連携の仕方や機能の分け方について勉強しようと思う。