この記事はハワイアンAdvent Calendar 2020 22日目の記事です。残り少なくなってきました。
DDDでのDomain ServiceというのはGRASP(General Responsibility Assignment Software Pattern)原則で示されている9つのパターンのうちの1つの人工品(Pure Fabrication)です。
GRASPの視点で見ると、デザインパターンもほとんどが人工品です。人工品という単語だけではFabricationになりますが、人工品の理想として、高凝集性と疎結合性を満たす純粋な設計である事が期待される(エンティティや値オブジェクトからは外れるものを敢えて作ったのに責務も不明瞭なのはどう考えてもまずいですよね)ので、Pureという修飾がついており、日本語訳でも純粋人工品としばし言われます。雑学はおいといて、人工品の多くはDomain Serviceとは言い難い所があります。それは「どこから生まれたのか」に違いがあるためです。
Domain ServiceとApplication Serviceはしばし混同されるので、例にあげてみます。Railsデザインパターンで語られているForm ObjectはApplication Serviceです。Domain Serviceは馴染み深い例?で言うとRepositoryです。Form Objectはユーザの入力のAnti-corruputionというような「アプリケーション層を中心に導き出した人工品」です。Repositoryはドメインモデルの中長期のライフサイクルを担う「ドメインモデルを中心に導き出した人工品」です。ドメインモデル、ひいては集約がまだない状態で先にRepositoryについて考えていたら、それはRepositoryという名前であってもDomain Serviceではないです。なんとなく分かってもらえたでしょうか。次に、混同する事の何がいけないのかという話をします。
ドメインモデリングについて改めて振り返ると、本来ドメインというのはどこにでもあるものなのでビジネスだろうがUIだろうがアプリケーションだろうが同じようにモデリングに立ち向かうものです。アプリケーション層でドメインモデリングをするというのは、アプリケーションとはなんなのか、という所を洞察していく事になります。その行為に価値があるかといえば…まあフレームワークに近いのでチームによっては生産性に寄与する…など一概に言い切れない所がありますが、フレームワークは薄い事に越した事はないと思っています。「最強のフレームワークはソースコード0byte」というプレゼンが昔あったんですが、参照先を失ってしまいました…。あれを肝に命じて生き続けています。
要するに観点が全然違うんですよね。Application Serviceをビジネス層の人工品だと勘違いしたままアプリケーション層に本来不必要な概念を掘り下げていってしまう現象というのが近年のソフトウェア開発において見かける事があり、これはまずいなと思いながら書いている訳です。じゃあどうしたら良いのか、何が足りないのか。現代のアプリケーション開発は進化可能性について検討する必要があるという観点から洞察すると、アプリケーション層でこれまで提案されてきた多くのデザインパターンは進化可能性について特に考慮がなく、そもそも高凝集性や疎結合性を満たしていないものも多々あるので、その辺に対するルールを付与した上で導入を検討するのが良い、という話になります。Scalable Contractも是非読んでください。
3層モデルの説明でドメイン層なんていい方をしてしまったのが多分ミスリードだったんじゃないかなと思うのですがそれはもう仕方がないとして、Domain ServiceとApplication Serviceの混同は中長期的に技術的な負債を生む上にそこを発展させる事にビジネス価値がない可能性すらあるので、しっかり区別し、それぞれのドメインにあった観点で育てていきましょう。もう書いちゃったのであれですが、ドメインモデルやDomain Serviceという表現も良くないのかもですね。Business Domain Modelとか、Business Serviceとかのが良いんじゃないですかね。