2013-08-29 1 views
3

Я не могу найти хороший способ и удобочитаемость, чтобы написать некоторые вычисления внутри класса. Представьте себе следующий класс и все способы, чтобы получить FinalPrice:Getter, Function или просто установить его на конструкторе?

public class Order { 
    public Order(Product[] products) { 
     Items = products; 

вариант 1: Having объявление переменной для каждого свойства, которые хотят быть вычислен, ужасный читаемость


 var orderPrice = products.Sum(p => p.Price * p.Quantity); 
     var orderTaxes = products.Sum(p => p.Taxes * p.Quantity); 
     var orderDiscount = products.Sum(p => p.Price * p.Quantity * p.Discount); 

     OrderPrice = orderPrice; 
     OrderTaxes = orderTaxes; 
     OrderDiscount = orderDiscount; 

     FinalPrice = orderPrice + orderTaxes - orderDiscount; 

вариант 2: проблема с порядком в классе важна! Строка FinalPrice не может быть до других или она не будет работать, но не будет вызывать ошибку.


 OrderPrice = products.Sum(p => p.Price * p.Quantity); 
     OrderTaxes = products.Sum(p => p.Taxes * p.Quantity); 
     OrderDiscount = products.Sum(p=> p.Price * p.Quantity * p.Discount); 

     FinalPrice = OrderPrice + OrderTaxes - OrderDiscount; 

вариант 3: переписывание все формулы - плохо для manteinance. Скорее всего, позже введут различия в ценах.


 FinalPrice = products.Sum(p => p.Price * p.Quantity) + 
        products.Sum(p => p.Taxes * p.Quantity) - 
        products.Sum(p => p.Price * p.Quantity * p.Discount); 

    } 

вариант 4: с помощью методов получения. Это будет рассчитываться каждый раз, когда оно вызывается. Это простой расчет, но в значительной степени предполагайте что-то большее количество кода.


public decimal FinalPrice { get { 
     return OrderPrice + OrderTaxes - OrderDiscount; 
    } } 
} 

вариант 5: с помощью функции. Это хорошо или плохо?


public decimal CalculateFinalPrice() { 
     return OrderPrice + OrderTaxes - OrderDiscount; 
    } 

ответ

5

Я хотел бы сделать всю логику в добытчиках:

public decimal CalculateFinalPrice 
{ 
    get { return CalculateOrderPrice + CalculateOrderTaxes - CalculateOrderDiscount; } 
} 

public decimal CalculateOrderPrice 
{ 
    get { return products.Sum(p => p.Price*p.Quantity); } 
} 

public decimal CalculateOrderTaxes 
{ 
    get { return products.Sum(p => p.Taxes*p.Quantity); } 
} 

public decimal CalculateOrderDiscount 
{ 
    get { return products.Sum(p => p.Price*p.Quantity*p.Discount); } 
} 

Если это происходит медленно в вашем secenario, вы можете кэшировать свойства.

private decimal? _calculateOrderPrice; 
public decimal CalculateOrderPrice 
{ 
    get 
    { 
     if (_calculateOrderPrice == null) 
     { 
      _calculateOrderPrice = products.Sum(p => p.Price*p.Quantity; 
     } 
     return _calculateOrderPrice.Value; 
    } 
} 

Если вы перейдете к определению свойства, вы сразу увидите, как оно рассчитывается. Кроме того, вам не важно, какие вычисления необходимо выполнить в первую очередь.

+0

Вы можете добавить что-то с кэш-сценарием? вы имеете в виду сохранение значений в частных свойствах? также любое преимущество использования геттеров вместо функций? –

+0

@Bart. Да, вы можете хранить кеш в частной области, используя Lazy . Когда использовать свойства или когда использовать функции без параметров. Это долгая история. На данный момент я должен сказать, что если vanlue никогда не изменится И если в первый раз вы используете свойство, это не очень медленно, но вы можете использовать свойство (кэширование). –

+0

@AlexSiepman сторона примечание. Кэширование в порядке. Но вам нужно обеспечить, чтобы недействительность кеша, если кто-то изменяет состояние объекта 'Order' (если класс' Order' является изменяемым, что кажется не в этом примере. Когда объект 'Order' создается с помощью' Product' массив, я думаю, что ни один клиент не изменит массив.) – Imran

4

Я хотел бы создать методы CalculateFinalPrice, CalculateOrderPrice, CalculateOrderTaxes и CalculateOrderDiscount, как это:

public decimal CalculateFinalPrice() { 
    return CalculateOrderPrice() + CalculateOrderTaxes() - CalculateOrderDiscount(); 
} 

public decimal CalculateOrderPrice() 
{ 
    // Logic here to calculate order price 
    return theOrderPrice; 
} 

public decimal CalculateOrderTaxes() 
{ 
    // Logic here to calculate order taxes 
    return theOrderTaxes; 
} 

public decimal CalculateOrderDiscount() 
{ 
    // Logic here to calcuate order discount 
    return theOrderDiscount; 
} 

Это дает вам больше, но более мелкие кусочки, которые легче поддерживать, читать и единичный тест, поскольку каждый метод несет отдельную ответственность.

+0

любое слово о том, почему функции вместо Getters? просто интересно, почему вы предпочитаете подход к функциям vs Alex, который предлагает подход getter. –

+0

Я предпочитаю подход метода, потому что методы могут или не могут быть привязаны к экземпляру, тогда как свойства обязательно являются частью экземпляра класса. Например, вы можете сделать вышеуказанные методы частью класса утилиты, где все они являются статическими, и они могут использоваться другими частями вашего приложения, которые не должны знать какой-либо конкретный экземпляр объекта. –

+1

@Bart Вот несколько полезных объяснений SO-вопросов по свойствам vs Методы.[link1] (http://stackoverflow.com/q/601621/1531157), [link2] (http://stackoverflow.com/q/1294152/1531157) – Imran

Смежные вопросы