J'ai lu sur DDD depuis des jours et j'ai besoin d'aide avec cet exemple de conception. Toutes les règles de DDD me rendent très confus quant à la façon dont je suis censé construire quoi que ce soit lorsque les objets de domaine ne sont pas autorisés à montrer des méthodes à la couche application; où d'autre pour orchestrer le comportement? Les référentiels ne sont pas autorisés à être injectés dans des entités et les entités elles-mêmes doivent donc travailler sur l'état. Une entité doit alors connaître autre chose du domaine, mais les autres objets d'entité ne sont pas autorisés à être injectés non plus? Certaines de ces choses ont du sens pour moi, mais d'autres non. Je n'ai pas encore trouvé de bons exemples de la façon de construire une fonctionnalité entière car chaque exemple concerne les commandes et les produits, répétant les autres exemples encore et encore. J'apprends mieux en lisant des exemples et j'ai essayé de créer une fonctionnalité en utilisant les informations que j'ai obtenues sur DDD jusqu'à présent.
J'ai besoin de votre aide pour signaler ce que je fais mal et comment y remédier, de préférence avec du code car "je ne recommanderais pas de faire X et Y" est très difficile à comprendre dans un contexte où tout est déjà défini vaguement. Si je ne peux pas injecter une entité dans une autre, il serait plus facile de voir comment le faire correctement.
Dans mon exemple, il y a des utilisateurs et des modérateurs. Un modérateur peut interdire les utilisateurs, mais avec une règle commerciale: seulement 3 par jour. J'ai tenté de mettre en place un diagramme de classes pour montrer les relations (code ci-dessous):
interface iUser
{
public function getUserId();
public function getUsername();
}
class User implements iUser
{
protected $_id;
protected $_username;
public function __construct(UserId $user_id, Username $username)
{
$this->_id = $user_id;
$this->_username = $username;
}
public function getUserId()
{
return $this->_id;
}
public function getUsername()
{
return $this->_username;
}
}
class Moderator extends User
{
protected $_ban_count;
protected $_last_ban_date;
public function __construct(UserBanCount $ban_count, SimpleDate $last_ban_date)
{
$this->_ban_count = $ban_count;
$this->_last_ban_date = $last_ban_date;
}
public function banUser(iUser &$user, iBannedUser &$banned_user)
{
if (! $this->_isAllowedToBan()) {
throw new DomainException('You are not allowed to ban more users today.');
}
if (date('d.m.Y') != $this->_last_ban_date->getValue()) {
$this->_ban_count = 0;
}
$this->_ban_count++;
$date_banned = date('d.m.Y');
$expiration_date = date('d.m.Y', strtotime('+1 week'));
$banned_user->add($user->getUserId(), new SimpleDate($date_banned), new SimpleDate($expiration_date));
}
protected function _isAllowedToBan()
{
if ($this->_ban_count >= 3 AND date('d.m.Y') == $this->_last_ban_date->getValue()) {
return false;
}
return true;
}
}
interface iBannedUser
{
public function add(UserId $user_id, SimpleDate $date_banned, SimpleDate $expiration_date);
public function remove();
}
class BannedUser implements iBannedUser
{
protected $_user_id;
protected $_date_banned;
protected $_expiration_date;
public function __construct(UserId $user_id, SimpleDate $date_banned, SimpleDate $expiration_date)
{
$this->_user_id = $user_id;
$this->_date_banned = $date_banned;
$this->_expiration_date = $expiration_date;
}
public function add(UserId $user_id, SimpleDate $date_banned, SimpleDate $expiration_date)
{
$this->_user_id = $user_id;
$this->_date_banned = $date_banned;
$this->_expiration_date = $expiration_date;
}
public function remove()
{
$this->_user_id = '';
$this->_date_banned = '';
$this->_expiration_date = '';
}
}
// Gathers objects
$user_repo = new UserRepository();
$evil_user = $user_repo->findById(123);
$moderator_repo = new ModeratorRepository();
$moderator = $moderator_repo->findById(1337);
$banned_user_factory = new BannedUserFactory();
$banned_user = $banned_user_factory->build();
// Performs ban
$moderator->banUser($evil_user, $banned_user);
// Saves objects to database
$user_repo->store($evil_user);
$moderator_repo->store($moderator);
$banned_user_repo = new BannedUserRepository();
$banned_user_repo->store($banned_user);
Le droit d'utilisateur doit-il avoir un 'is_banned'
champ qui peut être vérifié avec $user->isBanned();
? Comment supprimer une interdiction? Je n'ai aucune idée.