2009-12-26 10 views
13

¿Hay una manera de evitar dependencias circulares, distintos de los módulos de mezcla, en una disposición como esta (que es una aplicación de ajedrez)cómo evitar dependencias circulares aquí

Descripción larga:

  • Existe el módulo Gui que importa un módulo ChessWidget;
  • ChessWidget simplemente envuelve el módulo ChessWorld e importa CellButton;
  • El módulo CellButton importa el módulo Cell;
  • El módulo ChessWorld importa Board (para representarlo) y Players (para notificarlos y recuperar sus movimientos);
  • El módulo Board importa el módulo Piece;
  • El módulo Piece importa el módulo Player;

Y aquí está el problema:

El Player módulo necesita saber sobre otros jugadores y el tablero, la importación de este modo ChessWorld!

Breve descripción:

El módulo World necesita saber sobre el módulo Player (aunque sea indirectamente por Board/Piece) y Player necesita saber acerca World.

La ayuda es muy apreciada.

PD: No es porque no pueda usar las dependencias circulares, sino porque son malas.

Respuesta

14

Sigue la Dependency inversion principle: introducir una interfaz, que ChessWorld implementos, y sobre el que Player depende - y/o uno que Player implementos y en el que Piece Depende (uno o ambos pueden ser apropiadas dependiendo de detalles sobre la naturaleza de la dependencia). A menudo esto va junto con Dependency Injection, y, si el dependiente necesita instanciar dinámicamente una cantidad de instancia de los dependientes, con Factory DPs.

+0

En mi humilde opinión, esto no resuelve la dependencia circular. Todavía está allí pero manejado por un contenedor DI y acoplado libremente a través de interfaces. – Cohen

+7

Las dependencias tienen una dirección, p. A-> B-> C-> A es circular, pero si inviertes cualquiera de las flechas ya no es un círculo. –

0

Voy a poner mi mano aquí y decir ... en mi humilde opinión es posible que haya sobrediseñado esto.

¿Por qué una pieza necesita tener conocimiento del jugador? Una pieza en ajedrez es negra o blanca, independientemente de quién la controle (juegue).

Mencionas "módulo de reproductor" y "módulo de pieza": ¿por qué son módulos separados? ¿Por qué no son solo clases de datos (objetos de dominio) juntas en el mismo módulo?

Si he analizado esto o no he podido entender cómo has construido tu juego, entonces, por supuesto, ignora lo que dije. OTOH tal vez sí leí las cosas ¿verdad?

+0

es porque es un sistema de variante de ajedrez, así que puede ser 2 tablas 7 jugadores y reglas werid – zaphnat

+0

Ahh bien, eso lo explicaría :) – slugster

2

Considera lo que realmente necesita cada objeto, y no lo que solo necesita en este momento.

Una pieza probablemente no necesite saber acerca de un reproductor: lo que necesita saber es algo a lo que puede enviar actualizaciones.

Por lo tanto, para ese ejemplo, cree una interfaz que represente un "PieceMessageListener" o algo así, y haga que el Reproductor lo implemente. Ahora bien, ambas concreciones dependen de una abstracción (ir a la regla de "las concreciones deben depender de las abstracciones, las abstracciones no deben depender de las concreciones").

5

Creo que el olor de una dependencia circular muestra más un problema arquitectónico/de diseño, que no debe resolverse mediante DI, límite tardío, acoplamiento libre o cualquier otra forma de capa de abstracción adicional. Aunque son todos mecanismos muy buenos, pero no resuelven el problema debajo.

Corto: Creo que el ChessWorld tiene demasiadas responsabilidades. Si los divide, probablemente encontrará que las dependencias son responsabilidades más adecuadas en un módulo separado.

Explicación larga: Intentaré dar un ejemplo de cómo volvería a configurarlo, aunque es difícil porque realmente no soy el dominio completo del problema.

NOTA: No estoy familiarizado con Java, así que puedo malinterpretar las implicaciones de importar y ajustar.

Pero como entiendo las dependencias ser algo como esto:

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

mi humilde opinión, el problema es que ChessWorld tiene demasiadas responsabilidades diferentes. Mantener la lista de jugadores probablemente sea mejor en un módulo separado como PlayerList, RegisteredUsers o OnlineUsers o algo similar. Después de que los Refactorizando depedencies cambiarían de la siguiente manera:

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

playerlist es probablemente algo que tendría en el módulo de reproductor. Ahora Chessworld depende del módulo de jugador y no en la otra dirección.

No estoy seguro si se ajusta perfectamente a su intención, pero estoy muy interesado en hablar de esto, así que por favor comenten.

+0

el problema es que el jugador necesita saber sobre el tablero e incluso otros jugadores. Utilicé una pieza de separación de solución y un módulo de jugador, usando "claves" o ID y luego haciendo una interfaz WorldInfo que World implementa y reproduce Player. De esa forma, importar Tablero, no implica pieza importada. – zaphnat

Cuestiones relacionadas