Другие части эпической саги о вреде дублирования:
Дублирование также встречается при создании объектов. Например, когда требуется совершить несколько одинаковых действий перед тем, как создаваемый объект можно будет использовать. И чем сложнее ритуал создания объекта, тем больше работы будет по изменению каждой копии этого ритуала.
Всем известно, что в компании DcMonald's ленивых, грубых и неопрятных сотрудников превращают в зомби. При этом в каждом из этих случаев приходится повторять непростой процесс изготовления шаманом порошка из рыбы фугу, отравления сотрудника и чтения заклинания:
Любая ошибка в этой последовательности приведёт к утрате ценного сотрудника. Но избежать дублирования таких ценных знаний можно с помощью рефакторинга Move Creation Knowledge to Factory, либо Extract Method.
Теперь любой из отделов компании может создавать зомби, не вдаваясь в подробности сложного ритуала. И что самое главное - когда знания о создании зомби имеют единственное представление в системе, мы можем легко и быстро внести изменения в этот процесс (например, заменить ритуал вуду просмотром рекламы iPhone).
Другой случай - дублирование параметров конструкторов. Если периодически приходится повторять какое-то магическое сочетание параметров, значит в этом наборе параметров содержиться знание о каком-то особенном типе объекта. Например, я заметил, что в тестах несколько раз повторялись вызовы такого конструктора (первый параметр - размер ссуды, второй - дата возврата):
Немного поразмыслив, можно догадаться, что так создаётся просроченная ссуда. Чтобы устранить дублирование такого типа, можно воспользоваться рефакторингами Extract Class / Extract Subclass, либо Replace Constructors with Creation Methods:
Теперь у повторяющегося кода появилось имя, мы легко можем понять его назначение, а также изменить реализацию.
И ещё один случай - дублирование логики инициализации объекта в разных конструкторах:
Да, это простой случай. Но что, если конструкторов будет 5 и параметров побольше? Что, если надо добавить проверку параметров или другую логику? Знания о правильной инициализации объекта должны присутствовать в единственном экземпляре. И для этого тоже есть свой рефакторинг - Chain Constructors:
- Вступление
- Дублирование поведения
- Дублирование логики создания
- Дублирование условной логики
- Дублирование данных
Дублирование также встречается при создании объектов. Например, когда требуется совершить несколько одинаковых действий перед тем, как создаваемый объект можно будет использовать. И чем сложнее ритуал создания объекта, тем больше работы будет по изменению каждой копии этого ритуала.
Всем известно, что в компании DcMonald's ленивых, грубых и неопрятных сотрудников превращают в зомби. При этом в каждом из этих случаев приходится повторять непростой процесс изготовления шаманом порошка из рыбы фугу, отравления сотрудника и чтения заклинания:
foreach (var employee in _employeeRepository.FindLazyEmployees())
{
Bokor bokor = new Bokor();
Fish fish = new Pufferfish();
Powder ttx = bokor.PrepareTetrodotoxinFrom(fish);
employee.Drink(ttx);
bokor.CastSpellOn(employee);
Zombie zombie = new Zombie(employee);
// now we have good zombie and can use it
}
Любая ошибка в этой последовательности приведёт к утрате ценного сотрудника. Но избежать дублирования таких ценных знаний можно с помощью рефакторинга Move Creation Knowledge to Factory, либо Extract Method.
public class ZombieFactory
{
private Bokor _bokor;
public ZombieFactory(Bokor bokor)
{
_bokor = bokor;
}
public Zombie CreateZombieFrom(Employee employee)
{
Fish fish = new Pufferfish();
Powder ttx = _bokor.PrepareTetrodotoxinFrom(fish);
employee.Drink(ttx);
_bokor.CastSpellOn(employee);
return new Zombie(employee);
}
}
Теперь любой из отделов компании может создавать зомби, не вдаваясь в подробности сложного ритуала. И что самое главное - когда знания о создании зомби имеют единственное представление в системе, мы можем легко и быстро внести изменения в этот процесс (например, заменить ритуал вуду просмотром рекламы iPhone).
foreach (var employee in _employeeRepository.FindLazyEmployees())
{
Zombie zombie = _zombieFactory.CreateZombieFrom(employee);
// now we have good zombie and can use it
}
Другой случай - дублирование параметров конструкторов. Если периодически приходится повторять какое-то магическое сочетание параметров, значит в этом наборе параметров содержиться знание о каком-то особенном типе объекта. Например, я заметил, что в тестах несколько раз повторялись вызовы такого конструктора (первый параметр - размер ссуды, второй - дата возврата):
Loan loan = new Loan(100, DateTime.Now.AddDays(-1));
Немного поразмыслив, можно догадаться, что так создаётся просроченная ссуда. Чтобы устранить дублирование такого типа, можно воспользоваться рефакторингами Extract Class / Extract Subclass, либо Replace Constructors with Creation Methods:
public Loan CreateExpiredLoan(decimal amount)
{
return new Loan(amount, DateTime.Now.AddDays(-1));
}
Теперь у повторяющегося кода появилось имя, мы легко можем понять его назначение, а также изменить реализацию.
И ещё один случай - дублирование логики инициализации объекта в разных конструкторах:
public class Employee
{
private string _name;
private decimal _hourlyPayRate;
public Employee(string name)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentException("Name cannot be empty.");
_name = name;
_hourlyPayRate = 25M;
}
public Employee(string name, decimal hourlyPayRate)
{
_name = name; // oops, can be null
_hourlyPayRate = hourlyPayRate;
}
// etc.
}
Да, это простой случай. Но что, если конструкторов будет 5 и параметров побольше? Что, если надо добавить проверку параметров или другую логику? Знания о правильной инициализации объекта должны присутствовать в единственном экземпляре. И для этого тоже есть свой рефакторинг - Chain Constructors:
public class Employee
{
private string _name;
private decimal _hourlyPayRate;
public Employee(string name)
: this(name, 25M)
{
}
public Employee(string name, decimal hourlyPayRate)
{
if (String.IsNullOrEmpty(name))
throw new ArgumentException("Name cannot be empty.");
_name = name;
_hourlyPayRate = hourlyPayRate;
}
}
Комментариев нет:
Отправить комментарий