должен ли шаблон наблюдателя включать в себя обнаружение бесконечного цикла? - PullRequest
4 голосов
/ 08 июня 2009

Быстро просматривая книгу GoF и Head First Design Patterns, кажется, что нет упоминания об обнаружении и обработке бесконечного цикла для шаблона Observer?

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

Ответы [ 6 ]

10 голосов
/ 08 июня 2009

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

Традиционное использование Observer-Observable в многоуровневых архитектурах - например, когда контроллеры представления наблюдают за объектами модели или когда обработчики событий наблюдают компоненты GUI - и здесь график не будет циклическим, поэтому нет риска бесконечности цикл.

Я, наверное, должен объяснить о пункте (d), о различных видах изменений. Я имею в виду, что если у вас есть ситуация, когда, скажем, UserInputEvent может вызвать ModelStateChangedEvent, а ModelStateChangedEvent может вызвать WidgetUpdateEvent, который сам по себе ничего не может запустить, то даже если наблюдатели образуют циклический граф, вы никогда не сможете получить бесконечные циклы, потому что есть только конечное количество этапов в последовательности событий. По сути, события образуют ациклический граф, даже если наблюдатели этого не делают. Если, однако, ModelStateChangedEvent может вызвать другое ModelStateChangedEvent, то у вас есть риск циклов.

Если вы действительно не можете избежать риска циклов, то вы можете украсть идею у Jon Postel и сделать так, чтобы каждое уведомление о событии содержало целочисленный счетчик времени жизни. Когда Observable транслирует «оригинальное» событие, означающее что-то, что приходит извне сети наблюдателей и запускает каскад событий внутри него, он устанавливает счетчик на некоторое подходящее начальное значение TTL. Когда Observable реагирует на событие, передавая другое событие, он использует TTL на единицу меньше, чем у инициирующего события. Когда наблюдатель получает уведомление с TTL, равным нулю, он игнорирует его. Это предотвратит бесконечные циклы, но также помешает Наблюдателю «правильно» реагировать на некоторые события, поэтому эту идею следует использовать с осторожностью. Я настоятельно рекомендую, чтобы каскад событий, достигающий предела TTL, рассматривался как результат ошибки программирования и регистрировался и передавался так же, как если бы вы обрабатывали что-то вроде NullPointerException или ошибки подтверждения.

4 голосов
/ 08 июня 2009

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

1 голос
/ 01 октября 2009

Странно, что люди с высоким рейтингом дают такие бесполезные ответы. вздох

Циклы событий случаются и происходят ОЧЕНЬ часто в программировании GUI. Мне кажется, что более или менее стандартное решение состоит в том, чтобы разорвать циклы путем фильтрации дублированных или избыточных событий или ввести какой-либо метод, который не вызывает события.

1 голос
/ 08 июня 2009

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

1 голос
/ 08 июня 2009

Является ли вообще проверка бесконечного цикла эквивалентной проблеме остановки Тьюринга? Если это так, то это невозможно.

1 голос
/ 08 июня 2009

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

Это случай Не делай этого тогда.

...