2012-05-20 6 views
5

Ich versuche herauszufinden, wie ich ein bisschen Code verbessern kann, den ich schrieb, der ein paar Regeln verwendet, um ein paar verschiedene Preise für Autoversicherung zu berechnen. Hier ist das Stück, das mich stört:Wie kann ich diesen Preiskalkulationscode jetzt in 4 Berechnungen verbessern, aber in naher Zukunft mehr?

public Insurance GetInsurance(CarData carData) 
{ 
    var insurance = new Insurance(); 

    insurance.priceGeneral = this.CalculatePrice(new Car { BrandDealer = false, MonthPayment = false, CarData = carData }); 
    insurance.priceGeneralMonth = this.CalculatePrice(new Car { BrandDealer = false, MonthPayment = true, CarData = carData }); 
    insurance.priceBrandDealer = this.CalculatePrice(new Car { BrandDealer = true, MonthPayment = false, CarData = carData }); 
    insurance.priceBrandDealerMonth = this.CalculatePrice(new Car { BrandDealer = true, MonthPayment = true, CarData = carData }); 

    return insurance; 
} 

Hinweis, dass es einen signifikanten Unterschied bei der Berechnung der monatlichen Zahlungen über den Normalpreis (jährliche Zahlung) und die dependind, ob BrandDealer wahr oder falsch gibt es auch eine andere Berechnung dafür. Ich habe versucht, diese Variable zu eliminieren, aber der Kunde fordert diese Regeln.

Ich bin mir bewusst, dass einige der Eigenschaften sind nicht die tatsächlichen Eigenschaften eines "Car", aber ich werde das auch bald umgestalten.

Mich stört die Tatsache, dass ich diese Berechnung 4 Mal mache und es wird in der Zukunft mehr Regeln geben. Und die bevorstehende neue Regel wird einen weiteren booleschen und zwei weitere Berechnungen hinzufügen.

Gibt es ein schönes Designmuster, das ich hier nicht finde, das ich verwenden sollte?

+0

So viele Fragen ... zuerst, ist die Methode in der Insurance-Klasse oder einer anderen Klasse? – tcarvin

Antwort

0

Was Sie tun müssen, ist Ihre Berechnung in kleinere Komponenten zu brechen. Sie müssen den gemeinsamen Code finden und in einer Karte speichern. Sagen wir, dass calc 1 = A * B + C. und calc 2 = A * C - b

Sie müssen A, B, C nur einmal durchführen und in hashmap speichern. jetzt calc 2 = hash.getOrAdd (Ein Schlüssel) * hash.getOrAdd (C Schlüssel) - hash.getOrAdd (C Schlüssel).

Wenn Sie keinen Comon-Code finden, als Ihr Pech und müssen Sie alle Berechnungen durchführen.

0

Eine Sache, die wirklich hervorsticht, ist, dass Sie bei jeder Berechnung 4 neue Auto-Objekte erstellen. Ist das komplett notwendig? Könnten Sie 4 davon mit den verschiedenen Kombinationen von BrandDealer/MonthlyPayment erstellen (und speichern), um sie dann für die Berechnung der entsprechenden CarData zu verwenden?

Zusätzlich könnte dies besser mit einer Art einer Kalkulationsfabrik erreicht werden, die die verschiedenen benötigten Car-Objekte und andere Berechnungsdetails abstrahiert/versteckt. Erwägen Sie, für jeden Berechnungstyp interne Methoden hinzuzufügen, sodass Sie für neue Berechnungen nur eine andere Methode hinzufügen müssen, anstatt eine große Methode zu ändern. In der Regel wird dies durch Hinzufügen von Berechnungsobjekten anstelle von Methoden erreicht, die jedoch in dieser speziellen Situation möglicherweise übertrieben sind.

3

Lassen Sie uns zuerst das Problem lösen, das Sie heute haben, was eine Möglichkeit ist, den repetitiven Berechnungscode zu bereinigen.

mit zu beginnen, müssen wir das stratgey Muster zu Ihrer Preisberechnung werden die Definition der Schnittstelle der Berechnung und Bewegen der unterschiedlichen Berechnungslogik-Code in ihre neue Heimat anzuwenden:

// calculation common interface 
public interface IPriceCalculation 
{ 
    public InsurancePrice CalculatePrice(CarData data); 
} 

// result from the calculation 
public class InsurancePrice 
{ 
    public string Description { get; set; } 
    public decimal Price { get; set; }  
} 


// concrete implementations 
public class BrandDealerMonthlyPaymentCalculation : IPriceCalculation 
{ 
    public InsurancePrice CalculatePrice(CarData data) 
    { 
     // logic to perform calculation of BrandDealer = true, MonthPayment = true 

     // just for example... 
     return new InsurancePrice() 
     { 
     Description = "Policy price with a Brand dealer and monthly payments", 
     Price = 250.25; 
     }; 
    } 
} 

public class BrandDealerYearlyPaymentCalculation : IPriceCalculation 
{ 
    public InsurancePrice CalculatePrice(CarData data) 
    { 
     // logic to perform calculation of BrandDealer = true, MonthPayment = false 
    } 
} 

public class NonBrandDealerYearlyCalculation : IPriceCalculation 
{ 
    public InsurancePrice CalculatePrice(CarData data) 
    { 
     // logic to perform calculation of BrandDealer = false, MonthPayment = false 
    } 
} 

public class NonBrandDealerMonthlyCalculation : IPriceCalculation 
{ 
    public InsurancePrice CalculatePrice(CarData data) 
    { 
     // logic to perform calculation of BrandDealer = false, MonthPayment = true 
    } 
} 

Mit den Berechnungen definiert, Sie installieren sie. Innerhalb der Klasse, die die GetInsurance-Methode definiert (wir nennen es InsuranceFactory), werden wir dies in Ihrem ctor tun.Dies könnte über eine andere Klasse erfolgen treibt sie über Eigenschaften in über config über DI, was auch immer, aber der Ctor einfachste zur Veranschaulichung ist:

public class InsuranceFactory 
{ 
    private List<IPriceCalculation> _priceCalculators = new List<IPriceCalculation>(); 

    public InsuranceFactory() 
    { 
     _priceCalculators.Add(new BrandDealerYearlyPaymentCalculation()); 
     _priceCalculators.Add(new BrandDealerMonthlyPaymentCalculation()); 
     _priceCalculators.Add(new NonBrandDealerYearlyCalculation()); 
     _priceCalculators.Add(new NonBrandDealerMonthlyCalculation()); 
     // easy to add more calculations right here... 
    } 

} 

Als nächstes werden wir Ihre GetInsurance Methode in der InsuranceFactory Klasse erneut oben:

Beachten Sie, wie sich Ihre GetInsurance-Methode nicht mehr jedes Mal ändern muss, wenn Sie eine neue Berechnung erstellen. Wenn Sie die Ergebnisse in einer Liste innerhalb des Versicherungsobjekts speichern (insurance.PriceOptions), muss Ihre Versicherungssparte auch nicht geändert werden. Ihr UI-Code kann alle Optionen darstellen, indem er diese Liste wiederholt. Dieses Beispiel ist etwas vereinfacht, aber sollte Sie weiterbringen.

Jetzt ein paar Worte zu einem möglichen zweiten Problem, das ich erwarten kann. Wenn Ihre Berechnungsunterklassen zusätzliche Permutationen haben, werden Sie eine Klassenexplosion haben. Zum Beispiel haben Sie jetzt 2 Faktoren (Brand und PaySchedule) mit jeweils 2 Wahlmöglichkeiten, die Ihnen 2 x 2 = 4 Klassen geben. Aber was ist, wenn wir Credyscore mit 3 Wahlmöglichkeiten hinzufügen (Goor, Fair, Poor)? Dann erhalten Sie:

GoodCreditBrandDealerYearlyPaymentCalculation 
GoodCreditBrandDealerMonthlyPaymentCalculation 
GoodCreditNonBrandDealerYearlyCalculation 
GoodCreditNonBrandDealerMonthlyCalculation 
FairCreditBrandDealerYearlyPaymentCalculation 
FairCreditBrandDealerMonthlyPaymentCalculation 
FairCreditNonBrandDealerYearlyCalculation 
FairCreditNonBrandDealerMonthlyCalculation 
PoorCreditBrandDealerYearlyPaymentCalculation 
PoorCreditBrandDealerMonthlyPaymentCalculation 
PoorCreditNonBrandDealerYearlyCalculation 
PoorCreditNonBrandDealerMonthlyCalculation 

Dies wird nur von hier schlechter. Dies ist wirklich eine eigene Frage und Antwort, wenn es aufkommt, aber es ist etwas, auf das Sie achten sollten. Wenn es so wird, refaktorieren Sie die Berechnungsklassen. Aber was schön ist, muss der Code in GetInsurance immer noch nicht ändern.

Verwandte Themen