Il codice è C # pseudocode.
Una parola su MVC
Il modello di dominio non si preoccupa delle trasformazioni alle giunture di MVC. Cioè non ci interessa come i dati arriveranno dall'interfaccia utente alle classi business all'archivio dati (e viceversa). Un buon modello di dominio è il riferimento fisso attorno al quale evolve tutto il codice di trasmissione e MVC.
Riepilogo
Sembra molto? No. Le classi appropriate semplificano la codifica e il codice risultante è semplice. Come? Principio della singola responsabilità e incapsulamento.
Strutture dati del dominio
Progetta un modello che abbia senso in modo che sia facile da accedere ed è stabile man mano che l'algoritmo e il codice di costo / prezzo si evolvono.
public class Product {
var Id;
var Cost; // MSRP. Before the kibitzing begins.
// No Price property. Will dynamically calc.
// My design decision. You can do otherwise.
var Options;
// MSRP. No price adjusting.
public Decimal GetCost { return this.Cost + this.Options.GetCost(); }
// The visitor pattern.
public void GetPrice ( PricingCollection adjustments) {
if(adjustments == null) return this.GetCost();
return adjustments.Apply(this);
}
}
public class Option {
var Id;
var Cost; // MSRP
bool Discontinued; // don't show it on the UI if it is.
}
public class OptionCollection {
var Options; // Add() method not shown
public decimal GetCost() {
var total = 0;
foreach (var option in Options)
total += option.Cost;
return total;
}
}
del prodotto-Opzioni
public ProductOptions : Dictionary<Product, OptionCollection>
Compilato da un archivio dati al momento dell'inizializzazione del programma.
Il set completo di opzioni di prodotto e può essere utilizzato nell'interfaccia utente. Cambiare il data-store ovviamente cambia le opzioni disponibili per l'utente.
La rimozione delle opzioni dopo essere state selezionate per un prodotto è un problema con i requisiti. Penserei che tu riempissi gli ordini di prodotti esistenti con le opzioni ora fuori produzione.
Prezzi
Perhaps I can have a class for just options, and another class for just pricing,
Costruito in un insieme separato di classi. Inseriamo il "modello di prezzo" in Product
e il "modello di prezzo" sa come adeguare i costi per arrivare a un prezzo finale e totale.
Ad esempio "Acquista l'opzione X e ottieni l'opzione Y a metà prezzo". Oppure "$ 3, OOO fuori dal nostro camion Tough Texas, solo San Jacinto Day."
Non ho intenzione di discutere "interfaccia" vs "classe astratta". Il codice cliente si occupa dell'API, non della sua implementazione.
public abstract class PriceRule {
// Sub classes must implement this method
// As complex as your sales gimmic demands.
public abstract Decimal Apply (Product thisProduct);
}
PriceRule
deve conoscere la struttura del modello di dominio. Va bene. Questa è l'idea del modello di progettazione dei visitatori.
L'API PriceRule
implica (per il modello di dominio) che un OptionCollection
possa esistere solo w / in un oggetto Product
. Mi piace perché mantiene coerenti le nostre strutture: appartiene sempre a qualche oggetto Product
. A meno che i requisiti non dettino altrimenti, naturalmente.
public class PriceRuleCollection {
var PriceRules; // Add() method not shown
public Decimal Apply (Product thisProduct) {
var total = 0;
foreach (var rule in PriceRules)
total = rule.Apply(thisProduct);
return total;
}
}
and then some kind of a third "Combiner" class that knows how to combine options and pricing to come up with final totals. ... But won't that be too complicated?
Al contrario! Potresti pensarlo troppo banale, ma ha 2 scopi importanti.
- Dichiara esplicitamente il concetto di "modello di prezzo". Il termine fa parte del business per cui stiamo codificando. Possiamo parlare e codificare nei termini dei nostri clienti.
- Un posto per aggiungere codice al livello di astrazione del "modello di prezzo". Possiamo manipolare l'ordine dell'applicazione delle regole di prezzo. Possiamo aggiungere nuovi concetti come il finanziamento.
.
public class PricingModel{
public PricingModel( PriceRuleCollection pricing, Product product, ProductOptions allOptions ) {
this.Pricing = pricing;
this.Product = product;
this.ProductOptions = allOptions; // might be handy. We everything in one place.
}
public Decimal TotalPrice() {
return this.pricing.Apply(this.product);
}
}