как избежать круговых зависимостей здесь - PullRequest
15 голосов
/ 26 декабря 2009

Есть ли способ избежать круговых зависимостей, кроме модулей микширования, в такой схеме (это шахматное приложение)

Длинное описание:

  • Существует модуль Gui, который импортирует модуль ChessWidget;
  • ChessWidget просто упаковывает модуль ChessWorld и импортирует CellButton;
  • Модуль CellButton импортирует модуль Cell;
  • Модуль ChessWorld импортирует Board (чтобы представить его) и Players (чтобы уведомить их и получить их ходы);
  • Модуль Board импортирует модуль Piece;
  • Модуль Piece импортирует модуль Player;

И ЗДЕСЬ ПРОБЛЕМА:

Модуль Player должен знать о других игроках и игровом поле, поэтому импортирует ChessWorld!

Краткое описание:

Модуль World должен знать о модуле Player (даже косвенно Board / Piece), а Player должен знать о World.

Помощь очень ценится.

PS: Не потому, что я не могу использовать круговые зависимости, а потому, что они злые.

Ответы [ 4 ]

15 голосов
/ 26 декабря 2009

Следуйте принципу обращения зависимостей : введите интерфейс, который реализует ChessWorld и от которого зависит Player - и / или тот, который реализует Player и от которого зависит Piece (один или оба могут быть уместными в зависимости от деталей характера зависимости). Это часто происходит вместе с Внедрение зависимостей , и, если зависимому необходимо динамически создавать экземпляры нескольких экземпляров зависимых лиц, с Factory DP.

6 голосов
/ 07 января 2010

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

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

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

ПРИМЕЧАНИЕ. Я не знаком с Java, поэтому могу неправильно понять значение импорта и переноса.

Но, как я понимаю, зависимости выглядят примерно так:

Gui <- ChessWidget <- ChessWorld <- CellButton <- Cell
                                 <- Board <- Piece <- Player
                                 <- Players <- ChessWorld

ИМХО, проблема в том, что в ChessWorld слишком много разных обязанностей. Поддерживать список игроков, вероятно, лучше в отдельном модуле, таком как PlayerList, RegisteredUsers или OnlineUsers или что-то подобное. После этого рефакторинга ваши зависимости будут меняться следующим образом:

 Gui <- ChessWidget <- ChessWorld <- CellButton <- Cell
                                  <- Board <- Piece <- Player
                                  <- Playerlist <- Player

PlayerList - это, вероятно, то, что вы бы имели в модуле плеера. Теперь Chessworld зависит от модуля игрока, а не в другом направлении.

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

3 голосов
/ 26 декабря 2009

Подумайте, что действительно нужно каждому объекту, а не то, что ему нужно в данный момент.

Пьесу, вероятно, не нужно знать об Игроке - о чем он должен знать, это то, на что он может отправлять обновления.

Итак, для этого примера создайте интерфейс, представляющий «PieceMessageListener» или что-то подобное, и пусть Player реализует это. Теперь оба конкреции зависят от абстракции (переходя к правилу «конкреции должны зависеть от абстракций, абстракции не должны зависеть от конкреций»).

0 голосов
/ 26 декабря 2009

Я собираюсь засунуть руку сюда и сказать ... ИМХО, возможно, вы переоценили это.

Почему часть должна знать игрока? Шахматная фигура - черная или белая, независимо от того, кто ее контролирует (играет).

Вы упомянули "модуль модуля" и "модуль модуля" - почему они являются отдельными модулями? Почему они не просто классы данных (доменные объекты) вместе в одном модуле?

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

...