I will not repeat myself
I will not repeat myself
I will not repeat myself
I will not repeat myself
I will not repeat myself
I will not repeat myself

Представьте, что у вас есть 10 функций, разбросанных по коду, и из-за изменения требований вам нужно изменить поведение этих функций. Есть большая вероятность, что вы могли пропустить изменение одной или двух из этих функций, и теперь вы создали аномалию в своей системе. DRY — это не повторяться.

  • Повторяющийся код подвержен ошибкам
  • Создано из Pragmatic Programmer Энди Хантом, Дэйвом Томасом.
  • Каждая часть информации должна иметь единственное однозначное представление в системе.
  • Этот принцип можно применить к любому аспекту программирования, включая документацию.

Общие нарушения

  • Магические строки или любые магические значения
//bad
if(ErrorCode == 99)
{
}
//good
const int ConnectionError = 99;
if(ErrorCode == ConnectionError)
{
}
  • Дублирование логики в нескольких местах
//bad
class PosOperations
{
   public void Initiate()
   {
       var pos = New Pos();
       pos.SendCommand(1);
       pos.SendCommand(3);
       pos.SendCommand(9);
   }
   public void Terminate()
   {
       var pos = New Pos();
       pos.SendCommand(1);
       pos.SendCommand(5);
       pos.SendCommand(9);
   }
}
//better
class PosOperations
{
   const int beginCommand = 1;
   const int initiatePos = 3; 
   const int terminatePos = 5;
   const int endCommand = 9;
   public void Initiate()
   {
       var pos = New Pos();
       pos.SendCommand(beginCommand);
       pos.SendCommand(initiatePos);
       pos.SendCommand(endCommand);
   }
   public void Terminate()
   {
       var pos = New Pos();
       pos.SendCommand(beginCommand);
       pos.SendCommand(terminatePos);
       pos.SendCommand(endCommand);
   }
}
//good
class PosOperations
{
   const int beginCommand = 1;
   const int initiatePos = 3; 
   const int terminatePos = 5;
   const int endCommand = 9;
   public void Initiate()
   {
       Execute(initiatePos);
   }
   public void Terminate()
   {
       Execute(terminatePos);
   }
   public void Execute(int command)
   { 
       var pos = New Pos(); 
       pos.SendCommand(beginCommand); 
       pos.SendCommand(command);
       pos.sendCommand(endCommand);
   }
}
  • Повторяющиеся операторы if-else и/или switch разбросаны по кодовой базе.

Дублирующийся код — это всегда плохо

В некоторых случаях дублирование кода может быть хорошей идеей.

public class PosMachineABC
{ 
   public string MachineName; 
   public string Port; 
   public void Order(){};
}
public class PosMachineXYZ
{ 
   public string MachineName; 
   public string Port; 
   public void CheckOut(){};
}
//Refactored to conform DRY principle
public class Pos
{   
   public string MachineName; 
   public string Port;
}
public class PosMachineABC : Pos
{ 
   public void Order(){};
}
public class PosMachineXYZ : Pos
{ 
   public void CheckOut(){};
}

Этот рефакторинг на самом деле плохая идея по нескольким причинам, даже если кажется, что он соответствует принципу DRY.

  • Все Pos-машины могут иметь разное количество свойств, даже если они есть, эти свойства могут различаться в зависимости от контекста. Это нарушение принципа подстановки Лисков.
  • Сильная связь между базой и наследниками, когда наследование данных редко является хорошей идеей.