Per semplificare, supponiamo che un'applicazione abbia Accounts
e Users
. Ogni account può avere un numero qualsiasi di utenti. Ci sono anche 3 consumatori di UserRepository
:
- Un'interfaccia di amministrazione che può elencare tutti gli utenti
- Front-end pubblico che può elencare tutti gli utenti
- Un'API autenticata dall'account che dovrebbe elencare solo i propri utenti
Supponendo che UserRepository
è qualcosa del tipo:
class UsersRepository extends DatabaseAbstraction {
private function query() {
return $this->database()->select('users.*');
}
public function getAll() {
return $this->query()->exec();
}
// IMPORTANT:
// Tons of other methods for searching, filtering,
// joining of other tables, ordering and such...
}
Tenendo presente il commento di cui sopra e la necessità di astrarre le condizioni di query degli utenti, come dovrei gestire l'interrogazione degli utenti che filtrano per account_id
? Posso immaginare tre possibili strade:
1. Devo creare un AccountUsersRepository
?
class AccountUsersRepository extends UserRepository {
public function __construct(Account $account) {
$this->account = $account;
}
private function query() {
return parent::query()
->where('account_id', '=', $this->account->id);
}
}
Questo ha il vantaggio di ridurre la duplicazione dei metodi UsersRepository
, ma non si adatta abbastanza a tutto ciò che ho letto su DDD finora (sono tra l'altro rookie)
2. Dovrei metterlo come metodo su AccountsRepository
?
class AccountsRepository extends DatabaseAbstraction {
public function getAccountUsers(Account $account) {
return $this->database()
->select('users.*')
->where('account_id', '=', $account->id)
->exec();
}
}
Ciò richiede la duplicazione di tutti i metodi UserRepository
e potrebbe essere necessario un altro strato UserQuery
, che implementa tali logiche di interrogazione in modo concatenabile.
3. Devo interrogare UserRepository
dall'entità del mio account?
class Account extends Entity {
public function getUsers() {
return UserRepository::findByAccountId($this->id);
}
}
Questo mi sembra più una radice aggregata per me, ma introduce la dipendenza di UserRepository
su Account
entità, che può violare alcuni principi.
4. O mi manca completamente il punto?
Forse c'è una soluzione ancora migliore?
Note a piè di pagina: Oltre alle autorizzazioni che riguardano un servizio, a mio avviso, non dovrebbero implementare la query SQL, ma lasciarle ai repository poiché potrebbero non essere nemmeno basate su SQL.