Вопрос о дизайне программы на C ++ - PullRequest
0 голосов
/ 28 июня 2010

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

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

И давайте назовем один дискретный способ изменения этих объектов Mutator. Mutators применяются один раз (обычно) , и у них есть какой-то внутренний метод, такой как apply(Target& target, ...), который мгновенно провоцирует изменение состояния объекта (на самом деле, это своего рода функциональные объекты ).

Они также могут быть легко ассимилированы в цепочки и применены один за другим (Mutator m1, m2, ...); они также могут быть получены из некоторого базового BasicMutator с помощью virtual void apply(...) метода.

Я ввел классы InnerMutator и ExplicitMutator, которые различаются с точки зрения доступа - первый из них может также изменить внутреннее состояние объекта и должен быть объявлен как друг (friend InnerMutator::access;).


В этих проектах моя логика работала следующим образом:

  1. Подготовьте доступных мутаторов, выберите, какие из них применить
  2. Создайте и установите object в определенное состояние
  3. foreach (mutator) mutator.apply(object);

Теперь вопрос.

Эта схема работает хорошо и (мне) выглядит как образец какого-то нестандартного, но полезного дизайна шаблон.

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

Можно ли решить эту ситуацию с помощью Mutators или вы совет какой-то альтернативный шаблон с тот же результат?

Спасибо.

Ответы [ 2 ]

5 голосов
/ 28 июня 2010

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

Почему вам нужно, например, объединять мутаторы?Можно просто написать:

template <class T>
void mutate(T& t)
{
    t.mutate1(...);
    t.mutate2(...);
    t.mutate3(...);
}

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

Я один разсделал что-то, что могло бы быть довольно похожим.Я сделал функциональные объекты, которые оператор & & мог бы объединить в суперфункциональные объекты, которые применили оба операнда (в порядке слева направо), чтобы можно было написать код вроде:

foreach(v.begin(), v.end(), attack && burn && drain);

Это было действительно аккуратно ив то время мне это казалось действительно умным, и это было довольно эффективно, потому что оно генерировало новые функциональные объекты на лету (без задействованных механизмов времени выполнения), но когда мои коллеги увидели это, они подумали, что я сошел с ума.Оглядываясь назад, я пытался втиснуть все в программирование в функциональном стиле, которое имеет свою полезность, но, вероятно, не следует чрезмерно полагаться на C ++.Было бы достаточно просто написать:

BOOST_FOR_EACH(Something& something, v)
{
    attack(something);
    burn(something);
    drain(something);
}

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

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

Что касается InnerMutator, я думаю, вам следует избегать этого, как чумы.,Наличие внешних классов-мутаторов, которые могут изменять внутренние элементы класса настолько напрямую, насколько это возможно, в данном случае лишает многие цели создания внутренних элементов.

3 голосов
/ 28 июня 2010

Не лучше ли просто создать эти Mutator методы для классов, которые они меняют? Если есть общая функциональность, которую нужно иметь нескольким классам, то почему бы не заставить их наследовать один и тот же базовый класс? Делая это, я справлюсь со всем внутренним дискомфортом мутатора, который я себе представляю.

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

...