s平面の左側

左側なので安定してます(制御工学の話は出てきません)

Repository が永続化を担う対象は集約である

この記事について

YYPHP Advent Calendar 2018」14日目の記事。

はじめに

本当は「Repository パターンを使う 2 つのメリット(Laravel における実装例)」というタイトルで記事を書こうとしていた。

記事を書くにあたって Repository パターンの定義を DDD 本(エリック・エヴァンスのドメイン駆動設計)に確認しにいったら私の理解が間違っていたらしいことに気づいた。

そこで今回は、急遽記事の趣旨を変えて「私はどのように理解を間違えていたのか」を書くことにした*1

ただし、今の解釈も正しいか自信がないので、もし間違っていたらツッコみをいただけるととても嬉しい。

これまで私がやっていたこと

前提として、次のような Entity を考えるとする。

User
 - id
 - name
 - profile image

profile image はユーザのプロフィール画像で、画像は開発環境ではローカルに、本番環境では AWS S3 に保存する。

このとき私は Repository は「データの永続化について責務を担う」ということだけを認識していたので「画像の保存もデータの永続化だから Repository を作ろう」と考えた。

結果、UseCase から次のような使い方をするようなコードになった。

<?php

class UserUseCase 
{
    public function detail(int $userId, UserRepository $userRepository, UserProfileImageRepository $userProfileImageRepository)
    {
        // NOTE: $user は User Entity を表すオブジェクト
        $user = $userRepository->findById($userId);
        $user->profileImageUrl = $userProfileImageRepository->getUrlByUserId($userId);

        return $user;
    }
}

$userProfileImageRepository は interface になっていて、画像をローカルに保存する場合と AWS S3 に保存する場合で別の実装になる。

何を間違っていたのか

上記の例では profile image という Value Object に対して UserRofileImageRepository が存在している。

しかし DDD 本を参照したところ、Repository が永続化を担う対象は Entity(より厳密には集約)であるようだ。

つまり、利用する側から見て Repository は UserRepostiory 単一であるべきということになる。

<?php

class UserUseCase 
{
    public function detail(int $userId, UserRepository $userRepository)
    {
        // NOTE: この時点で $user->profileImageUrl に値がセットされている
        $user = $userRepository->findById($userId);

        return $user;
    }
}

感想

改めて定義をきちんと確認することは大切だなあと思った。

このきっかけを与えてくれた YYPHP Advent Calendar 2018 に感謝!

そんな YYPHP Advent Calendar 2018 の明日の担当は YYPHP 主催者のひとり @reoring さん!

*1:その結果 PHP と直接関係無い内容になってしまってごめんなさい。。。