Ho letto DDD da giorni e ho bisogno di aiuto con questo esempio di design. Tutte le regole della DDD mi rendono molto confuso su come dovrei costruire qualcosa quando gli oggetti del dominio non sono autorizzati a mostrare metodi al livello dell'applicazione; dove altro per orchestrare il comportamento? I repository non possono essere iniettati in entità e le entità stesse devono quindi lavorare sullo stato. Quindi un'entità deve sapere qualcos'altro dal dominio, ma non è possibile iniettare anche altri oggetti di entità? Alcune di queste cose hanno senso per me, ma alcune no. Devo ancora trovare buoni esempi di come costruire un'intera funzione, dato che ogni esempio riguarda gli ordini e i prodotti, ripetendo gli altri esempi più e più volte. Imparo meglio leggendo esempi e ho cercato di creare una funzione utilizzando le informazioni che ho acquisito riguardo al DDD fino a questo punto.
Ho bisogno del tuo aiuto per sottolineare cosa faccio di sbagliato e come risolverlo, preferibilmente con codice come "Non consiglierei di fare X e Y" è molto difficile da capire in un contesto in cui tutto è solo vagamente definito . Se non riesco a iniettare un'entità in un'altra, sarebbe più facile vedere come farlo correttamente.
Nel mio esempio ci sono utenti e moderatori. Un moderatore può vietare agli utenti, ma con una regola aziendale: solo 3 al giorno. Ho fatto un tentativo di impostare un diagramma di classe per mostrare le relazioni (codice sotto):
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);
Se l'entitity dell'utente ha un campo 'is_banned'
che può essere controllato con $user->isBanned();
? Come rimuovere un divieto? Non ne ho idea.