Как удалить дублирующийся код (в общем)?

10

На языке ОО (например, но не только на Java), как вы исправляете дублирующий код в зависимости от области его появления? Я бы начал с (например)

  • в том же классе (области действия) выполнить рефакторинг Извлечь метод (исправить)
  • в классах той же иерархии (области видимости) выполнить Extract Method и Pull Up (исправить)
  • ...
Питер Кофлер
источник
взгляните на пример реализации принципа СУХОЙ (не повторяйте себя) с одним и тем же классом: geekswithblogs.net/chrisfalter/archive/2008/03/07/…
NoChance
Оригинальный вопрос на SO ( stackoverflow.com/questions/7380946/… ) был закрыт. Поэтому я перенес это сюда.
Питер Кофлер

Ответы:

8

Недавно я нашел хороший ответ на свой вопрос в «Чистом коде» дяди Боба, которым хочу поделиться. Он различает три типа дублирования

Части идентичного кода должны быть заменены одним методом. Таким образом, исправление будет состоять в том, чтобы извлечь метод и делегировать обычное поведение.

  • в том же методе выполните Извлечение локальной переменной и повторно используйте ее.
  • в том же классе выполнить рефакторинг Extract Method.
  • в классах той же иерархии Извлечь метод и потянуть его. Иерархия может быть создана, чтобы найти место для методов.
  • в классах отдельных иерархий используют делегирование новым объектам.
  • Если методы не нуждаются в каком-либо включающем состоянии, тогда может быть применен шаблон «lib» (это контейнер для статических методов, обычно вызываемых SthUtilили SthLib).

случаи switch/caseи if/elseкоторые всегда проверяют один и тот же набор условий .

  • Их следует заменить полиморфизмом.

Модули, которые реализуют аналогичные алгоритмы . Их труднее всего найти, поскольку их не может обнаружить ни один клон-детектор.

  • Так как область применения больше, используются шаблоны дизайна. Шаблонный шаблон Метод проектирования может применяться для алгоритмов внутри иерархии классов.
  • Шаблон разработки стратегии может применяться для любого алгоритма, который используется в разных местах.

Также допустимый момент, упомянутый Одедом, при работе с разными версиями библиотек

  • консолидировать на одной версии. Шаблон дизайна фасада может помочь здесь.

В конце концов, лучшее предложение, чтобы ответить на мой вопрос:

Метод повторного использования кода, используемый в ОО-языках, - это объекты.

Питер Кофлер
источник
5

В общем, объедините дублирующийся код в одном месте и убедитесь, что исходный сайт дублирования вызывает объединенное место.

В ваших примерах в классе это будет извлеченный метод, а в наборе классов - метод pull-up в базовом классе.

В коде копирования-вставки это будет означать удаление дубликатов и обеспечение того, чтобы все пользователи теперь использовали единственную копию (на каком бы уровне это ни было).

При работе с разными версиями библиотек объединяйтесь в одну версию (если это возможно).

Одед
источник
Разве это не был бы метод "раскрытия", если он в базовом классе? Я всегда представляю базовые классы как физически под производными классами.
Дейв Най
Правильное название из книги «Рефакторинг» - «подтяни».
Питер Кофлер
1

Я думаю, что это открытый вопрос, но он также зависит от состояния кода. Я имею в виду, вы можете терпеть дубликата кода немного в зависимости от контекста. Правило трех хорошо для этого вопроса.

Правило Три В первый раз, когда вы делаете что-то, вы просто делаете это. Во второй раз, когда вы делаете что-то подобное, вы вздрагиваете при дублировании, но вы все равно делаете дубликат. В третий раз вы делаете что-то подобное, вы рефакторинг.

Несмотря на то, что это в значительной степени спорно, это сообщение также рассматривает случаи , когда вы выдерживающие повторяющийся код.

Уилл Хьюз
источник
1
+1 о «правиле трех». Я всегда поражаюсь, насколько это применимо.
Энди Манго
1
Это не отвечает на вопрос как .
Ян Догген