Progettazione di entità che dovrebbero essere modificabili tramite la GUI ma protette da errori del programmatore

3

Ho un insieme di entità, per ora rappresentate da classi molto semplici (ulteriormente semplificate per questo esempio):

public class Item
{
    public string Name { get; private set; }
    public double MainValue { get; private set; }  //should be exposed for editing in GUI
    public double Value { get; private set; }  //should be exposed for editing in GUI
}

public class Record
{
    public Item Item { get; private set; }
    public double Quantity { get; private set; } //should be exposed for editing in GUI
    public double MainValue { get { return Item.MainValue*Quantity; } }
    public double Value { get { return Item.Value*Quantity; } }
}

public class DayAccount
{
    public DateTime Date { get; private set; }
    public IEnumerable<Record> Records { get; private set; }
    public double MainValueGoal { get; private set; }   //should be exposed for editing in GUI
    public double MainValueTotal { get { return Records.Sum(r => r.MainValue); } }
    public double ValueTotal { get { return Records.Sum(r => r.Value); } }

    public void Add(Record record) {}
    public void Remove(Record record) {}
}

Ci sarà una classe di repository per l'accesso, l'aggiunta e la permanenza di entità DayAccount, ma questo è praticamente tutto. L'utente finale dovrebbe essere in grado di modificare alcune proprietà di queste entità tramite la GUI se ha bisogno di modificarle, ma tutte le altre operazioni su di esse saranno pura analisi dei dati e di sola lettura. Le entità saranno anche mantenute, lette e aggiornate da un ORM e serviranno come modelli nel modello MVVM.

Ciò che mi infastidisce è che queste entità verranno passate pesantemente e vorrei proteggerle da modifiche non intenzionali delle loro proprietà nel codice.

Prima di tutto - stai implementando qualsiasi tipo di protezione che valga la pena? Le modifiche involontarie avverranno solo in caso di errore del programmatore / utilizzo inadeguato della classe. Forse le entità dovrebbero essere lasciate completamente mutabili e il codice ben documentato e ritenuto sicuro finché sarà completamente coperto dai test e superato?

Per scopi didattici, supponiamo che la protezione da modifiche involontarie sia obbligatoria. Come posso rinforzarlo? Rendere gli oggetti completamente immutabili e la loro clonazione potrebbe creare delle difficoltà quando si lavora con l'ORM. Fornire un semplice switch mutabile / immutabile è fuorviante in un contesto multithread. L'introduzione di interfacce immutabili che espongono un oggetto mutevole come in questa risposta non impone l'immutabilità, ma nasconde solo gli oggetti - è più esplicito per un utente di questo codice, ma non completamente protetto da un errore del programmatore.

Uso C # 5 e .NET Framework 4.5.

Aggiorna

Ok, mi sono reso conto di quanto poco conosca sulla progettazione guidata da domini e sui suoi concetti. Ad ogni modo, in base alle due risposte in questo thread, ho trovato il seguente design:

  • Ci sarà una classe di repository che nasconde l'ORM e la logica di persistenza. L'ORM funziona con DTO (tutti i setter pubblici, nessuna convalida, costruttore predefinito). Gli utenti del repository non possono vedere i DTO ma sono in grado di interrogare oggetti di dominio immutabili che il repository crea in base a questi DTO.
  • Per aggiungere / modificare entità, viene creato un modulo di visualizzazione e le sue proprietà vengono popolate con valori dall'oggetto dominio. Il viewmodel è completamente modificabile e ha tutta la logica di validazione. Al salvataggio, un nuovo oggetto dominio viene creato con i valori da viewmodel e quindi salvato o aggiornato attraverso il repository.

Per me, questo pone due nuove domande. L'oggetto di dominio immutabile rappresenta un'entità valida, quindi tutti i suoi valori devono essere convalidati nel costruttore. Il viewmodel, d'altra parte, può contenere valori errati, che vengono poi convalidati (ad esempio, nell'implementazione IDataErrorInfo). Come evitare la duplicazione della logica di convalida tra il modello di visualizzazione e l'oggetto dominio?

Seconda domanda: per memorizzare / aggiornare un oggetto dominio attraverso il repository, devo tenere traccia del valore Id dal DTO creato dall'ORM e impostarlo nell'oggetto dominio. Ciò che mi dà fastidio è che questo è un dettaglio strettamente persistente e non ha rilevanza nella logica di business. Va bene che questo dettaglio di persistenza penetri nel dominio?

Quanto è ragionevole questo design? Sto forse pensando nella giusta direzione?

    
posta sdds 06.04.2015 - 15:44
fonte

2 risposte

4

Consiglierei di associare i tuoi DTO a un oggetto di dominio e rendere immutabile quell'oggetto di dominio

Basta dargli dei setter privati e crearlo attraverso una fabbrica, invece di passare attorno al DTO dappertutto.

Rendere immutabile non è assolutamente una cattiva idea se pensi che debba essere immutabile, documentare ha ancora il rischio che un nuovo sviluppatore entri nell'arena e commetta alcuni errori iniziali. Questa non è la fine del mondo ma vuoi ridurre l'entropia del software il più possibile.

Tuttavia, non consiglierei di rendere immutabile il tuo DTO perché non dovresti averne bisogno per la maggior parte del tempo. È un oggetto stupido e semplice che trasporta i dati, ma l'oggetto dominio, d'altra parte, può essere immutabile perché riflette i requisiti di vita reali dell'azienda.

    
risposta data 06.04.2015 - 16:17
fonte
4

The entities will also be persisted, read and updated by an ORM, and will serve as models in the MVVM pattern.

Perché?

Voglio dire, praticamente sei venuto fuori e hai detto che ti piacerebbe che la tua entità (come quella usata dalla logica di business e usata dall'ORM) fosse immutabile, ma che ti piacerebbe il tuo modello (come usato dall'interfaccia utente ) per essere modificabile (almeno per la schermata di aggiunta / modifica).

Quindi disaccoppia queste due cose, come dovrebbero essere state in primo luogo.

    
risposta data 06.04.2015 - 16:28
fonte

Leggi altre domande sui tag