[OutSystems]Architecture Canvasを使った設計の骨格

OutSystemsが標準として公開し、推奨しているアーキテクチャ設計手法・図法であるArchitecture Canvasについて、骨格部分をまとめ。

# 前提知識
アーキテクチャ設計を理解するための前提となる用語を整理しておきます。
## Module
- OutSystemsで作るソフトウェアの基本単位で普段開発するときに開発ツールで開いているもの
- eSpace (Service Studioで編集する) とExtension (Integration Studioで編集する）に分かれる

## Application
- Moduleの入れ物
- Service StudioやLifeTimeで作成するもの
- リリースの単位、ITユーザーの権限管理の単位

## Team
- 開発チームに対応する概念
- LifeTime上に作成し、アプリケーションのセットとそのアプリケーションに対して権限を有するITユーザーのセットを登録する
- OutSystemsのDDDで設計したドメインは、Teamに対応する

## 依存関係
あるModule/Applicationが、他のModule/Applicationを参照すること。
参照する側を「Consumer」、される側を「Producer」と呼ぶ。
Consumerをリリースするときに、使用しているバージョンのProducerをリリース済みでないと、同時にリリースする必要がある。
Producerを更新すると、（更新内容にもよるが）Consumerで参照を更新したり再Publishする必要がある。

## 強い依存関係と弱い依存関係
モジュール間の依存関係には強い依存関係と弱い依存関係がある。
強い依存関係があると、Producerの実装とI/Fどっちが変わってもConsumerからの参照が古くなり、再Publishが必要。
それに対して、弱い依存関係しかないモジュール間では、ProducerのI/Fが変わったときのみ再Publishが必要。

強い依存関係の例：Server Action、Client Action、Block
弱い依存関係の例：Service Action、Screen

# アーキテクチャ設計の全体像
1. DDDに従ってドメイン（Team）に分割する
1. 設計手順（Disclose -> Organize -> Assemble) に従って、要求等をモジュール／アプリケーションにまとめ上げる
1. 結果をルールに従って検証し、必要に応じてリファクタリング

# アーキテクチャキャンバス
Module/Applicationを役割によって3つのレイヤーに整理していく設計手法・図法。
3つのレイヤーとは、上から順にEnd User、Core (Business)、Foudation。
## 各レイヤーの意味、代表的な要素
### End User
再利用しない要素を置く。ユーザーの要求を直接実現する要素を配置。
例：画面、再利用しない業務ロジック、Process

### Core
再利用可能な部品で、業務要求に関連するもの。
例：Expose API (REST/SOAP)、業務要求に関わるWidget、業務ロジック

### Foundation
再利用可能な部品で、業務要求に直接関わらないものを配置する。
例：Extension、UI Pattern (OutSystems UIに含まれるWidget等、純粋なUI部品）、Theme

## キャンバスへの配置
業務要求や連携先の外部システムの記述から、概念を抽出し、OutSystemsで構築するシステムの要素としてまとめたものがモジュールになる。

モジュールをさらにまとめるのがアプリケーション。アプリケーションの所属レイヤーは、アプリケーション内の全モジュールで一番上位のレイヤーになる。
例1：アプリケーションAが、End-Userモジュール1・Coreモジュール3・Foundationモジュール1を含む場合、AのレイヤーはEnd-User
例2：アプリケーションBが、Core 1・Foundation3を含む場合、BのレイヤーはCore

# 設計手順
業務要求・ユーザーストーリー・外部制約から、アーキテクチャキャンバスを描くための手順。
以下の3ステップ

1. Disclose：業務要求等から設計対象の概念を抽出する
1. Organize：抽出した概念をArchitecture Canvasに配置する
1. Assemble：配置した概念をまとめ上げてモジュールにする

後の手順で新事実が判明したり、新しい要求が発生すれば、各ステップを繰り返す。
Assembleで考慮すべき基本原則：
- 密接に関係する要素をモジュールにまとめる（関連がないものは別モジュールに分割）
- 複雑すぎるもの、ライフサイクルが異なるもの（開発者が異なるものや、ユーザー部門の異なるもの）は別のモジュールに分割
- 知られているアーキテクチャパターン（OutSystemsのドキュメントに公開されているもの）に寄せる（例：外部システム連携がある場合、外部システムと直接接続するモジュールのIntegration Serviceと、そのI/Fを抽象化するCore Serviceモジュール二分割する。これはExternal Core Serviceパターンと呼ばれる）

# 検証とリファクタリング
設計手順に従ってアーキテクチャキャンバスに配置したモジュール／アプリケーションを「検証」し、問題があれば「リファクタリング」する。
## 検証
不要な依存関係をなくすためのルール。このルールはモジュール間だけでなく、アプリケーション間にも適用される。

1. 上方参照禁止：下位レイヤーのモジュールから上位レイヤーのモジュールを参照するのは禁止。例：CoreからEnd-Userを参照するなど
1. End-Userレイヤー間での参照禁止。ドキュメント上明記はないと思うが、恐らく強い参照のみが禁止で画面の参照は可であると思われる（フォーラムの投稿等から）。例：End-UserモジュールAから別のEnd-UserモジュールBのServer Actionを参照するのは不可
1. 循環参照禁止。例：モジュールAとBが相互のServer Actionを参照し合うようなケース

## リファクタリング
ここでは、アーキテクチャキャンバスのルール違反を、モジュールやアプリケーションの構成を改善することで解消する作業のこと。

推奨される改善順序は

1. End-Userレイヤーへの上方／横参照
1. Coreレイヤー間での直接的な循環参照
1. Coreレイヤーへの上方参照
1. Foundationレイヤー間での直接的な循環参照

影響範囲の大きいものから優先的に解消する。
Entityをリファクタリングで移動する場合、データはついていかない（内部DBの場合）点に注意。

# Ver10経験者向けの注意
Architecture Canvasは、以前4 Layer Canvasと呼ばれていたもの。
OutSystems 11では、参照の強弱の概念が導入され、画面間の参照が許容されるようになった。
それに伴い、複数のモジュール間の画面をまとめる最上位レイヤー（Orchestration）が不要になりレイヤー数が4 -> 3と減り、同時に名前が変更されている。

また最下位レイヤーは改名されてLibrary -> Foundationになった。
これは恐らく、モジュール種別「Library」が導入されたため。

# 参考資料
[OutSystemsのDDD情報まとめ](https://qiita.com/jyunji_watanabe/items/357470b3b632c232ce76)
[強い依存関係と弱い依存関係について理解する](https://success.outsystems.com/ja-jp/Documentation/11/Developing_an_Application/Reuse_and_Refactor/Understand_Strong_and_Weak_Dependencies)
[設計手順：アーキテクチャから開発へ](https://success.outsystems.com/ja-jp/Documentation/Best_Practices/Architecture/From_architecture_to_development)
[検証：アプリケーションアーキテクチャを検証する](https://success.outsystems.com/ja-jp/Support/Enterprise_Customers/Maintenance_and_Operations/Designing_the_Architecture_of_Your_OutSystems_Applications/Validating_your_application_architecture)
[アーキテクチャパターン（英語）：Architecture Patterns in OutSystems](https://www.outsystems.com/training/courses/68/architecture-patterns-in-outsystems/)
[Architecture Dashboardの概要](https://success.outsystems.com/ja-jp/Documentation/11/Managing_the_Applications_Lifecycle/Manage_technical_debt)