48748


DDDでエンティティをORM（例えばPHPのLaravel（Eloquent））を利用して永続化する際、リポジトリの実装の中でエンティティをORM固有のオブジェクトに詰め替える必要があるように思うのですが、つまりエンティティにはgetterが必須ということになるのでしょうか？

[code]

    function persist($itemEntity) {
        $item = new Item(); // ORMのオブジェクト
    
        $item->id = $itemEntity->getId()->value();
        $item->name = $itemEntity->getName()->value();
    
        $item->save();
    }
    
[/code]

PHPでDDDの実装サンプルを見ると皆このようになっています。  
が、IDDD本のサンプルコードを見る限り永続化メソッドにgetterは登場していないように見えます。（但しJavaはよく分かっていないのでコードの意味が理解出来ていないだけかもしれません。）

Viewに渡すようなクエリ系はCQSのクエリサービス+DTOの構造にして、getterの役割はDTO側に実装しつつ、コマンド側に徹するエンティティからはgetterを取り除いてより閉じた状態にしたいと考えたのですが。


CC BY-SA 4.0
2018-09-26T23:57:10.363
48745
2018-09-27T00:51:15.800
28206
question
ドメイン駆動設計
ドメイン駆動設計のエンティティにgetterは必須でしょうか


getterは必須ではありません。  
ちょっと手間ですが、私は「リポジトリでカプセル化を破るためのインタフェース」を使うことがよくあります。  
※多分何かのデザインパターンとして名前があったと思いますが、分からないです

PHPが分からないのでJavaで書きます。

[code]

    // Hogeエンティティ
    // ドメインモデルなので当然ドメインレイヤーに配置
    public class Hoge {
        // IDはずっと変化しない
        // ドメイン上ではgetterが不要だが、永続化の際に取り出せる必要がある
        private final int id;
    
        // 名前は変更することがある
        private String name;
    
        public Hoge(int id, String name) {
            this.id = id;
            this.name = name;
        }
    
        public String name() {
            return this.name;
        }
    
        public void rename(String newName) {
            this.name = newName;
        }
    
        public void deencapsulate(HogeDeencapsulator deencap) {
            deencap.setId(this.id);
            deencap.setName(this.name);
        }
    }
    
    // Hogeのカプセル化を破るためのインタフェース
    // これはドメインレイヤーに配置
    public interface HogeDeencapsulator {
        void setId();
        void setName();
    }
    
    // HogeDeencapsulatorの実装クラス
    // これはリポジトリの実装と同じインフラレイヤーに配置
    public class HogeDeencapsulatorImpl implements HogeDeencapsulator{
        private int id;
        private String name;
    
        public int getId() {
            return this.id;
        }
    
        @Override
        public void setId(int id) {
            this.id = id;
        }
    
        public String getName() {
            return this.name;
        }
    
        @Override
        public void setName(String name) {
            this.name = name;
        }
    }
    
[/code]

ここまで用意すれば、リポジトリの実装では次のようにしてHogeのidを取り出せます。

[code]

    public void save(Hoge hoge) {
        HogeDeencapsulatorImpl hogeDeencap = new HogeDeencapsulatorImpl();
        hoge.deencapsulate(hogeDeencap);
    
        int id = hogeDeencap.getId();
        String name = hogeDeencap.getName();
        ...
    }
    
[/code]

どうしてもカプセル化を維持したい場合に使ってます。  
列挙型（enum）を持ってるけど、ドメインとしてのインタフェースは「isなんちゃら」のメソッドしか公開したくない場合とかも。  
面倒なときは普通にgetter付けちゃいますが。


CC BY-SA 4.0
2018-09-27T00:51:15.800
48748
2018-09-27T00:51:15.800
8078
48745
answer