У меня есть два базовых класса, Operation
и Trigger
. У каждого есть несколько подклассов, которые специализируются на определенных типах операций или триггеров. А Trigger
может вызвать конкретный Operation
. Хотя Operation
может быть вызвано конкретным Trigger
.
Мне нужно написать код, который сопоставляет данное Operation
с данным Trigger
(или наоборот), но я не уверен, где его поставить.
В этом случае код явно не принадлежит одному классу или другому классу. Таким образом, с точки зрения принципа единственной ответственности, я не уверен, куда должен принадлежать код.
Я вижу три варианта, которые все будут работать. Хотя 1 и 2 кажутся просто выбором семантики, 3 представляет совершенно другой подход.
- На триггере, например
bool Triggers(Operation o)
. - На операции, например
bool TriggeredBy(Trigger t)
. - В совершенно новом классе, который управляет отображением, например
bool MappingExists(Trigger t, Operation o)
.
Как мне решить, где разместить код общего сопоставления в соответствии с принципом единой ответственности?
Как управлять единой ответственностью, когда ответственность разделена?
Редактировать 1.
Таким образом, фактический код выглядит следующим образом. Все свойства, являются либо string
, Guid
, collection<string>
или enum
. Они в основном представляют собой небольшие фрагменты данных.
Изменить 2.
Причина возврата типа bool. Другой класс будет использовать коллекцию Trigger
и коллекцию Operation
. Нужно знать, где существует соответствие между a Trigger
и a Operation
. Он будет использовать эту информацию для создания отчета.
источник
Ответы:
Я думаю об этом так: как определяется, какая операция вызывает какой триггер запускается. Это должен быть алгоритм, который может изменяться со временем или развиваться в несколько алгоритмов. Включение его в классы Trigger или Operation означает, что эти классы смогут обрабатывать такие сценарии в будущем. Обратите внимание, что я не рассматриваю это так просто, как отображение, так как может быть что-то еще.
Мой выбор - создать класс с соответствующими методами, такими как GetOperationForTrigger (Trigger t). Это позволяет коду превращаться в набор таких классов, выбор которых может зависеть во время выполнения или других переменных (например, шаблон стратегии).
Обратите внимание, что основное предположение в этом направлении заключается в написании минимального кода (т.е. трех классов сегодня), но во избежание серьезного рефакторинга, если в будущем необходимо расширить функциональность, не делая предположения, что всегда будет только один способ определить, какой триггер вызывает какую операцию.
Надеюсь это поможет. Хотя ответ похож на user61852, рассуждения разные. В результате реализация будет отличаться (т. Е. Иметь явные методы вместо переопределения equals, поэтому число методов может развиваться с течением времени в зависимости от потребностей).
источник
Был там, сделал это.
Вариант № 3.
Я не знаю, какой язык вы будете использовать, но я буду использовать псевдокод, очень похожий на Java. Если ваш язык C #, вы, вероятно, имеете похожие интерфейсы и структуры.
Иметь класс или интерфейс Mapping:
equals()
методMapping
коллекций, поэтомуMapping
можно узнать, содержат ли они заданное отображение.equals()
методы.Comparable
, так что вы можете сортировать отчеты.Их вы можете просто положить сопоставления в коллекцию
Позже вы можете спросить:
источник
В настоящее время у вас есть класс A, знающий о классе B, и класс B, зная о классе A. Это очень сложная связь.
По определению A выполняет, по крайней мере, свою собственную операцию И проверяет, должен ли B выполняться. Обратное верно в отношении B. Какой бы класс ни назывался первым, он должен иметь возможность посмотреть на результат и посмотреть, нужно ли ему что-то еще делать.
Попробуйте разорвать эту связь, разбив ваши классы на более мелкие компоненты. Мне нравится помещать комментарий в начале каждого класса, объясняя простым языком, что он делает. Если вам нужно использовать такие слова, как «И», или если они идут в одном или двух предложениях, вам следует подумать о том, чтобы разбить их. Как правило, все, что после «и» должно быть в своем собственном классе
Также посмотрите, можете ли вы определить интерфейс, который охватывает функциональные возможности триггера и операции. Если вы не можете, это еще один признак того, что ваш класс становится слишком большим. Это также нарушит связь между вашими классами.
источник
Trigger
будет связано с aOperation
. Но именно так выглядят данные реального мира. Они связаны, потому что есть отображение, например, они должны знать друг о друге, чтобы иметь смысл.