Класс (классы) помощника по сравнению с функциональным наследованием. Лучшая практика

У меня есть классы команд тот интерфейс ICommand { Execute } реализации. Несколько команд имеют дублирующиеся части кода. У меня есть несколько опций как к DRY:

  • Создайте статический класс (классы) помощника и переместите дублирующий код туда
  • Создайте наследование команд с защищенными вспомогательными методами

Что Вы предложили бы и почему?

ДОБАВЛЕННОЕ Спасибо все, кто ответил, много ответов, были подобны и полезны!

7
задан Andrew Florko 18 June 2010 в 03:32
поделиться

6 ответов

Это полностью зависит от характера вашего дублированного кода.

Каковы входы / выходы ваших вспомогательных функций? Оперируют ли они логически связанным набором переменных? Тогда - да, вам лучше создать базовый класс с этими переменными в качестве членов и соответствующим набором вспомогательных функций.

В противном случае, если параметры в ваших вспомогательных функциях не согласованы, вы бы все равно реализовали эти функции как статические, верно? Я не вижу причин усложнять вещи с наследованием в этом случае, и я бы сделал это только с помощью вспомогательных функций (или, если ваш язык не рассматривает функции как граждан первого класса, используйте статический вспомогательный класс).

3
ответ дан 6 December 2019 в 12:46
поделиться

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

Если у вас есть код, который является общим только для подмножеств несвязанных команд, и создание иерархии наследования вынудило бы установить несуществующую связь, то добавление «вспомогательного» класса (нестатического, если возможно , чтобы улучшить тестируемость) было бы совершенно естественным способом решить эту проблему. Вы можете обнаружить, что можете естественным образом сгруппировать "вспомогательные" методы в отдельные классы. Например, если несколько методов должны взаимодействовать с вашей подсистемой аутентификации, у вас может быть AuthenticationMediator для этих методов. Я также не вижу никаких противоречий между тем и другим.

1
ответ дан 6 December 2019 в 12:46
поделиться

Вместо статических классов другой вариант - поместить общий код в новый класс и использовать внедрение зависимостей для внедрения вспомогательного класса в команды. Это также соответствует понятию композиции над наследованием.

5
ответ дан 6 December 2019 в 12:46
поделиться

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

3
ответ дан 6 December 2019 в 12:46
поделиться

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

Наслаждайтесь!

3
ответ дан 6 December 2019 в 12:46
поделиться

Если логика работает с членами интерфейса , а не с членами реализации , то рекомендуется написать вспомогательный метод [или метод расширения].

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;
}

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

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

Надеюсь, это поможет! :)

0
ответ дан 6 December 2019 в 12:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: