6

Zone私はオブジェクトのツリーを持っています:

class Zone {
    protected $parent;

    public function __construct(Zone $parent) {
        $this->parent = $parent;
    }
}

ドメイン モデルでこれらの関係を管理する手間を省きたいので、Zone にはプロパティもプロパティもありません。 childrendescendants

代わりに、ドメイン サービスは、データベース内にクロージャ テーブルを保持し、任意のレベルでゾーンをそのすべての子孫にマップします。

これで、User1 つまたは複数のゾーンを割り当てることができる があります。

class User {
    protected $zones;

    public function assignZone(Zone $zone) {
        $this->zones[] = $zone;
    }
}

私の問題は、新しいゾーンをユーザーに割り当てる前に、このゾーンがまだ割り当てられていないことを、その子孫のいずれかを介して明示的または暗黙的に確認したいということです。

したがって、必要なチェックを実行するために、コントローラーで Service をこのメソッドに一時的に挿入する必要があります。

class User {
    protected $zones;

    public function assignZone(Zone $newZone, ZoneService $zoneService) {
        foreach ($this->zones as $zone) {
            if ($service->zoneHasDescendant($zone, $newZone)) {
                throw new Exception('The user is already assigned this zone');
            }
        }

        $this->zones[] = $zone;
    }
}

それは良い習慣ですか、そうでない場合、正しい代替手段は何ですか?

4

1 に答える 1

4

ドメインモデルでこれらの関係を管理する手間を省きたいので、Zone には子プロパティも子孫プロパティもありません。

代わりに、ドメイン サービスはデータベース内にクロージャ テーブルを維持し、ゾーンをそのすべての子孫に任意のレベルでマップします。

少し矛盾しているように見えるので、強調を加えました。ドメインの「苦痛」は必要ありませんが、ドメイン サービスでクロージャ テーブルを管理します。エンティティにサービスを注入する必要があるという事実は、設計を改善できることを示している場合があります。

ゾーンの階層があるようです。これはドメインの重要な部分のようです。ゾーンには親と子孫があるため、それに応じてモデル化する必要があります。モデルの表現力のためにそれを行うため、関係を管理する苦痛は「正当な」苦痛です。この場合、ドメインが設計を推進します。したがって、ゾーン自体は次のようになります。

zone->hasDescendant($newZone)

また、サービスを注入する必要はありません。実際、サービスはまったく必要ありません。このサービスの唯一の理由は、クロージャ テーブルを維持するためです。これはドメインの問題ではなく、単なる持続性の問題です。

なんらかの理由でまだサービスが必要な場合は、それを Zone クラスに注入することをお勧めします。このようにして、問題はその原因の近くで解決されます。

于 2011-09-19T19:47:50.853 に答える