内のエンティティの状態へのアクセス私は:)DDD - リポジトリ
をすれば、私に知らせて、私は良いデザインの経験が不足していると私は以上の事を複雑かもしれないという感じはの例を見てみましょうユーザーエンティティとユーザーリポジトリ
そのPHP(タフでなければなりません:リポジトリ
class UserRepository { public function save(User $user) { if($user->getStatus() == User::STATUS_NEW) $this->getDataAccessObject()->insert($user->getState()); else $this->getDataAccessObject()->update($user->getState()); $user->setStatus(User::STATUS_MANAGED); } }
とコード上のユーザーも自己
class UserEntity { const STATUS_NEW = 1; const STATUS_MANAGED = 2; private $_status = self::STATUS_NEW; private $_state = array(); public static function create($username, $password) { return new UserEntity(array('Username' => $username, 'Password' => $password)); } public function __construct(array $state) { $this->_state = $state; } public function getState() { return $this->_state; } public function getStatus() { return $this->_status; } public function setStatus($status) { $this->_status = $status; } }
ので、いくつかの注意事項、私は質問をする前と 病気開始C++ \ C#\ Java)誰もが理解しやすい
私は省略しますこの例を簡単にするために、基本クラス(抽象リポジトリとUserRepositoryとUserEntityが継承する抽象エンティティのような)を実装しました。
私はファクトリオブジェクト/クラスパターンを放棄しましたが、代わりにエンティティ自体の中にファクトリメソッドパターンを使用することを好みます。
ファクトリメソッドは、この例では冗長に見えると
$ユーザー= UserEntity(配列( 'ユーザ名' => $ユーザ名、 'パスワード' => $パスワード))と置換することができます。
しかし、現実にはその工場は、(例えばPOSTフォームから)「生」のデータを受け取り、その後、が有効なユーザーエンティティをを作成するために必要なすべてのエンティティやバリューオブジェクトを作成しますので、より複雑なビット(そうエンティティ内のパスワードは実際のパスワードではなく、パスワードではなくパスワードのハッシュを含む値オブジェクトです。今の質問に
:
私は世界に私の私はgetStateをを公開するということで自己()とのsetStatus()メソッドで完了していませんよ。これらのメソッドはリポジトリ内でのみ使用する必要がありますが、公開されているため、エンティティの状態にアクセスしたり、状態を変更したりすることは禁じられていません。繰り返しますが、これ以上のものではありませんが、私はそれが正しいとは感じません。
のみ「ソリューション」私は見つけることは、リポジトリ経由
class Entity {
public static function create($identity, $param1, $param2, Repository $r) {
$state = $r->getNewState($identity, $param1, $param2);
return new Entity($state);
}
private $_state = null;
public function __construct(State $state) {
$this->_state = $state;
}
public function getIdentity() {
$this->_state->getIdentity();
}
}
class Repository {
private $_states = array();
public function getNewState($identity, ...) {
$state = new State($identity, ...);
$this->_states[$identity] = $state;
return $state;
}
public function save(Entity $entity) {
$id = $entity->getIdentity();
//maybe check if such entity is managed by this repository..
if($this->_states[$id]->getStatus() === State::STATUS_NEW)
$this->getDataAccessObject()->insert($this->_states[$id]->toArray());
else
$this->getDataAccessObject()->update($this->_states[$id]->toArray());
$this->_states[$id]->setStatus(State::STATUS_MANAGED);
}
}
class State {
const STATUS_NEW = 1;
const STATUS_MANAGED = 2;
private $_state = array()
private $_identity = 'something';
public function getIdentity() {
return $this->_state[$this->_identity];
}
public function toArray() {
return $this->_state;
}
}
のようなものをすべてを通過させることである私は、エンティティの内部状態を公開していないここので、それは私に、「より正確」に見えるとリポジトリだけがそれについて知っています。
あなたはどう思いますか?エンティティの内部状態が公開されていますか?あるいは、2番目の例は、そのようなシステムを設計するより良い方法でしょうか?あるいはもっと良い方法を知っているかもしれませんか?
ありがとうございました!
非常に興味深いアプローチです!私はDTOについて知りませんでした(私のStateクラスはあなたのDTOに似ています)。 DAOについては、DAOが特定のストレージにアクセスするためのインターフェイスであることを確信していました。リポジトリ。 DDDにはリポジトリが存在する必要があるので、実装にリポジトリがないという事実は完全ではありません。 –
DAOは同様の抽象化を提供していますが、集約を格納するのには適していません。実際には、青い本で伝えられている記憶域を抽象化するための単なる使用可能なパターンです。例:グループを持つことができます。グループは複数のユーザーの集約ルートになります。グループを持続させるためのGroupRepositoryを持つことができ、そのグループは個々のユーザーを永続させるためにユーザーDAOの束を使いました。 DAOは集約で使用すると本当に乱雑になります。 – Tobias
ああ、DDDから離れていくための主なポイントは、ビジネスドメインが、あなたが取り組んでいる特定のインフラストラクチャではなく、デザインを推進すべきだということです。リポジトリ、およびDAOパターンは、インフラストラクチャを抽象化して、ドメインのユビキタス(スペル?)言語を定義し、テクノロジに悩まされることなくその周辺をデザインすることができます。 – Tobias