У меня есть классы команд тот интерфейс ICommand { Execute } реализации. Несколько команд имеют дублирующиеся части кода. У меня есть несколько опций как к DRY:
Что Вы предложили бы и почему?
ДОБАВЛЕННОЕ Спасибо все, кто ответил, много ответов, были подобны и полезны!
Это полностью зависит от характера вашего дублированного кода.
Каковы входы / выходы ваших вспомогательных функций? Оперируют ли они логически связанным набором переменных? Тогда - да, вам лучше создать базовый класс с этими переменными в качестве членов и соответствующим набором вспомогательных функций.
В противном случае, если параметры в ваших вспомогательных функциях не согласованы, вы бы все равно реализовали эти функции как статические, верно? Я не вижу причин усложнять вещи с наследованием в этом случае, и я бы сделал это только с помощью вспомогательных функций (или, если ваш язык не рассматривает функции как граждан первого класса, используйте статический вспомогательный класс).
Вероятно, здесь нет правильного / неправильного ответа, хотя я полагаю, вы, безусловно, могли бы реализовать его плохо. Вероятно, это очень зависит от ваших реальных требований и того, насколько ваши команды связаны друг с другом. Как правило, я бы, вероятно, выбрал реализацию базового класса и иерархию наследования, предполагая, что команды связаны, а код относится непосредственно к самим командам, а не к некоторому внешнему объекту, который должен быть классом сам по себе. Конечно, они связаны тем, что являются командами, и базовый класс может это отразить.
Если у вас есть код, который является общим только для подмножеств несвязанных команд, и создание иерархии наследования вынудило бы установить несуществующую связь, то добавление «вспомогательного» класса (нестатического, если возможно , чтобы улучшить тестируемость) было бы совершенно естественным способом решить эту проблему. Вы можете обнаружить, что можете естественным образом сгруппировать "вспомогательные" методы в отдельные классы. Например, если несколько методов должны взаимодействовать с вашей подсистемой аутентификации, у вас может быть AuthenticationMediator для этих методов. Я также не вижу никаких противоречий между тем и другим.
Вместо статических классов другой вариант - поместить общий код в новый класс и использовать внедрение зависимостей для внедрения вспомогательного класса в команды. Это также соответствует понятию композиции над наследованием.
Если есть вероятность, что дублирующая логика может понадобиться и другим классам вне иерархии, я бы поместил ее в статические вспомогательные классы. В противном случае - в базовый класс с защищенным наследованием.
На мой взгляд, я бы поместил повторяющийся код в базовый класс, если он относится только к этой иерархии классов и не будет использоваться вне ее. Если есть возможность использовать код в разных классах, переместите его во вспомогательный класс в общем проекте.
Наслаждайтесь!
Если логика работает с членами интерфейса , а не с членами реализации , то рекомендуется написать вспомогательный метод [или метод расширения].
public IRandom
{
byte NextByte ();
}
public static class IRandomExtensions
{
// logic that acts against public interface IRandom
// may be applied to all implementations
public static int GetNextUnbiasedInteger (this IRandom random) { }
public static IEnumerable<T> Shuffle<T> (
this IRandom random,
IEnumerable<T> items) { }
}
Если бизнес-логика работает против членов реализации ,
public class SomeCommand : ICommand
{
// an implementation-specific member, NOT a member
// of ICommand
public int SomeControlCount { get; set; }
}
// a method that references implementation-speciic
// details. where should this go?
public void DoSomething ()
{
SomeCommand command;
int count = command.SomeControlCount;
}
, то, вероятно, нам следует более жестко привязать ее к реализующему классу. Если это достаточно частое явление, тогда может иметь смысл базовый класс.
Лично сложные иерархии доставляют больше проблем, чем они того стоят, используйте свое собственное суждение в отношении ремонтопригодности, удобочитаемости и повторного использования, и все должно быть в порядке!
Надеюсь, это поможет! :)