Open10

ドメインオブジェクトなEntityのライフサイクルってどうやって表現する?【PHP】

@tyamahori@tyamahori

HogeEntityInterface でライフサイクルを問わない共通な何かを設定する?

@tyamahori@tyamahori
  • 新規作成を想定しているので new NewHogeEntity(1 , 2, 3) でしか生成出来ない
  • バリデーションは__construct内部で必須
  • パラメータが増えてきたら、Builderパターンの利用も検討する
  • 識別子は外から渡す? Entityで生成する。。。?
    • 新規生成時に識別子の概念いらなくない?
    • そもそも識別は永続化層での都合だから、ここではいらなくない。。?
<?php

class NewHogeEntity implements HogeEntityInterface
{
    /**
     * @var int
     */
    private static int $basicInteger = 5;

    /**
     * @param int $hoge1
     * @param int $hoge2
     * @param int $hoge3
     * @throws Exception
     */
    public function __construct(
        private int $hoge1,
        private int $hoge2,
        private int $hoge3
    ) {
        $this->validateParameter($hoge1);
        $this->validateParameter($hoge2);
        $this->validateParameter($hoge3);
    }

    /**
     * @param int $hoge
     * @throws Exception
     */
    private function validateParameter(int $hoge): void
    {
        $randomInteger = random_int(1, 10);
        if (self::$basicInteger < $randomInteger) {
            throw new InvalidArgumentException($hoge);
        }
    }

    /**
     * @return int
     */
    public function getHoge1(): int
    {
        return $this->hoge1;
    }

    /**
     * @return int
     */
    public function getHoge2(): int
    {
        return $this->hoge2;
    }

    /**
     * @return int
     */
    public function getHoge3(): int
    {
        return $this->hoge3;
    }
}
@tyamahori@tyamahori
  • DBとかの永続化層から生成するためにつかう
  • constructではバリデーションは行わないなぜなら、ここで行ってしまうと、DBにデータがあるにも関わらず、Entityが生成出来ないから。。
  • 識別子は必須。更新後の永続化で絶対に迷子になる。。
    • たとえば永続仮想の都合でupdateするのが、delete insertするのか。識別子があればどちらでも対応はできる
  • setterメソッドでバリデーションをする。DBからデータを取得したときではなく、データを変更する際に何かしらの仕様を強制できるから。
  • updateHoge()とか、データを更新、変更するという意図が伝わるような命名がいいかも
    • そもそもミューターブル。イミュータブルにする意味ナッシング。。。
    • idを更新、変更する意味はない。。
<?php

class ReconstructHogeEntity implements HogeEntityInterface
{
    /**
     * @var int
     */
    private static int $basicInteger = 5;

    /**
     * @param int $id
     * @param int $hoge1
     * @param int $hoge2
     * @param int $hoge3
     */
    public function __construct(
        private int $id,
        private int $hoge1,
        private int $hoge2,
        private int $hoge3
    ) {
    }

    /**
     * @throws Exception
     */
    private function validateParameter(int $hoge): void
    {
        $randomInteger = random_int(1, 10);
        if (self::$basicInteger < $randomInteger) {
            throw new InvalidArgumentException($hoge);
        }
    }

    /**
     * @param int $hoge1
     * @return ReconstructHogeEntity
     * @throws Exception
     */
    public function setHoge1(int $hoge1): ReconstructHogeEntity
    {
        $this->validateParameter($hoge1);
        $this->hoge1 = $hoge1;

        return $this;
    }

    /**
     * @param int $hoge2
     * @return ReconstructHogeEntity
     * @throws Exception
     */
    public function setHoge2(int $hoge2): ReconstructHogeEntity
    {
        $this->validateParameter($hoge2);
        $this->hoge2 = $hoge2;

        return $this;
    }

    /**
     * @param int $hoge3
     * @return ReconstructHogeEntity
     * @throws Exception
     */
    public function setHoge3(int $hoge3): ReconstructHogeEntity
    {
        $this->validateParameter($hoge3);
        $this->hoge3 = $hoge3;

        return $this;
    }

    /**
     * @return int
     */
    public function getId(): int
    {
        return $this->id;
    }

    /**
     * @return int
     */
    public function getHoge1(): int
    {
        return $this->hoge1;
    }

    /**
     * @return int
     */
    public function getHoge2(): int
    {
        return $this->hoge2;
    }

    /**
     * @return int
     */
    public function getHoge3(): int
    {
        return $this->hoge3;
    }
}
@tyamahori@tyamahori

最後は、DeleteHogeEntity

  • 普通にIDをしてして消せばいいと思っていた。
  • いや。。削除条件とかあるやん。。。
  • Entityとしてつくるか。。
  • new DeleteHogeEntity が生成されたときは削除条件は満たしている
    • ただ、よくある例で、ある利用者が削除できるのは自分が作ったデータのみの場合はどうするか。。
    • 削除しようとするIDと削除できるIDをEntityに含める?
@tyamahori@tyamahori

repository に メソッドをはやして、 findEntityToBeDeleted(SomeDto $dto): DeleteHogeEntity にして、返り値を Entity にすれば良さそう。

そして、delete(DeleteHogeEntity $entity) にすれば行けそうだな

@tyamahori@tyamahori

永続層の検索では動作主を識別するID, 削除対象の識別IDを使って検索し、それとは別に削除条件をまとめたやつを含めてDeleteHogeEntityを返せば良さそう?

DeleteEntityに削除条件を渡して、constructorで削除条件のバリデーションを行う。Entityが生成できたら削除できるものとして扱って、削除処理を行うとかよさそう