Lascia che ti presenti in un caso minimalista e inventato con ordine cronologico, aggiornamenti e problemi in tempo reale.
Utente con solo ID
Avevo un sistema e aveva un'entità User
con la sola colonna ID
. Quindi, c'era una classe User
e una tabella SQL Users
:
[Table("Users")] // database table
public class User
{
[Key]
[Column("Id")] // database column
public long Id { get; set; }
}
Nuove proprietà
Un giorno, il proprietario di un prodotto viene da me e mi chiede di introdurre 4 nuove proprietà:
- compleanno
- età matura (18 anni e oltre)
- termine di sottoscrizione (pagato fino a) data
- è attivo, il che significa che l'abbonamento non è ancora scaduto
Naturalmente, all'inizio propongo di non archiviare "maturità" e "è attivo", poiché si tratta di un valore valutato secondario.
Tuttavia, l'analista di business mi dice: OK, fai come vuoi, ma dovremo vedere \ esportare la tabella di tutti gli utenti con i loro stati di maturità e attivazione, con un massimo di 10000 utenti.
Ora, vedo 3 soluzioni e non posso decidere quale sia migliore in termini di valutazione riassuntiva dell'architettura, delle prestazioni e della futura sostenibilità.
Possibili soluzioni
1. Proprietà valutabili nel modello di dominio
[Table("Users")] // database table
public class User
{
[Key]
[Column("Id")]
public long Id { get; set; }
[Column("Birthday")]
public DateTime Birthday { get; set; }
public bool IsMature
{
get { return (DateTime.Now - Birthday).Years > SystemCfg.MaturityAge; }
}
[Column("PaidUntil")]
public DateTime? PaidUntil { get; set; }
public bool IsActive
{
get { return PaidUntil.HasValue && PaidUntil.Value >= DateTime.Now; }
}
}
Pro:
- Valori effettivi: i valori sono sempre effettivi
- Posizionamento della logica di business: la logica di business viene archiviata in un unico punto
Contro:
-
Rendimento: nell'esempio reale,
PaidUntil
è in realtà una proprietà che richiede un po 'di tempo per essere calcolata, a volte con richieste web, quindi calcolarlo per 10000 utenti in modo dinamico può diventare drammaticamente lento in futuro
2. Proprietà archiviate nel database, ricalcolate all'accesso
[Table("Users")] // database table
public class User
{
[Key]
[Column("Id")]
public long Id { get; set; }
[Column("Birthday")]
public DateTime Birthday { get; set; }
[Column("IsMature")]
public bool IsMature
[Column("PaidUntil")]
public DateTime? PaidUntil { get; set; }
[Column("IsActive")]
public bool IsActive { get; set; }
}
// on sign in:
user.IsMature = (DateTime.Now - user.Birthday).Years > SystemCfg.MaturityAge;
user.IsActive = PaidUntil.HasValue && PaidUntil.Value >= DateTime.Now;
_userRepository.Update(user);
if (!user.IsActive)
return AuthResult.UserIsInactive;
Pro:
- Rendimento: i valori vengono ricalcolati al momento dell'accesso, il che porta le migliori prestazioni tra queste opzioni
Contro:
- Posizionamento della logica aziendale: la logica aziendale è archiviata in un unico luogo, ma il modello è ora anemico
- Valori effettivi: i valori non sono per lo più effettivi per le viste di report / esportazione, poiché vengono aggiornati all'accesso utente
3. Proprietà archiviate nel database, ricalcolate nella pianificazione
Stesso modello, ma i dati vengono aggiornati da uno speciale servizio di Windows, che viene eseguito attraverso il mio database e tiene aggiornati i dati.
Pro:
- Rendimento: i valori vengono calcolati su un thread / applicazione / server separato
- Valori effettivi: i valori sono garantiti come effettivi Il server di aggiornamento UNTIL viene sovraccaricato o inattivo
Contro:
- Posizionamento della logica aziendale: la logica aziendale viene archiviata in un'applicazione separata non di dominio
- Questo approccio sembra strano
Quindi, quale approccio dovrei usare per questo caso speciale?
Che approcci di solito usi tu e le persone?