Другие части эпической саги о вреде дублирования:
Этот вид дублирования не так очевиден, как предыдущие - потому что повторяется лишь условная логика, управляющая потоком выполнения приложения. Выполняемые при этом операции зачастую совершенно различны.
Нет ничего плохого в том, чтобы написать блок switch один раз (часто я так поступаю при создании объектов с помощью фабрики). Но повторение одних и тех же условий - не сулит ничего хорошего. Например, расчёт зарплат и бонусов зависит от типа сотрудника:
Условная логика хранит знания о различных типах сотрудников. Повторение условий приводит к дублированию этих знаний. Поэтому при добавлении нового типа сотрудника прийдётся найти и обновить все повторяющиеся условия. Устранить такое дублирование можно с помощью полиморфизма (рефакторинг Replace Conditional with Polymorphism):
К слову, тип объекта не всегда явно выражается кодом типа. Это может быть и условное выражение:
- Вступление
- Дублирование поведения
- Дублирование логики создания
- Дублирование условной логики
- Дублирование данных
Этот вид дублирования не так очевиден, как предыдущие - потому что повторяется лишь условная логика, управляющая потоком выполнения приложения. Выполняемые при этом операции зачастую совершенно различны.
Нет ничего плохого в том, чтобы написать блок switch один раз (часто я так поступаю при создании объектов с помощью фабрики). Но повторение одних и тех же условий - не сулит ничего хорошего. Например, расчёт зарплат и бонусов зависит от типа сотрудника:
public abstract class Employee : Entity<int>
{
private string _name;
private decimal _hourlyPayRate;
private decimal _annualSalary;
private decimal _tax;
private EmployeeType _employeeType;
public decimal CalculatePayment()
{
decimal result = CalculateWeeklyPayment() - _tax;
if (DateTime.Today.Month == 12)
result += CalculateChristmasBonus();
return result;
}
private decimal CalculateWeeklyPayment()
{
switch (_employeeType)
{
case EmployeeType.Hourly:
const int hoursInPayPeriod = 40;
return hoursInPayPeriod * _hourlyPayRate;
case EmployeeType.Salaried:
const int payPeriodsInYear = 52;
return _annualSalary / payPeriodsInYear;
case EmployeeType.Zombie:
return 0;
default:
throw new InvalidEnumArgumentException();
}
}
private decimal CalculateChristmasBonus()
{
switch (_employeeType)
{
case EmployeeType.Salaried:
return _annualSalary / 12;
default:
return 50;
}
}
}
Условная логика хранит знания о различных типах сотрудников. Повторение условий приводит к дублированию этих знаний. Поэтому при добавлении нового типа сотрудника прийдётся найти и обновить все повторяющиеся условия. Устранить такое дублирование можно с помощью полиморфизма (рефакторинг Replace Conditional with Polymorphism):
public abstract class Employee : Entity<int>
{
private string _name;
private decimal _tax;
public decimal CalculatePayment()
{
decimal result = CalculateWeeklyPayment() - _tax ;
if (DateTime.Today.Month == 12)
result += CalculateChristmasBonus();
return result;
}
protected abstract decimal CalculateWeeklyPayment();
protected virtual decimal CalculateChristmasBonus()
{
return 50;
}
}
public class HourlyEmployee : Employee
{
private decimal _hourlyPayRate;
protected override decimal CalculateWeeklyPayment()
{
const int hoursInPayPeriod = 40;
return _hourlyPayRate * hoursInPayPeriod;
}
}
public class SalariedEmployee : Employee
{
private decimal _annualSalary;
protected override decimal CalculateWeeklyPayment()
{
const int payPeriodsInYear = 52;
return _annualSalary / payPeriodsInYear;
}
protected override decimal CalculateChristmasBonus()
{
return _annualSalary / 12;
}
}
public class Zombie : Employee
{
protected override decimal CalculateWeeklyPayment()
{
return 0;
}
}
К слову, тип объекта не всегда явно выражается кодом типа. Это может быть и условное выражение:
private decimal CalculateChristmasBonus()
{
if (_annualSalary > 0) // same as EmployeeType.Salaried
return _annualSalary / 12;
return 50;
}
Комментариев нет:
Отправить комментарий