Considera di scrivere classi separate Repository
che sono responsabili per l'interrogazione del tuo database, ma che non contengono nemmeno dati di dominio. (Potrebbero contenere lo stato della connessione DB o qualcosa di simile ma non dati di dominio effettivi)
Quando si lavora con i risultati della query, la soluzione ideale è quella di mappare su semplici entità "modello" che contengono solo proprietà e nessuna logica (cioè non considerano le entità mappate come oggetti, perché la loro responsabilità è solo quella di colmare il divario per il tuo database).
Considera di modificare User
in UserModel
che contiene solo le proprietà dati mappate dal tuo database e nessuna logica. (considera anche Job
a JobModel
per coerenza)
In secondo luogo, utilizza diverse classi Repository
per interrogare il database e restituire i dati mappati alle classi di entità; Ad esempio
-
UserRepository
per interrogare e mappare UserModel
dati
-
JobRepository
per interrogare e mappare JobModel
dati
-
AddressRepository
per interrogare e mappare AddressModel
dati
Ciascuna delle tue visualizzazioni dell'interfaccia utente può scegliere i dati di cui hanno bisogno da ciascun repository (se ce ne sono) in base a una query decisa dal controller della vista, senza collocare una dipendenza su un oggetto User
.
Infine, se una vista ha bisogno di qualcosa di più di un singolo modello di database (e soprattutto se ha bisogno di dati aggiuntivi che non provengono dal database), considera di fare in modo che il View Controller costruisca ViewModel
s in base ai modelli dei tuoi repository . Ad esempio:
class UserViewModel {
UserModel user;
List<AddressModel> addresses;
bool isReadOnly;
}
I ViewModel sono utili per garantire che ogni View abbia i dati giusti (e solo i dati di cui ha bisogno) senza lasciare problemi di interfaccia utente nel resto di un'applicazione. Modelli di interfaccia utente comuni come MVC / MVP utilizzano ViewModels per disaccoppiare qualsiasi struttura di interfaccia utente speciale o strutture di interfaccia utente dal resto dell'app
Aggiornamento:
(In risposta al commento sulla logica aziendale)
Né le classi dell'interfaccia utente né le classi di database / persistenza dovrebbero occuparsi della logica aziendale. La maggior parte delle applicazioni non banali richiede molto più della semplice capacità di estrarre dati direttamente da un repository; un "livello" in più tra le classi e le funzioni che contengono quella logica è la soluzione tipica.
La logica aziendale, la logica delle app e altre classi intermedie verrebbero utilizzate direttamente dalle classi del controller UI, ad esempio (Rough schematic):
View --> Controller --> Business logic classes --> Repositories / External APIs / etc.
Frecce che indicano la direzione di ciascuna dipendenza. Un controller di visualizzazione può dipendere da classi contenenti la logica aziendale ma non viceversa; Le classi di business logic possono dipendere dai repository ma i repository non saprebbero ancora nulla della logica di business.