СУХОЙ не связанный, но почти идентичный код

34

У меня есть некоторый код, который почти идентичен, но использует абсолютно разные типы, без наследования между ними, в основной переменной. В частности, я пишу анализатор с Roslyn для C # и VB.NET следующих типов:

Microsoft.CodeAnalysis.CSharp.Syntax.AttributeSyntax Microsoft.CodeAnalysis.VisualBasic.Syntax.AttributeSyntax

Мне интересно, если из-за того, что код выполняет одно и то же, я должен сохранить его как можно более СУХИМЫМ, разделив как можно меньше на отдельные (но идентичные, отличные от типа) методы, или полностью разделив его, потому что эти два метода не связанные и будущие изменения могут заставить одну версию изменить, но не другую (хотя это маловероятно)?

Изменить: Примерно через год я столкнулся с той же проблемой, и команда Roslyn помогла мне решить ее: написать базовый класс, который принимает дженерики и имеет TAttributeSyntaxпараметр, который выполняет большую часть работы. Затем напишите производные классы с минимальным объемом данных, которые требуют определенного типа.

Hosch250
источник
Будет ли это работать для создания вашего собственного интерфейса AttributeSyntax, который обернет существующие классы, но даст вам наследование, которое концептуально должно быть там?
Уинстон Эверт
7
Извините, если это очевидно, но универсальные шаблоны существуют, поэтому вам не нужно повторяться для идентичного кода, но для типа. Если это не то, что вы имели в виду, пожалуйста, не обращайте внимания.
Дэвислор
@Lorehead Обычно я делаю это, но это единственный метод, которому передается тип, который содержит узел в качестве полезной нагрузки от внутреннего метода, который я не контролирую.
Hosch250
@WinstonEwert Я посмотрю на это. Однако я не уверен, что хочу сделать это для всех типов C # / VB.NET.
Hosch250
1
Рефакторинг налагает много компромиссов, а иногда и парадоксов. Например, слабая связь по отношению к СУХОЙ или коротким функциям, но многие из них, по сравнению с более длинными функциями, и немногие из них. В конце концов, это сложный зверь: ваша цель - удобочитаемость и ремонтопригодность. Вы должны думать как аватар, который видит ваш код впервые. А иногда вы просто пытаетесь увидеть, что лучше. К сожалению, идеальный рефакторинг невозможен.
Френель

Ответы:

111

Вы не делаете СУХОЙ, потому что кто-то написал это в книге где-то, что это хорошо делать, вы делаете СУХОЙ, потому что это на самом деле имеет ощутимые преимущества.

Именно из этого вопроса:

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

Однако умные программисты часто доводят DRY до крайности. Иногда, чтобы не повторяться, вы должны создавать абстракции, настолько тупые, что ваши товарищи по команде не могут следовать за ними. Иногда структура двух вещей только смутно похожа, но достаточно различна. Если doStuff1-4 отличаются настолько, что рефакторинг их, чтобы они не повторялись, заставляет вас писать неестественный код или делать умные откаты кодирования, которые заставят вашу команду смотреть на вас, тогда, возможно, будет хорошо повторить себя. Я наклонился назад, чтобы не повторяться пару раз неестественным образом, и пожалел о конечном продукте.

Так что, в принципе, не думайте: «О, чувак, этот код очень похож, может быть, я должен рефакторинг, чтобы не повторяться». Подумайте: «Разве рефакторинг, чтобы заставить эту кодовую базу повторно использовать общие элементы, делает код более понятным или менее обслуживаемым ?» Затем выберите тот, который делает его более ремонтопригодным.


При этом, учитывая SRP и просто пытаясь иметь небольшие гибкие классы в целом, может иметь смысл проанализировать ваш код по этой причине , разбить на части фрагменты поведения, которые используют универсальные типы (вы сказали, что они идентичны, кроме типа), в маленькие классы. Затем вы обнаружите, что некоторые из этих классов на самом деле полностью идентичны (а не просто идентичны), и затем вы можете создать инструментарий на случай, если захотите добавить Microsoft.CodeAnalysis.CPlusPlus.Syntax.AttributeSyntax.

durron597
источник
32
TL; DR - DRY - это средство для достижения цели. Сосредоточьтесь на конце, а не на средствах. Если бы я мог дважды проголосовать за Lego Man, я бы сделал это.
Одно важное замечание: если вы делаете повторяться, всегда упоминают в комментарии все другие места , которые должны быть посещены , когда повторяющиеся изменения кода. Это не только снижает вероятность рассинхронизации, но и служит индикатором того, какую боль от обслуживания вызывает у вас повторение.
Сион