Обычный инстинкт - удалить любое дублирование кода, которое вы видите в коде. Однако я оказался в ситуации, когда дублирование иллюзорно .
Чтобы описать ситуацию более подробно: я разрабатываю веб-приложение, и большинство представлений в основном одинаковы - они отображают список элементов, которые пользователь может прокручивать и выбирать, второй список, содержащий выбранные элементы, и «Сохранить». Кнопка, чтобы сохранить новый список.
Мне показалось, что проблема проста. Тем не менее, у каждого представления есть свои особенности - иногда вам нужно что-то пересчитать, иногда вы должны хранить некоторые дополнительные данные и т. Д. Я решил это, вставив хуки обратного вызова в основной логический код.
Между представлениями так много мелких различий, что они становятся все менее и менее обслуживаемыми, потому что мне нужно предоставить обратные вызовы для практически всех функций, и основная логика начинает выглядеть как огромная последовательность вызовов обратного вызова. В конце я не экономлю ни времени, ни кода, потому что у каждого представления есть свой собственный код, который выполняется - все в обратных вызовах.
Проблемы:
- различия настолько малы, что код выглядит почти одинаково во всех представлениях,
- Есть так много различий, что, когда вы смотрите на детали, код не похож
Как мне справиться с этой ситуацией?
Является ли ядро логики, состоящее полностью из вызовов обратного вызова, хорошим решением?
Или мне лучше дублировать код и отбросить сложность кода, основанного на обратном вызове?
источник
Ответы:
В конечном счете, вам необходимо принять решение о том, комбинировать ли подобный код для устранения дублирования.
Кажется, есть печальная тенденция принимать такие принципы, как «Не повторяйся», как правила, которые должны всегда соблюдаться. На самом деле, это не универсальные правила, а руководящие принципы, которые должны помочь вам продумать и разработать хороший дизайн.
Как и все в жизни, вы должны учитывать преимущества по сравнению с затратами. Сколько дублированного кода будет удалено? Сколько раз код повторяется? Сколько будет усилий, чтобы написать более общий дизайн? Сколько вы можете разработать код в будущем? И так далее.
Не зная вашего конкретного кода, это неясно. Возможно, есть более элегантный способ устранения дублирования (например, предложенный Линдой Джин). Или, возможно, просто не хватает истинного повторения, чтобы оправдать абстракцию.
Недостаточное внимание к дизайну является ловушкой, но также стоит остерегаться чрезмерного дизайна.
источник
Помните, что СУХОЙ - это знание . Не имеет значения, выглядят ли два фрагмента кода одинаково, одинаково или совершенно по-разному, важно то, чтобы в обоих из них можно было найти одно и то же знание о вашей системе.
Часть знаний может быть фактом («максимально допустимое отклонение от предполагаемого значения составляет 0,1%») или это может быть какой-то аспект вашего процесса («эта очередь никогда не содержит более трех элементов»). По сути, это любая отдельная часть информации, закодированная в вашем исходном коде.
Поэтому, когда вы решаете, является ли что-то дублированием, которое следует удалить, спросите, является ли это дублированием знаний. Если нет, то это, вероятно, случайное дублирование, и его извлечение в какое-то обычное место вызовет проблемы, когда позже вы захотите создать аналогичный компонент, в котором эта явно дублированная часть отличается.
источник
Рассматривали ли вы использовать шаблон стратегии ? У вас будет один класс View, который содержит общий код и подпрограммы, вызываемые несколькими представлениями. Дочерние элементы класса View будут содержать код, специфичный для этих экземпляров. Все они будут использовать общий интерфейс, который вы создали для View, и, таким образом, различия будут инкапсулированы и согласованы.
источник
Каков потенциал перемен? Например, наше приложение имеет 8 различных бизнес-областей с потенциалом 4 или более типов пользователей для каждой области. Представления настраиваются в зависимости от типа пользователя и области.
Первоначально это было сделано с использованием одного и того же представления с несколькими проверками здесь и там, чтобы определить, должны ли показываться разные вещи. Со временем некоторые сферы бизнеса решили делать совершенно разные вещи. В конце концов, мы в основном перешли на одно представление (частичное представление в случае ASP.NET MVC) на единицу функциональности на бизнес-область. Не все бизнес-сферы имеют одинаковую функциональность, но если один хочет функциональность, которая есть у другого, эта область получает свое собственное представление. Это намного менее громоздко для понимания кода, а также для тестируемости. Например, внесение изменений в одну область не вызовет нежелательных изменений в другой области.
Как упомянуто @ dan1111, это может привести к решению суда. Со временем вы можете узнать, работает ли он или нет.
источник
Одной из проблем может быть то, что вы предоставляете интерфейс (теоретический интерфейс, а не языковой компонент) только для одного уровня функциональности:
Вместо нескольких уровней в зависимости от того, сколько контроля требуется:
Насколько я понял, вы только выставляете интерфейс высокого уровня (A), скрывая детали реализации (другие вещи там).
Сокрытие деталей реализации имеет свои преимущества, и вы только что обнаружили недостаток - контроль ограничен, если вы явно не добавите функции для каждой отдельной вещи, которая была бы возможна при непосредственном использовании низкоуровневого интерфейса (ов).
Итак, у вас есть два варианта. Либо вы используете только низкоуровневый интерфейс, либо низкоуровневый интерфейс, потому что высокоуровневый интерфейс был слишком трудоемким для обслуживания, либо открываете интерфейсы как высокого, так и низкого уровня. Единственный разумный вариант - предложить интерфейсы как высокого, так и низкого уровня (и все, что между ними), при условии, что вы хотите избежать избыточного кода.
Затем, когда вы пишете еще одну из ваших вещей, вы смотрите на все доступные функции, которые вы написали так далеко (бесчисленные возможности, вы сами решаете, какие из них могут быть повторно использованы), и собираете их вместе.
Используйте один объект, где вам нужно мало контроля.
Используйте функциональность самого низкого уровня, когда должно произойти что-то странное.
Это также не очень черно-белый. Возможно, ваш большой класс высокого уровня МОЖЕТ разумно охватить все возможные варианты использования. Возможно, варианты использования настолько различны, что ничего, кроме примитивной функциональности самого низкого уровня, не достаточно. До вас, чтобы найти баланс.
источник
Уже есть другие полезные ответы. Я добавлю мой.
Дублирование плохо, потому что
Итак, суть в том, что вы не устраняете дублирование ради него или потому, что кто-то сказал, что это важно. Вы делаете это, потому что хотите уменьшить количество ошибок / проблем. В вашем случае, похоже, что если вы измените что-то в представлении, вам, вероятно, не нужно будет менять одну и ту же строку во всех других представлениях. Таким образом, у вас есть очевидное дублирование , а не фактическое дублирование.
Другой важный момент - никогда не переписывать с нуля то, что сейчас работает, только исходя из принципиальных соображений, как сказал Джоэл (вы, возможно, уже слышали о нем ....). Так что, если ваши взгляды работают, продолжайте улучшать шаг за шагом и не становитесь жертвой «единственной худшей стратегической ошибки, которую может совершить любая компания-разработчик программного обеспечения».
источник