Considerazioni sulla progettazione della gerarchia Contract / Project / Line-Item

5

Al momento disponiamo di un'applicazione che consente agli utenti di creare un Contract . Un contratto può avere 1 o più Project . Un progetto può avere 0 o più sottoprogetti (che possono avere i propri sottoprogetti e così via) e uno o più Line . Le linee possono avere qualsiasi numero di sotto-linee (che possono avere le loro linee secondarie e così via).

Attualmente, il nostro design contiene riferimenti circolari e mi piacerebbe allontanarmene. Attualmente, sembra un po 'come questo:

public class Contract
{
    public List<Project> Projects { get; set; }        
}

public class Project
{
    public Contract OwningContract { get; set; }
    public Project ParentProject { get; set; }
    public List<Project> SubProjects { get; set; }
    public List<Line> Lines { get; set; }
}

public class Line
{
    public Project OwningProject { get; set; }
    public List ParentLine { get; set; }
    public List<Line> SubLines { get; set; }
}

Usiamo il modello "M-V-VM" e usiamo questi modelli (e i loro modelli di vista associati) per compilare una grande schermata di "modifica" in cui gli utenti possono modificare i loro contratti e le proprietà su tutti gli oggetti. Dove le cose iniziano a generare confusione per me è quando aggiungiamo, ad esempio, una proprietà Cost a Line . Il problema sta riflettendo al più alto livello (il contratto) le modifiche apportate al livello più basso.

In cerca di alcuni pensieri su come modificare questo disegno per rimuovere i riferimenti circolari. Un pensiero che ho avuto è stato che il contratto avrebbe un Dictionary<Guid, Project> che conterrebbe TUTTI i progetti (indipendentemente dal loro livello nella gerarchia). Il Project avrebbe quindi una proprietà Guid chiamata "Parent" che potrebbe essere usata per cercare nel dizionario del contratto l'oggetto genitore. La stessa logica potrebbe essere applicata al livello Line .

Grazie! Qualsiasi aiuto è apprezzato.

    
posta Thelonias 25.10.2012 - 20:41
fonte

1 risposta

2

Ecco alcuni pensieri:

  • Quello che hai descritto è il tuo Model , non il tuo ViewModel . Ho fatto MVVM su una struttura ad albero prima e diventa brutto velocemente. Il tuo ViewModel deve imitare questa struttura, ma dovrebbe utilizzare ObservableCollection anziché List e può accettare più dati non validi perché i dati sono in transizione mentre li modificano.
  • Crea un codice che convertirà dal tuo Model al tuo ViewModel quando carichi lo schermo. Ciò ti consente di implementare un pulsante Annulla che non fa nulla.
  • Ho usato gli eventi per propagare le modifiche ai livelli più bassi nell'albero fino ai nodi più alti, e consiglierei non a farlo. Sarebbe meglio se il nodo figlio avesse appena chiamato un metodo sul nodo genitore, come PriceChanged(decimal oldPrice, decimal newPrice)
  • Considera tutte le azioni che devono essere propagate: nuovi bambini, riordinando i bambini, eliminando i bambini.
  • Decidi in anticipo se vuoi implementare la funzionalità di annullamento perché è estremamente difficile farlo in seguito. Se vuoi annullare l'operazione, ti suggerisco di progettare l'albero in modo tale che ogni azione abbia un'azione di inversione facile e ovvia, quindi spinga l'azione inversa a Stack<Action> . Potresti voler passare un riferimento a quel Stack a ogni nodo nell'albero in modo da non dover passare le azioni di annullamento sull'albero per l'archiviazione. Ricorda che quando ogni azione ha un'azione inversa, devi pensare anche a PropertyChanged eventi, quindi il tuo View rimane sincronizzato.
  • Avrai bisogno del codice che convalida ViewModel prima di confermare le modifiche a Model e avrai bisogno del codice che impegna le modifiche.
  • Pensa all'intera attività come a un problema di struttura dei dati. Pre-condizioni, azioni, post-condizioni. Se non hai mai utilizzato lo sviluppo basato su test, suggerisco che sarebbe un ottimo punto di partenza per utilizzarlo.
risposta data 25.10.2012 - 21:18
fonte

Leggi altre domande sui tag