読書メモ:ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本 2

DDD自体が複雑な概念なので、その用語とパターンに集中して解説する入門書のメモの2回目。

Chapter5 データにまつわる処理を分離する「リポジトリ」

エンティティから、データストアを直接操作してデータを永続化する処理を切り離す先がリポジトリ。

切り離す事によって、エンティティにはドメインの概念を表すコードのみが含まれるようになる。

OutSystemsにマッピングするなら、背後にいるデータストアが、

  • DB → Entity (これはそのまま)。この場合、Core Entity PatternのAction部分が本来のDDDにおける「ドメインサービス」または「エンティティ」ということになるか
  • 外部サービス → Integration Pattern (連携パターン)[1]コアサービスを抽象化するための連携パターン というアーキテクチャパターンがある。その連携サービスがリポジトリに、コアサービスがエンティティ・値オブジェクト・ドメインサービスに当たると思われる

Chapter6 ユースケースを実現する「アプリケーションサービス」

アプリケーションサービスは、ドメインオブジェクトを操作して、直接ユーザーの要求事項を満たす機能を提供する。

ドメインサービスと同じく、サービス(呼ぶ側に何らかの機能を提供するソフトウェア)だが、アプリケーションサービスはドメインオブジェクトではない。

そのため、ドメイン内の知識をアプリケーションサービスに直接含まない(ドメインサービス等ドメインオブジェクトを経由して操作する)ように気をつける。

さて、上記説明を考慮すると、OutSystemsでは、End-Userレイヤーのモジュールとその内部の要素がちょうど対応しそうに見える。End-Userレイヤーのモジュールは、CoreやFoundationレイヤーの機能を利用してユーザーの要求を直接叶える機能を実装する場所であるため。

ちなみに、

アプリケーションサービスが振る舞いの戻り値としてドメインオブジェクトを返した場合、

アプリケーションサービス以外のオブジェクトがドメインオブジェクトの直接のクライアントとなって自由に操作できてしまうということです。(PAGE 196)

とある。その場合、返されたドメインオブジェクトを利用するコードがドメイン外のあちこちにできてしまうという問題がある。

OutSystemsの場合、ちょっと面白いところがあって、Entityを(Expose Read Only=Yesで)ドメイン外に公開しても、

  • 更新はできない(Expose Read Only=Yesなので)
  • Entity自体には(Entity Action以外の)振る舞いが含まれない
  • 検索系処理には便利にAggregateが使える

という点。OutSystemsのマイクロサービスやDDD関係ドキュメントでも、ドメイン間でService Actionの他にQuery ModelとしてEntityを公開するのは想定されている。

Chapter7 柔軟性をもたらす依存関係のコントロール

例えば、アプリケーションサービスAとレポジトリBがあるとき、通常は(AがBを利用するので)

A -> B

の方向で依存が発生する。

これだと、より上位レイヤーのAが下位のBに依存しており、Bの何らかの変更がAに波及する可能性がある。上位のレイヤーの方がより重要なので、下位のレイヤーへの依存度を減らしたい。

そこで、

Bの手前に (OOPLの)interfaceを定義すると

A -> interface <- B

という依存関係になる(Bから伸びている矢印はinterfaceの実装)。

interfaceの仕様は利用側であるAの都合で決まるので、この実装方法を、依存関係逆転の原則(Dependency Inversion Principle)という。

さて、この関係をOutSystemsで表現するのはちょっと難しい。なにしろinterfaceがない(OOPLではないため仕方がない)。

依存関係逆転の原則の定義は

A. 上位レベルのモジュールは下位レベルのモジュールに依存してはならない、どちらのモジュールも抽象に依存すべきである。

B. 抽象は、実装の詳細に依存してはならない。実装の詳細が抽象に依存すべきである。(PAGE 256)

ということなので、少なくともこのままOutSystemsに実装できるような「抽象」に対応する要素がない。

また、この章の後半で出てくるDIみたいなこともOutSystemsではできない。テストのためにデータストアを切り替えたりできないのもOutSystemsで困るポイントの一つ。

Chapter8 ソフトウェアを組み立てる

ここまで作り上げてきたドメインオブジェクトとサービスを利用するユーザーインターフェースを作る章。

同じドメインサービスを利用する複数のユーザーインターフェース(コマンドライン、MVC、微妙だがユニットテスト)を作ってみせる、という内容になっている。

それ自体については特にコメントないが、

アプリケーションにとってユーザーインターフェイスは交換可能なものです。(PAGE 312)

の部分と、それに続く、ASP.NET FormsをASP.NET MVCに乗り換える部分は、OutSystemsでも似たようなことが過去に発生した。

OutSystems10、及び11の途中まではOutSystemsで作る画面は背後にASP.NET Formsを基盤とするTraditional Webであったが、その後Reactive Web Appが発表され、主流はそちらになった。

UI部分はほぼ別物になったわけだが、背後のサーバーサイドのロジックは実はそのまま利用可能であったため、当初からOutSystemsのベストプラクティスに従ってUIとビジネスロジックを分離していたならば、既存ロジックを比較的低コストで載せ替え可能であった。

DDDに従ってドメインオブジェクトをきちんと作ることは同様のメリットをもたらしてくれるのだろう。