Le migliori pratiche per le date valutate dinamicamente nel sistema?

3

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?

    
posta Yeldar Kurmangaliyev 04.05.2017 - 06:23
fonte

1 risposta

2

La tua prima soluzione: calcola che il modello di dominio è il migliore.

In effetti anche se qui ci sono due tipi di campi calcolati. Quelli che cambiano a seconda della data in cui si guarda l'oggetto e quelli che cambiano a seconda di un evento di sistema (paidUntilDate)

I campi che cambiano in base a quando li guardi devono essere calcolati al volo o rischiano di non essere aggiornati. L'esportazione sarà errata il giorno successivo alla sua generazione e dovresti probabilmente cercare di evitare tali campi dove possibile.

Tuttavia, il PaidUntilDate dovrebbe essere calcolato quando l'evento che lo modifica avviene. Presumibilmente quando il cliente acquista un abbonamento.

Questo aggira il tuo lungo problema di calcolo. Forse puoi semplicemente fare un join a una tabella di iscrizioni invece del calc.

    
risposta data 04.05.2017 - 08:49
fonte

Leggi altre domande sui tag