OutSystemsのDDD情報まとめ

Eric Evansの有名な本『Domain-Driven Design: Tackling Complexity in the Heart of Software』で示された、ドメイン駆動設計（Domain Driven Design。以下DDD）。
OutSystemsの公式ドキュメントで、OutSystemsで作成するソフトウェアにDDDを適用する方法が説明されています。

# 更新履歴
2022/1/26 Bounded Contextについて追記 (実プロジェクトへの適用（私見）内に）

# DDDとは
OutSystemsのドキュメント、[ドメイン駆動設計](https://success.outsystems.com/ja-jp/Documentation/Best_Practices/Architecture/OutSystems_Domain_Driven_architecture/Domain_Driven_Design)の記述を引用します。

まずはドメインの意味。
> ドメインは、ソフトウェアで解決する必要があるビジネス上の問題の境界です。

OutSystemsにおけるドメインには、以下の分類がある

- Orchestrator：昔の4LCにおける同名レイヤーと同じく複数の機能のポータルとなるドメイン
- Vertical：ソフトウェアで解決しようとする業務に対応するドメイン
- Horizontal：複数のVerticalドメインで共有する再利用できる機能を持つドメイン

ソフトウェアをこのドメインと調和させる方法がDDDですが、ドキュメントでは以下のように書かれています。
> ドメイン駆動設計（DDD）は、進化し続けるコアビジネスロジックのモデルで複雑なソフトウェアを、接続された小さな要素に変換して開発しやすくする手法です。これは、複雑なシステムを開発するための手法とプロセスに対する解決策になります。

# 前提知識：OutSystemsのマイクロサービス
OutSystemsで作成するソフトウェアは、いかにソフトウェアアーキテクチャ上の工夫をしようとも、根っこの部分（サーバーソフトウェア等基盤部分）ではつながってしまっています（ただし、最近発表されたProject Neoは別）。

その前提の上で、OutSystemsでマイクロサービスと言えば、概ね「Service Action」のことを指します。
Service ActionはServer ActionとExpose REST APIの中間の位置づけで、
- 実行時にはHTTP通信がConsumerからProducerに送られる（RESTと同じ）
- トランザクションは別になる
- ログイン情報は使える
- OutSystemsによる各種チェック（PublishやLifeTimeによるリリース時の整合性チェック）は働く

というもの。
Service Actionを呼べるのは同じOutSystems環境だけです。
マイクロサービスが必要になった時点で、そのI/FはService Actionにします。

マイクロサービスにするといいのは、CI/CDへの親和性が高いことと、モジュールの独立性が上がりPublishやリリースのインパクトが下がること。逆にマイクロサービスにしない通常の作り方のほうがロジックそのものがシンプルになり、開発速度も上がる、ということが動画（記事末尾にリンク）スライドに書かれていました。

# OutSystemsのドメイン駆動設計方法の骨格
公式ドキュメント：[OutSystemsを使用したドメイン駆動設計](https://success.outsystems.com/ja-jp/Documentation/Best_Practices/Architecture/OutSystems_Domain_Driven_architecture/Domain_Driven_Design_with_OutSystems)から手順をまとめ。

1. システム化対象業務を知る。分割するのに適切な基準[^1]を決定する
1. 定めた基準に従って対象業務を分割する。適切な粒度[^2]に分割できるまで、新たな基準を見つけて分割を繰り返す
1. 十分に分割できたら、その結果の1つ1つがドメイン。ドメインをLifeTimeのTeamに割り当てる（＝ドメインに対応するTeamを作る、Teamはそのまま開発者のチームでもある）
1. ドメインごとにマイクロサービス（OutSystems概念での）として構成する
    - ドメイン内の各アプリケーション／モジュールは、通常のOutSystems開発。強い参照関係
    - ドメイン間で参照する場合は、弱い参照関係にする[^3]
    - 上記制約を考慮しつつ、ドメインに分割後は通常のArchitecture Canvasに従ってアーキテクチャ設計を行う

[^1]: 例としてあげられているのは、会社の部門（Line of Business）やその他の機能基準（Other functional criteria)くらい。詳細な情報はないので、担当者のドメイン知識／経験ベースになると思われる。あるいはオリジナルのドメイン駆動設計の本を読むか
[^2]: どのくらいが適切な粒度であるかの基準は示されていないが、LifeTimeのTeamに割り当てるため、Teamとして管理しやすいくらい、というなんとなくの基準は思いつく
[^3]: Service ActionまたはQuery Modelとされているが、Query Modelをどうやって実現するかは明記されていない。恐らく、サマリや一覧情報は必要な情報のみに絞ったList of Structureを返すAction (Server/Service) で、詳細情報取得と更新系はService Actionか。なお、Horizontalドメインを参照対象とする場合は例外としてI/Fに使える要素の制約がゆるくなる

# Discovery (Forge)
DDDに対応するため、ForgeにあるDiscoveryが変更されていました（恐らく2018年ごろから？）。
DiscoveryはOutSystems環境内のアプリケーション／モジュールのアーキテクチャを、グラフィカルに分析／改善していくためのツールですが、Domainsというメニューが追加されていました。

デフォルトでは表示されません。
表示するには、メニューのConfiguration/General Configurationsで開くページでUse DomainsのチェックボックスをオンにするとTrueになり、Domainsメニューが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/6e72e2f2-b948-e261-bd9d-d1cf60787816.png)

（この設定値は、DiscoveryProbeモジュールのGetUseDomainValueというActionで取得している）

このときLifeTimeの環境ホスト名と認証情報が必要。どうもLifeTimeのTeamからドメインが作れそうですが、Personal Environmentではこの辺り触れないため、動作確認はできませんでした。

Domainは
・手動追加
・LifeTimeのおそらくTeamから追加
のパターンがあり、後者が本来のここまで見てきたOutSystemsのDDDで設計する対象ですね。

# 実プロジェクトへの適用（私見）
OutSystemsにおけるDDDの出番は、
・ドメインを認識してLifeTimeのTeamに割り当て
・ドメイン内の参照は強い参照で良い（モノリス）
・ドメイン間の参照は弱い参照にする（マイクロサービス）
という構造における「ドメイン」を認識するため、という理解です。

なので、DDDではLifeTimeのTeamまでを設計の対象とし、その内部はArchitecture Canvasに従って設計ということになるはず。ドキュメントではサブドメインがApplication、サブドメイン内の概念がModuleに対応することになっていますが、Domainの枠内のものはArchitecture Canvasで設計していくことにしたほうがわかりやすそうな気がしています。

:::note info
2022/01/26追記
ドメイン内で複数のサブドメインをまとめたシステム上の区切りであるBounded Contextの単位でArchitecture Canvasを使った設計をすると収まりが良さそうな気がしています。
:::

このドメインを導き出すために、「どの基準でシステム化対象業務を分割するか」「ヒアリングやフィードバックで出てきた新しい事実をどうドメインに反映させるか」を判断する業務知識とモデリングスキルが必要ですね。ドキュメントでも強調されていますが、そうした専門家が必要です。

> 「ドメイン専門家」とも呼ばれるスペシャリストを加える必要があります。ドメイン専門家は、知識を移転し、ドメインを強化して、その理解を促すスタッフです。また、ドメインのモデル化も支援します

また、ドメインはモデルは徐々に磨いていくもので、ドメインに何らかの変更があるなら影響が大きいので、CIでガードする事が必要になりそうです。CIについて、コードをレポジトリ内で統合するところまでは、OutSystemsでは強制適用ですが、自動テストを作って走らせる部分は開発チームで用意しないといけないですね。

# 参考動画
ODC 2018: [Domains and Services Architecture](https://www.outsystems.com/training/lesson/1696/odc-2018-domains-and-services-architecture)
Course: [Domains and Services Architecture](https://www.outsystems.com/training/courses/150/domains-and-services-architecture/)