Bad Code
namespace TesteCleanCode
{
public class Class1
{
public decimal Calculate(decimal amount, int type, int years)
{
decimal result = 0;
decimal disc = (years > 5) ? (decimal)5 / 100 : (decimal)years / 100;
if (type == 1)
{
result = amount;
}
else if (type == 2)
{
result = (amount - (0.1m * amount)) - disc * (amount - (0.1m *
amount));
}
else if (type == 3)
{
result = (0.7m * amount) - disc * (0.7m * amount);
}
else if (type == 4)
{
result = (amount - (0.5m * amount)) - disc * (amount - (0.5m *
amount));
}
return result;
}
}
}
Clean Code
namespace TesteCleanCode
{
public class DiscountManager
{
private readonly IAccountDiscountCalculatorFactory _factory;
private readonly ILoyaltyDiscountCalculator _loyaltyDiscountCalculator;
public DiscountManager(IAccountDiscountCalculatorFactory factory,
ILoyaltyDiscountCalculator loyaltyDiscountCalculator)
{
_factory = factory;
_loyaltyDiscountCalculator = loyaltyDiscountCalculator;
}
public decimal ApplyDiscount(decimal price, AccountStatus accountStatus,
int timeOfHavingAccountInYears)
{
var priceAfterDiscount =
_factory.GetAccountDiscountCalculator(accountStatus).ApplyDiscount(price);
priceAfterDiscount =
_loyaltyDiscountCalculator.ApplyDiscount(priceAfterDiscount,
timeOfHavingAccountInYears);
return priceAfterDiscount;
}
}
}
namespace TesteCleanCode
{
public interface IAccountDiscountCalculator
{
decimal ApplyDiscount(decimal price);
}
}
namespace TesteCleanCode
{
public interface IAccountDiscountCalculatorFactory
{
IAccountDiscountCalculator GetAccountDiscountCalculator(AccountStatus
accountStatus);
}
}
namespace TesteCleanCode
{
public interface ILoyaltyDiscountCalculator
{
decimal ApplyDiscount(decimal price, int timeOfHavingAccountInYears);
}
}
namespace TesteCleanCode
{
public class NotRegisteredDiscountCalculator : IAccountDiscountCalculator
{
public decimal ApplyDiscount(decimal price)
{
return price;
}
}
}
namespace TesteCleanCode
{
public class SimpleCustomerDiscountCalculator : IAccountDiscountCalculator
{
public decimal ApplyDiscount(decimal price)
{
return price - Constants.DISCOUNT_FOR_SIMPLE_CUSTOMERS * price;
}
}
}
namespace TesteCleanCode
{
public class ValuableCustomerDiscountCalculator : IAccountDiscountCalculator
{
public decimal ApplyDiscount(decimal price)
{
return price - Constants.DISCOUNT_FOR_VALUABLE_CUSTOMERS * price;
}
}
}
namespace TesteCleanCode
{
public class MostValuableCustomerDiscountCalculator :
IAccountDiscountCalculator
{
public decimal ApplyDiscount(decimal price)
{
return price - Constants.DISCOUNT_FOR_MOST_VALUABLE_CUSTOMERS *
price;
}
}
}
namespace TesteCleanCode
{
public enum AccountStatus
{
NotRegistered = 1,
SimpleCustomer = 2,
ValuableCustomer = 3,
MostValuableCustomer = 4
}
}
namespace TesteCleanCode
{
public static class Constants
{
public const int MAXIMUM_DISCOUNT_FOR_LOYALTY = 5;
public const decimal DISCOUNT_FOR_SIMPLE_CUSTOMERS = 0.1m;
public const decimal DISCOUNT_FOR_VALUABLE_CUSTOMERS = 0.3m;
public const decimal DISCOUNT_FOR_MOST_VALUABLE_CUSTOMERS = 0.5m;
}
}
using System;
namespace TesteCleanCode
{
public class DefaultAccountDiscountCalculatorFactory :
IAccountDiscountCalculatorFactory
{
public IAccountDiscountCalculator
GetAccountDiscountCalculator(AccountStatus accountStatus)
{
IAccountDiscountCalculator calculator;
switch (accountStatus)
{
case [Link]:
calculator = new NotRegisteredDiscountCalculator();
break;
case [Link]:
calculator = new SimpleCustomerDiscountCalculator();
break;
case [Link]:
calculator = new ValuableCustomerDiscountCalculator();
break;
case [Link]:
calculator = new MostValuableCustomerDiscountCalculator();
break;
default:
throw new NotImplementedException();
}
return calculator;
}
}
}
namespace TesteCleanCode
{
public class DefaultLoyaltyDiscountCalculator : ILoyaltyDiscountCalculator
{
public decimal ApplyDiscount(decimal price, int
timeOfHavingAccountInYears)
{
var discountForLoyaltyInPercentage = timeOfHavingAccountInYears >
Constants.MAXIMUM_DISCOUNT_FOR_LOYALTY
? (decimal) Constants.MAXIMUM_DISCOUNT_FOR_LOYALTY / 100
: (decimal) timeOfHavingAccountInYears / 100;
return price - discountForLoyaltyInPercentage * price;
}
}
}
[Link]
a-good-code