Il tuo repository non interrompe " architettura pulita ", che identifica le entità come il nucleo, richiede l'inversione di dipendenza, ma non impone l'uso di archivi.
Ma il tuo repository sembra infrangere i principi del codice pulito, e in particolare:
- il principio di responsabilità singola : impacchetta cose che hanno motivi diversi modificare:
Payment
(che potrebbe cambiare ad esempio a causa di nuove pratiche commerciali o nuovi standard bancari) e User
(soggetto a politica interna, dubbi di GDPR o requisiti del provider di identità);
- il principio di separazione delle interfacce : tu costringi i client del tuo repository a conoscere l'interfaccia di
Payment
e User
, anche se non ne hanno bisogno (ad esempio se un caso di utilizzo successivo produrrebbe un rapporto sul totale dei pagamenti al giorno nell'ultimo mese) .
Il tuo approccio non è in linea con i principi Domain Driven Design , che suggeriscono un repository per un singolo aggregato :
-
In DDD identificate Entità e raggruppate in Aggregati indipendenti che sono sempre accessibili tramite una singola radice aggregata .
-
Ma nel tuo caso, hai due Entità indipendenti che costituiscono ciascuna il proprio Aggregato:
- Non è possibile vedere
Payment
come un aggregato contenente un User
dipendente, poiché quest'ultimo potrebbe esistere prima di aver effettuato qualsiasi pagamento.
- Non è possibile considerare
User
come un aggregato con Payments
dipendente, perché ciò significherebbe che è possibile identificare un pagamento solo in relazione a un utente, che non è un caso realistico per i sistemi di pagamento.
Modifica: informazioni aggiuntive
Il concetto di repository intende fornire un livello di astrazione che consente di gestire oggetti persistenti come se fossero in una raccolta in memoria e senza eseguire il db.
Con questo modello architettonico, preferisci fare riferimento ad altri aggregati per identità (valore) . Lo scenario tipico è ottenere Payments
interrogando PaymentRepository
. Quindi verrà utilizzato UserId
del pagamento per ottenere l'utente con UserRepostitory.getById()
. In alternativa, devi utilizzare PaymentId
per interrogare un utente di un pagamento invocando UserRepostitory.getByPaymentId()
.
Il vantaggio dell'identità è che consente di separare le Entità in modelli molto complessi: passare tutti i possibili tipi di oggetti a un repository (invece di un semplice id) causerebbe un'esplosione di dipendenze dell'interfaccia. Allo stesso modo, se gli oggetti correlati verrebbero caricati sistematicamente dal repository (come pensate di aspettarvi), allora potreste avere un effetto valanga: immaginate di avere entità che rappresentano nodi e bordi di un grafico. Qualunque sia il nodo che si ottiene dal repository, si finirebbe con il grafico completo in memoria!
Detto questo, non conosco il tuo modello né i tuoi vincoli e non giudico. Sta a voi decidere quale sia l'architettura più adatta. Puoi discostarti perfettamente dalle regole se hai argomenti validi e comprendi le conseguenze. A proposito, questa domanda sulle prestazioni del repository potrebbe interessarti.