Closed8

LaravelにおけるServiceとUseCaseの違い

buno15buno15

Laravelの開発ではよくMVCが採用される。自分なりの理解としては以下の感じ。

純粋なMVC

  • Model: 業務ロジックを持つ、DBとのやり取り、データ構造を持つ
  • View: Bladeテンプレートを使用してUIを構成しユーザーとのやり取りを行う
  • Controller: HTTPリクエストを受取り、ModelとViewと連携する
buno15buno15

しかしMVCのみでは各層の責務が肥大化しやすいため、ServiceやRepositoryが追加で実装される。

Service

Modelから業務ロジックを分離する。Modelの役割をDB操作やアプリケーションで使用するデータ構造の管理に専念させる。Serviceには業務ロジックを実装しControllerから呼び出す形にする。

Repository

ModelからDB操作を分離する。DB操作(データアクセス処理)を抽象化し、業務ロジックと永続化を分離させる。

  • 業務ロジックがDB操作の具体的な実装に依存しなくなる
  • 特定の仕組み(Eloquent, QueryBuilder等)に依存する必要がなくなるので、保守性向上
buno15buno15

Serviceに似たものでUseCaseがあるが、これらの役割の違いが分からなかった。と言うより、言葉が違うだけで同じものだと思ってた。厳密な違いを確認しておきたい。

buno15buno15

そもそもService, UseCase, RepositoryはDDD、クリーンアーキテクチャ、デザインパターンの思想であり、Laravelに限ったことではないと思う。DDDやクリーンアーキテクチャの話に広げると長いので、とりあえずServiceとUseCaseの違いについてまとめることにする。

buno15buno15

https://qiita.com/MK32A/items/769e4a059ec4dd2954be
https://zenn.dev/knao124/articles/230809-android-ddd-note
AIに聞いたり、調べた感じの自分なりの解釈としては、

UseCase

  • 単一のユースケース(登録処理、支払い処理...)をカプセル化する
  • 誰が何のためにどういったことをするのか意識した粒度
  • 低い抽象度、再利用性が低い
  • 他のUseCaseと独立した実装になりやすい
  • Controllerと一対一対応
  • 1つのUseCaseクラスが1つの関数をもつ

Service

  • 複数のユースケースでの使用を想定した共通処理でカプセル化する
  • 高い抽象度、再利用性が高い
  • Controllerは複数のServiceを呼び出す
  • 1つのServiceクラスは複数の関数を持つ
buno15buno15

ControllerとServiceの間にUseCaseを入れると、Controllerは責務が明確になりそう。一方でレイヤーを増やすことで実装/保守のコストが上昇することにつながる。

buno15buno15

UseCaseを間に挟むとControllerで手続き的な処理を記述する必要がなくなるのでControllerの肥大化を防げる。

// Service
class UserController {
    function login() {
        $isExist = $userService->isExistAccount();
        if($isExist) {
            $userService->login();
        }
    }
}

// UseCase
class UserController {
    function login() {
        $userLoginUseCase->execute();
    }
}
buno15buno15

ただ大規模なアプリケーションでない限り、UseCaseは必要以上なレイヤーだと思う。

このスクラップは16日前にクローズされました