Cómo resolver dependencias de paquetes circulares

11

Estoy refactorizando una base de código grande donde la mayoría de las clases se encuentran en un paquete. Para una mejor modularidad, estoy creando subpaquetes para cada funcionalidad.

Yo recuerdo haber aprendido en alguna parte que un gráfico de dependencias paquete no debe tener bucles, pero no sé cómo resolver el siguiente problema: Figurees en el paquete figure, Layoutes en el paquete layout, Layoutrequiere la cifra para llevar a cabo el diseño, por lo que el paquete layoutdepende de paquete figure. Pero, por otro lado, un Figurepuede contener otros Figures dentro de él, que tienen el suyo propio Layout, lo que hace que el paquete figuredependa del paquete layout.

He pensado en algunas soluciones, como crear una Containerinterfaz que Figureimplemente y ponerla en el Layoutpaquete. ¿Es esta una buena solución? ¿Alguna otra posibilidad?

Gracias

vainolo
fuente
Sus módulos (por ejemplo, diferentes jarras) no pueden tener dependencias circulares. Los paquetes PUEDEN y con frecuencia TENEN dependencias circulares, siempre que pertenezcan al mismo módulo.
lorus
@lorus ¿Entonces esto no es un problema de diseño?
vainolo
2
No, no es. Los paquetes normalmente son solo espacios de nombres. Esto puede cambiar solo cuando se usan para otra cosa, por ejemplo, para cambiar la visibilidad de su contenido en el entorno OSGi. No te molestes de lo contrario.
lorus
1
Tenga en cuenta que muchas autoridades condenan las dependencias cíclicas, y a veces con buenas razones, pero antes de refactorizar ciegamente, debe asegurarse de que una de esas razones realmente se aplique a usted. Si la estructura del paquete no le está causando problemas y, en buena conciencia, no puede ver por qué en el futuro no cambiará algo tan fundamental solo para satisfacer los valores arquitectónicos abstractos.
Kilian Foth

Respuestas:

9

Debe pensar en la Inversión de control

Básicamente, define una interfaz para usted Layoutque se encuentra en algún lugar cerca de su clase Layout en un paquete propio, por lo que tendría un paquete de implementación y un paquete de interfaz pública; por ejemplo, llámelo Layoutable(no sé si eso es inglés correcto). Ahora: Layout no implementará esa interfaz sino la Figureclase. Del mismo modo, crearía una interfaz para Figure, Drawablepor ejemplo.

Entonces

my.public.package.Layoutable
my.implementation.package.Layout
my.public.package.Drawable
my.implementation.package.Figure

Ahora: la Figura implementa Layoutable y, por lo tanto, puede ser utilizada por Layout y (todavía no estoy seguro si eso es lo que quería): Layout implementa Drawable y se puede dibujar en una Figura. El punto es que la clase que expone algún servicio lo hace disponible a través de una interfaz (aquí: Layout and Layoutable): la clase que quiere usar ese servicio tiene que implementar la interfaz.

Entonces tendrías algo así como un objeto creador que une a ambos. Por lo tanto, el creador tendría una dependencia Layouttanto como a Figure, pero Layouty Figureellos mismos serían independientes.

Esa es la idea aproximada.

Una excelente fuente de soluciones a estos problemas es el libro Java Application Architecture de Kirk Knoernschild.

michael_s
fuente
¿No es esto lo mismo que la Containerinterfaz como se sugiere en la pregunta?
vaughandroid
Sí, y no, no los pondría a ambos en el mismo paquete que dije. Y no había mucha teoría detrás de esto. Y en este caso no es suficiente hacerlo por un lado, tendrá que hacerlo por ambos lados. ¿Bien?
michael_s
Vaya, me perdí un poco en la pregunta original sobre Containerir en el mismo paquete Layout. Eso no funcionaría, mientras que su solución sí.
vaughandroid
ah, bueno, parecía haber perdido la parte del Contenedor cuando estaba hackeando, debería haberlo llamado Contenedor;)
michael_s
0

No tengo muy claro qué Figurees, pero ¿quizás debería estar en el mismo paquete que Layout?

Su Containersolución de interfaz propuesta no funcionaría, a menos que coloque la Containerinterfaz en un tercer paquete, aún tendría una dependencia circular entre los dos paquetes. Vea la respuesta de michael_s para algo que funcionaría.

Otra cosa, como han mencionado otros, probablemente nunca será un problema. Que sólo va a tener problemas en el futuro si Figurey Layoutquieren estar en distintos módulos . Puede lidiar con esto cuando sea necesario, pero dado que las dos clases parecen estar estrechamente relacionadas, parece muy poco probable.

vaughandroid
fuente