Событийная архитектура ... бесконечный цикл - PullRequest
9 голосов
/ 11 сентября 2010

У меня есть управляемая событиями архитектура, где A ожидает изменения от B, а B ожидает изменения от C, а C ожидает изменения от A, формируя цикл.

Теперь, если B изменяется, то A запускает событие для C, которое запускается для B, которое запускается для A, которое запускается для C ... до бесконечности.

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

Ответы [ 5 ]

3 голосов
/ 11 сентября 2010

Составьте карту ваших зависимостей. Там не должно быть циклов. Циклические зависимости - хороший повод для реорганизации вашего кода.

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

2 голосов
/ 24 июля 2015

Как предотвратить подобные вещи при разработке систем, основанных на событиях?

  1. Вызывать событие, только когда состояние объекта действительно изменяется.

  2. Запретить изменение состояния объекта при возникновении события.

2 голосов
/ 18 апреля 2012

Кажется, все здесь говорят, что циклические зависимости плохие. В некотором смысле это правильно, и я стараюсь избегать статических циклических зависимостей практически любой ценой. Вы можете сделать это с инверсией управления, как показано в этом блоге: http://blog.schauderhaft.de/2011/07/17/breaking-dependency-cylces/

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

Первый взлом

Убедитесь, что каждое событие, вызванное другим событием, имеет ссылку на исходное событие (или важную информацию о нем, например, идентификатор). Когда вы обрабатываете событие, убедитесь, что оно не исходит от вас самих.

Pro: простота реализации; предотвращает рекурсию абсолютно

Другая половина взлома

Если вы работаете синхронно, вы можете установить флаг firingEvent до и сбросить его после. Игнорировать поступающие события, пока установлено firingEvent.

Pro: еще проще реализовать; абсолютно исключает рекурсию при работе в одном потоке

Семантическое богатое решение

Я убежден, что событие, в котором A срабатывает по какому-то внешнему триггеру, и событие, которое A запускает из-за того, что C запускает, - это на самом деле два разных события, или все три события на самом деле просто одно, которое может исходить из еще не идентифицированного источника. D. Или что-то в этом роде. Невозможно без информации сказать, что такое А, В и С и какие события они запускают. Если вы найдете правильные события, цикл исчезнет.

Pro: дизайн будет чище и будет содержать больше информации.

0 голосов
/ 18 апреля 2012

Я думаю, что это хороший вопрос.К сожалению, у меня нет полного ответа, но в этом посте есть пара хороших моментов:

как избежать бесконечного цикла в схеме наблюдателя?

Я не думаю, что ответ состоит в том, чтобы избежать циклических зависимостей, как предлагали другие.(Ну, это зависит от вашего определения «циклической зависимости».) Язык, подобный Java, будет использовать интерфейсы для минимизации циклических зависимостей типов во время компиляции, что часто является хорошей идеей.Например, класс представления в шаблоне MVC не «зависит» от вашего приложения, он знает только об интерфейсах с именами, такими как ValueChangedListener, ClickListener и т. Д. Но это не устраняет циклические соединениясреди объектов во время выполнения, что может привести к возникновению циклов событий.

Как упоминалось в другом связанном посте, некоторые циклы останавливаются в наборах инструментов пользовательского интерфейса, поскольку представление не будет запускать событие «изменено», еслиКонтроллер или модель "устанавливает" значение представления, равное его текущему значению.Но в других случаях, например при создании пользовательского представления более сложного фрагмента данных, может оказаться невозможным вычислить равенство текущих и новых данных.

0 голосов
/ 11 сентября 2010

Циклические зависимости действительно плохие. Я должен был записать ваш пост в терминах A, B и C, прежде чем он даже имел смысл для меня. Я думаю, что вы должны избавиться от этого. Если вы заглядываете в угол, это, вероятно, намного лучше, чем проблемы, с которыми вы можете столкнуться при циклических зависимостях.

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

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

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

Удачи!

...