5

Actualmente estoy experimentando con la inversión de guice de Google en el contenedor de control. Anteriormente tenía singletons para casi cualquier servicio (base de datos, directorio activo) que mi aplicación usara. Ahora refactoreé el código: todas las dependencias se dan como parámetros a los constructores. Hasta aquí todo bien. Ahora la parte más difícil es con la interfaz gráfica de usuario. Me enfrento a este problema: tengo una tabla (JTable) de productos envueltos en un ProductFrame. Doy las dependencias como parámetros (EditProductDialog).¿La inyección de dependencia es solo para objetos de tipo de servicio y singletons? (y NO para GUI?)

@Inject 
public ProductFrame(EditProductDialog editProductDialog) { 
    // ... 
} 

// ... 

@Inject 
public EditProductDialog(DBProductController productController, Product product) { 
    // ... 
} 

El problema es que guice no puede saber qué producto que he seleccionado en la tabla, por lo que no puede saber lo que inyectar en el EditProductDialog.

Dependency Injection es bastante viral (si modifico una clase para usar la inyección de dependencia también tengo que modificar todas las demás clases con las que interactúa) entonces mi pregunta es ¿debo instanciar directamente EditProductDialog? Pero luego tendría que pasar manualmente DBProductController a EditProductDialog y también tendré que pasarlo al ProductFrame y todo esto se reducirá a no usar ninguna inyección de dependencia.

¿O mi diseño es defectuoso y por eso no puedo adaptar el proyecto a la inyección de dependencia?

Dame algunos ejemplos de cómo usaste la inyección de dependencia con la interfaz gráfica de usuario. Todos los ejemplos que se encuentran en Internet son ejemplos muy simples en los que se usan algunos servicios (principalmente bases de datos) con inyección de dependencia.

Respuesta

1

Según lo que veo en su código de muestra, no estoy seguro de pasar Product a EditProductDialog es el mejor diseño, esto significa que no puede reutilizar el mismo cuadro de diálogo para 2 productos diferentes.

En general, prefiero añadir un setProduct(Product)-EditProductDialog con el fin de: reutilización

  • habilitación del mismo cuadro de diálogo
  • permitir la inyección de constructor del propio diálogo

Además, también puede, si desea mantener los argumentos de constructor actuales, echar un vistazo a Guice Assisted Injection, lo que le permitiría tener todas las dependencias inyectadas en el constructor, mientras sigue proporcionando el producto explícitamente .

Finalmente, es posible que desee echar un vistazo a Guts-GUI, un marco de código abierto para crear GUIs de Swing con Guice (todavía en funcionamiento, pero listo para usar a partir de hoy). Tiene una aplicación de muestra que contiene ejemplos de diálogos reutilizables.

+0

Estaba pensando en la misma solución, pero no estaba seguro de que sea el mejor enfoque, porque con la inyección de dependencias "necesitas declarar tus dependencias" (en el constructor en el caso de guice). Pero esta parece ser la mejor solución en este momento. Gracias por los enlaces. ¡Definitivamente son útiles! –

+0

Otro enfoque que estaba pensando es utilizar guice solo para servicios (base de datos, etc.) y para las clases gui solo para pasar el inyector como parámetro. Tampoco estoy seguro de este enfoque. –

+1

¡No hagas eso! El uso directo de Guice Injector en el código de la aplicación debe considerarse un olor de diseño, esto es contrario a "Inversión de control" y se parece al "patrón de fábrica". Solo los marcos o las bibliotecas pueden tener esta necesidad y solo en oportunidades excepcionales. – jfpoilpret

0

Creo que el uso de Guice en el desarrollo de la GUI de escritorio funciona mejor para la configuración del servicio.

Con este enfoque, deberá configurar los ámbitos de interacción correctamente para poder inyectar correctamente los objetos de dominio de usuario que se seleccionan en la GUI en los servicios.

En su lugar, puede hacer que los datos de selección sean accesibles desde un servicio que se inyecta como un servicio singleton a otros servicios que requieren datos de selección.

El SelectionService podría ser algo como esto

public interface SelectionService { 

    Product getSelectedProduct(); 

    // ... 

} 

En el desarrollo de GUI Web tiene por ejemplo la sesión y el alcance de solicitud. Creo que el alcance es más difícil en la programación de la GUI de escritorio, así que elegiría DI para servicios únicos y cableado de componentes de GUI estáticos e instanciación manual para todo lo demás.

Y si necesita hacer que los datos de Selección estén disponibles como un Servicio, el fragmento de código podría ser de ayuda.

0

Depende de lo que queremos decir con "GUI".

No utilizaría DI para JSP, pero lo haría en los controladores que interactúan con ellos. Considero que los controladores son parte de la IU. Inyecto los validadores, mapeadores y servicios que necesitan para cumplir con las solicitudes y elaborar respuestas.

Si está de acuerdo, entonces DI es apropiado para la capa de visualización.

1

A composite GUI ciertamente puede hacer uso de DI. Sin embargo, tendrá que ser dogmático para mantener una orientación compuesta. Cualquier acoplamiento directo entre los elementos de la interfaz creará muchos dolores de cabeza.

1

El problema es que guice no puede saber lo que Producto he seleccionado en la tabla , por lo que no se puede saber qué se inyectan en el EditProductDialog.

Use la inyección de dependencia para las dependencias que se pueden resolver por Guice (cuando se inicia la aplicación). Utilice argumentos de método para establecer cualquier estado de sus servicios que esté determinado por la lógica de la aplicación y, por lo tanto, solo se conozca más adelante, en tiempo de ejecución.

En este caso específico, el código que decide qué producto mostrar (presumiblemente el ProductFrame que conoce la selección en la tabla) invocaría un método SetProduct en el cuadro de diálogo antes de mostrarlo.

Cuestiones relacionadas