Bene, puoi vedere un buon esempio in Spring Data Framework che si basa sul concetto di repository.
Lì vedrai che i repository si occupano solo dell'archivio dati e raramente contengono alcuna logica aziendale (questo è riservato per il livello di servizio). Quindi, ad esempio, dai un'occhiata al loro design e vedrai che hanno un'interfaccia CRUDRepository che espone metodi per creare, distruggere e recuperare entità (tra le altre cose). C'è anche un PagingAndSortingRepository che aggiunge funzionalità extra proprio per questo, risultati di ordinamento e paging, ecc. Ecc.
Quindi, questo framework è forse un buon posto per studiare un buon design del repository.
Per quanto ne so, molti dei concetti implementati dal Spring Data Framework provengono da un grande libro intitolato Domain-Driven Design: Tackling Complexity in the Heart of Software , il libro ha un'intera sezione dedicata al design del repository.
Puoi prendere in considerazione l'idea di ottenerne una copia.
Un piccolo estratto del libro spiega:
Il modello REPOSITORY è un semplice framework concettuale per incapsulare quelle soluzioni e riportare il focus del nostro modello.
Un REPOSITORY rappresenta tutti gli oggetti di un certo tipo come un insieme concettuale (solitamente emulato). Funziona come una raccolta, tranne con una capacità di query più elaborata. Vengono aggiunti e rimossi oggetti del tipo appropriato e il macchinario dietro il REPOSITORY li inserisce o li elimina dal database. Questa definizione raccoglie un insieme coerente di responsabilità per fornire l'accesso alle radici di AGGREGATES dal ciclo di vita iniziale fino alla fine.
I client richiedono oggetti dal REPOSITORY utilizzando metodi di query che selezionano gli oggetti in base a criteri specificati dal client, in genere il valore di determinati attributi. Il REPOSITORY recupera l'oggetto richiesto, incapsulando il meccanismo di query del database e mappatura dei metadati. I REPOSITORI possono implementare una varietà di query che selezionano gli oggetti in base ai criteri richiesti dal cliente. Possono anche restituire informazioni di riepilogo, ad esempio un conteggio di quante istanze soddisfano alcuni criteri. Possono persino restituire calcoli di riepilogo, come il totale su tutti gli oggetti corrispondenti di alcuni attributi numerici.
Un REPOSITORY solleva un enorme onere dal cliente, che ora può parlare con un'interfaccia semplice e che rivela l'intenzione e chiedere ciò di cui ha bisogno in termini di modello. Per supportare tutto ciò è necessaria una complessa infrastruttura tecnica, ma l'interfaccia è semplice e concettualmente connessa al modello di dominio.
Perciò:
Per ogni tipo di oggetto che necessita di accesso globale, creare un oggetto in grado di fornire l'illusione di una raccolta in memoria di tutti gli oggetti di quel tipo. Configurare l'accesso tramite una nota interfaccia globale.
Fornire metodi per aggiungere e rimuovere oggetti, che incapsuleranno l'inserimento o la rimozione effettiva dei dati nell'archivio dati. Fornire metodi che selezionano gli oggetti in base ad alcuni criteri e restituiscono oggetti o raccolte di oggetti completamente istanziati i cui valori di attributo soddisfano i criteri, incapsulando così l'effettiva tecnologia di archiviazione e query. Fornire i repository solo per le radici AGGREGATE che necessitano effettivamente dell'accesso diretto. Mantieni il client focalizzato sul modello, delegando tutto l'archiviazione degli oggetti e l'accesso ai REPOSITORI.