2011-06-01 8 views
11

He escuchado afirmaciones de que "@ImplementedBy es malo", debido a que rompe los conceptos de DI y hace que la interfaz conozca a sus implementadores.¿El @ImplementedBy de Guice es malo? ¿Es apropiado en algunos casos?

Esto podría ser cierto en algunos casos, pero a menudo descubrí que solo conduce a un código más limpio (no hay módulos largos que mantener), mientras que realmente no hace daño a nada en el proceso.

Como pragmáticos, no puristas, ¿cuándo crees que vale la pena usar @ImplementedBy?

+11

Eso sería incompatible con el lema "no hagas mal" de Google, ¿no? – skaffman

Respuesta

8

Tuve la misma sensación ugh, ick, yuck de @ImplementedBy PERO, al mismo tiempo, es muy útil. Spring tiene que analizar todas las clases en la lista de paquetes que le proporcione. En Guice no tiene que configurar esa lista de paquetes para escanear y @ImplementedBy es la clave para eso (si no usa el Binder para enlazar eso). A medida que baja la jerarquía de objetos en el primer Injector.getInstance, y acierta una interfaz, luego usa @ImplementedBy para encontrar la implementación predeterminada (siempre que no haya nada en el Binder anulando ese valor predeterminado).

Usamos @ImplementedBy también. Nos parece extremadamente agradable de usar, es un poco ugh, pero simplemente funciona y funciona muy bien y, dado que es DI, en realidad no depende de la implementación, ya que puedes anular las vinculaciones con las nuevas de todos modos.

Al mismo tiempo, las interfaces generalmente se utilizan cada vez menos con marcos DI. Todas las interfaces DAO se fueron en nuestro proyecto Y todavía podemos intercambiar objetos simulados para el DAO. Las clases de Java son interfaces implícitas para empezar que se pueden burlar sin necesidad de la interfaz. Ahora reservamos el uso de la interfaz para apis principales para que sea muy claro y no se complique con el código de implementación. Para DAO ya no necesitamos esto.

5

En general, debe preferir enlaces explícitos a través de enlaces just-in-time (JIT). Los enlaces explícitos permiten que el inyector rastree el gráfico de dependencia en el momento de creación del inyector. Esto le permite a Guice fallar rápidamente si una dependencia falta o no es válida. Con enlaces just-in-time como @ImplementedBy, Guice no puede informar el problema hasta que se ejerza el enlace.

Las uniones JIT también interactúan mal con PrivateModules/child injector. Aunque la mayoría de las aplicaciones no deberían necesitar estas funciones, cuando lo hace, es menos doloroso si cada enlace pertenece a un módulo específico.

2

Puedo ver por qué Google hizo lo que hicieron, pero tener una implementación preferida de algo no es necesariamente malo. Tenga en cuenta que la documentación dice que es para la implementación predeterminada, no el único uno.

Btw, encontré esta pregunta porque estaba buscando en Internet las implementaciones existentes del concepto de @ImplementedBy.

Creé una anotación llamada @ImplementedBy para colocar en una de mis interfaces. Cuando se usa la reflexión pura no inyectada, esta es la forma más simple de indicarle a la interfaz qué implementación usar, especialmente cuando se trabaja con API existentes que solo entienden las interfaces. (interfaz, no implementación)

La anotación me permite genérico algunos generadores realmente retorcidos con una línea de anotación y una línea dentro del decorador. No tengo que usar un marco de dependencia para una operación tan simple.

4

Es útil cuando una interfaz no está destinada a tener múltiples implementaciones, pero tiene que ser parte del proceso de inyección de dependencia porque tiene dependencias que tienen que ser inyectadas por el marco.

0

para mí, sí, es malo si lo usas para atar cables y nunca vuelve a usar el encuadernador porque inviertes el sentido de una interfaz. Estoy de acuerdo con @thSoft en que este es un patrón muy común, pero ni siquiera es claro para mí, por qué no tenemos una anotación @Implements. También podría ser irritante que la implementación predeterminada dada no sea la que se usa en tiempo de ejecución.

Para que quede claro lo que google sayed to that

Annotate types tell the injector what their default implementation type is. … 

!! También descarta interfaces genéricas como

@ImplementedBy(MyImpl.class) 
public interface MyInterface<SIn,SOut> {} 

public class MyImpl implements MyInterface<String, Integer> {} 

que normalmente no se implementan solo una vez. ver Inject Generic Implementation using Guice para más detalles.

+0

La razón por la que no hay '@ Implements' es que no tiene sentido: 1. Puede haber varias clases anotadas con' @Implements (MyInterface.class) 'y luego estás perdido. 2. Lo que es peor, para encontrar la implementación, primero debes cargar todas las clases. +++ En cuanto a los genéricos, supongo que '@ ImplementedBy' es solo un atajo para un uso simple, por lo que es lo suficientemente bueno. AFAIK, no hay forma de usar un 'TypeToken' como argumento de anotación. – maaartinus

Cuestiones relacionadas