質問: 現在、SpringBootでAPIを作っており、3層モデル(Application, Domain, Infrastructure)で設計しています。 その中で参考にしたアーキテクチャ図が以下のNTTDataのTERASOLUNAのものです。 ![![TERASOLUNA](https://teratail-v2.storage.googleapis.com/uploads/contributed_images/6bb2ac3483392488609b08fda4dad0ec.png) ここで質問したいのが、Contoroller側で複数のServiceを呼びたい時の呼び方についてです。 Controller側は1つのServiceを呼び、そこから他のServiceを呼ぶのか、 Controller側で必要な複数のServiceを呼ぶのか。 どちらが良いのかわかりませんでした。 例えば、複数のServiceを使用する場合に、AService、BServiceがあったとして、 AServiceの処理結果をBServiceで用いる場合は、 前者の場合は、ASeviceの処理の中で、BServiceを呼び、その2つの処理の結果を呼び出し元に返す。 後者の場合は、ASeviceの処理結果を呼び出し元に返し、その結果をBServiceに渡して、BServiceの結果を受け取り、この2つの処理の結果を呼び出し元で結合する。 となるイメージです。 私的には、前者の方がしっくりきます。なぜかというとContoroller側ではなるべくロジックをもたせたくないからです。 後者の場合、結果の抽出や結合のロジックがApplication層に入るので、設計的にどうなんだろうとふわっとした疑問があります。 それともにその結合や抽出などのデータ処理を、このアーキテクチャ図でいうHelper逃して、 後者で実装するべきなのでしょうか? ご意見を伺いたいです。
回答: > > Controller側は1つのServiceを呼び、そこから他のServiceを呼ぶのか、 > > Controller側で必要な複数のServiceを呼ぶのか。 > > どちらが良いのかわかりませんでした。 > > > こちらについて制限はありません。 (アプリケーションを設計・実装する際の規約になることはあります。) なお、実際にServiceクラスから別のServiceクラスを呼び出すことはあり得ます。ServiceクラスはWebアプリケーションから呼び出されることだけを想定したクラスにしないことが指針です。 1Controllerから常に1つのServiceしか呼び出さない(呼び出せない)作りはControllerの実装が簡潔になりますが、Controllerから呼び出されるServiceクラスの責務が重くなります。わかりやすい事例では、Serviceから別のクラスを呼び出す関係性や制御を担うことになり、メソッドや引数のパターンが増える懸念があります。ただしトランザクション境界をController-Service間へ画一的に設計できる楽な面があるでしょう。 1Controllerから複数のServiceを呼び出す場合はServiceクラスの責務は軽くなり、Serviceクラスを呼び出す順序はControllerによって制御されます。一見こちらが良さそうに思えますが、トランザクション境界を`@Controller`に置くか、特定の`@Service`に置くかを検討しなければならないでしょう。 WebアプリケーションないしはWebAPIとして提供する場合、ServiceクラスはWebのレスポンス内容に依存した結果を返さない想定であるため、Terasolunaの実装例ではHelperが用意されています。 これをViewModelなどの出力用クラスに置き換える設計指針もあります。(個人的には、Helperという名前がやや曖昧にも感じます。)