Всем привет,
Вопрос скорее про паттерны, без опыта не понятно, как их тут можно применить
Есть не сложные модели (рекордами)
public record Cart(int DeliveryZoneId, string? Promocode, int[] ProductIds);
public record DeliveryZone(int Id, double Fee);
public record Product(int Id, double Price, string Name);
public record Promocode(double Discount, string Code);
Собственно, в корзине имеется зона доставки, может быть промокод и список каких-то айдишников продуктов
Нужно посчитать по корзине итоговую сумму, учитывая скидку за промокод, учитывая минимальную сумму заказа (если она меньше, то добавляется) и есть еще момент, что если много товаров в корзине, то добавляется еще какая-то сумма за большой заказ.
Вот такой код у меня получился, он простой, как топор, и я не понимаю, как его можно еще улучшить. Тут напрашиваются паттерны цепочка обязанностей и стратегия. Я читаю по ним инфу и мне кажется, они тут не нужны (примеры может плохие). С другой стороны, если я пытаюсь что-то добавить, то получается слишком сильное усложнение, новые сущности, не сразу очевидные вещи. Короч, помогите разобраться, вот мой вариант задачи:
using CartCalculator.Models;
namespace CartCalculator;
public class Calculator
{
private const double FreeDeliverySum = 1000;
private const int VeryLargeOrderProductCount = 20;
private const double VeryLargeOrderFee = 200;
private readonly Product[] _allMenuProducts;
private readonly Promocode[] _allAvailablePromocodes;
private readonly DeliveryZone[] _allDeliveryZones;
public Calculator(Product[] allMenuProducts, Promocode[] allAvailablePromocodes, DeliveryZone[] allDeliveryZones)
{
_allMenuProducts = allMenuProducts;
_allAvailablePromocodes = allAvailablePromocodes;
_allDeliveryZones = allDeliveryZones;
}
public double CalculateTotalPrice(Cart cart)
{
var totalPrice = TotalPrice(cart.ProductIds);
if (!string.IsNullOrEmpty(cart.Promocode))
{
var discount = GetPromocodeDiscount(cart.Promocode);
totalPrice *= 1 - discount;
}
if (totalPrice < FreeDeliverySum)
{
var deliveryFee = GetDeliveryFee(cart.DeliveryZoneId);
totalPrice += deliveryFee;
}
if (cart.ProductIds.Length > VeryLargeOrderProductCount)
{
totalPrice += VeryLargeOrderFee;
}
return totalPrice;
}
private double GetDeliveryFee(int deliveryZoneId)
{
var deliveryZone = _allDeliveryZones.SingleOrDefault(dz => dz.Id == deliveryZoneId);
if (deliveryZone == null)
{
throw new Exception($"Cannot find delivery zone with id \"{deliveryZoneId}\"");
}
return deliveryZone.Fee;
}
private double GetPromocodeDiscount(string promocode)
{
var promo = _allAvailablePromocodes.SingleOrDefault(p => p.Code == promocode);
if (promo == null)
{
throw new Exception($"Cannot find promocode \"{promocode}\"");
}
return promo.Discount;
}
private double TotalPrice(IEnumerable<int> productIds)
{
double totalPrice = 0;
foreach (var productId in productIds)
{
var product = _allMenuProducts.SingleOrDefault(p => p.Id == productId);
if (product == null)
{
throw new Exception($"Cannot find product with id \"${productId}\"");
}
totalPrice += product.Price;
}
return totalPrice;
}
}