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-машины могут иметь разное количество свойств, даже если они есть, эти свойства могут различаться в зависимости от контекста. Это нарушение принципа подстановки Лисков.
- Сильная связь между базой и наследниками, когда наследование данных редко является хорошей идеей.