Ho a che fare con un sistema di modellazione (finanziario) che ha dozzine di variabili. Alcune variabili sono indipendenti e funzionano come input per il sistema; la maggior parte di essi sono calcolati da altre variabili (indipendenti e calcolate) nel sistema.
Quello che sto cercando è un modo pulito ed elegante per:
- definisce la funzione di ogni variabile dipendente nel sistema
- attiva un nuovo calcolo, ogni volta che cambia una variabile, delle variabili che dipendono da esso
Un modo ingenuo per farlo sarebbe scrivere una singola classe che implementa INotifyPropertyChanged
, e usa un'enorme dichiarazione di caso che elenca tutti i nomi delle variabili x1, x2, ... xn da cui dipendono gli altri, e, ogni volta che una variabile xi
cambia, attiva un ricalcolo di ciascuna delle dipendenze di quella variabile.
Sento che questo approccio ingenuo è imperfetto e che deve esserci un modo più pulito. Ho iniziato il percorso di definizione di una classe CalculationManager<TModel>
, che sarebbe stata utilizzata (in un semplice esempio) come segue:
public class Model : INotifyPropertyChanged
{
private CalculationManager<Model> _calculationManager = new CalculationManager<Model>();
// each setter triggers a "PropertyChanged" event
public double? Height { get; set; }
public double? Weight { get; set; }
public double? BMI { get; set; }
public Model()
{
_calculationManager.DefineDependency<double?>(
forProperty: model => model.BMI,
usingCalculation: (height, weight) => weight / Math.Pow(height, 2),
withInputs: model => model.Height, model.Weight);
}
// INotifyPropertyChanged implementation here
}
Non riprodurrò CalculationManager<TModel>
qui, ma l'idea di base è che imposta una mappa delle dipendenze, ascolta gli eventi PropertyChanged
e aggiorna le proprietà dipendenti secondo necessità. Sento ancora che mi manca qualcosa di importante qui, e che questo non è l'approccio giusto:
- l'uso (errato) di
INotifyPropertyChanged
mi sembra un odore di codice - il parametro
withInputs
è definito comeparams Expression<Func<TModel, T>>[] args
, il che significa che l'elenco di argomenti diusingCalculation
non è selezionato al momento della compilazione - l'elenco degli argomenti (peso, altezza) è definito in modo ridondante in
usingCalculation
ewithInputs
Sono sicuro che questo tipo di sistema di variabili dipendenti deve essere comune in matematica computazionale, fisica, finanza e altri campi. Qualcuno sa di una serie di idee consolidate che si occupano di ciò che sto afferrando qui? Questa sarebbe un'applicazione adatta per un linguaggio funzionale come F #?
Modifica
Altro contesto:
Il modello esiste attualmente in un foglio di calcolo di Excel e viene migrato in un'applicazione C #. Viene eseguito su richiesta e le variabili possono essere modificate dall'utente dall'interfaccia utente dell'applicazione. Il suo scopo è recuperare le variabili a cui è interessata l'azienda, dati gli input correnti dai mercati e i parametri del modello impostati dall'azienda.