2009-11-19 14 views
7

Estoy tratando de decidir si tiene sentido realizar el esfuerzo adicional para encapsular mi contenedor IoC. La experiencia me dice que debo poner una capa de encapsulación entre mis aplicaciones y cualquier componente de terceros. Simplemente no sé si esto está bordeando excesivamente.¿Debo encapsular mi contenedor IoC?

Puedo pensar en situaciones en las que podría querer cambiar contenedores. Por ejemplo, mi contenedor actual deja de mantenerse, o se comprueba que un contenedor diferente es más liviano/funcional y se adapta mejor a mis necesidades. Si esto sucede, entonces posiblemente tendré que volver a cablear mucho para hacerlo.

Para ser claros, estoy considerando encapsular el registro y resolución de tipos. Creo que es una obviedad encapsular la resolución. Espero que sea una práctica común tener una clase auxiliar/utilitaria delegando en el contenedor.

EDIT:

La suposición es que prefiero alambre de seguridad de mis tipos de programación para el tipo-seguridad, en tiempo de compilación de cheques y refactorability. Es este código y su dependencia del contenedor del que estoy tratando de protegerme.

También he estado usando un contenedor IoC para varios otros proyectos que comparten muchas de las mismas relaciones, pero el contenedor es un dolor para trabajar, así que quiero un cambio. Pero, un cambio significa que pierdo la reutilización del código de registro. Por lo tanto, ¿por qué estoy contemplando la encapsulación? No es una carga enorme, pero a la que me gustaría mitigar.

Busco a:

  • minimizar el impacto del cambio en contenedores/recipientes versiones de
  • proporcionar un cierto nivel de consistencia de registro de tipo a través de proyectos que pueden utilizar diferentes contenedores
  • proporcionar la interfaz métodos que tienen sentido para mí (RegisterSingleton < T, T > en lugar de RegisterType < T, T > (SomeLifetimeProvider) - usando Unity como ejemplo).
  • Aumente el contenedor a medida que cambien los requisitos de condiciones/escalabilidad, p. agregando mejor almacenamiento en caché, registro, etc. durante la resolución/registro.
  • Proporcionar mi propio modelo para registrar las asignaciones de tipos.
    • Digamos que quiero crear una gran cantidad de objetos RegistrationHandler en un ensamblado/paquete y así puedo separar fácilmente las responsabilidades de registro en múltiples clases y retirar estos manejadores automáticamente sin cambiar el código en ningún otro lado.

Soy consciente de que es un poco subjetivo, por lo ventajas/desventajas podrían ser útiles

Gracias!

+1

Se ha realizado. (Para .NET, al menos.) [Biblioteca de Local Service Service] (http://www.codeplex.com/CommonServiceLocator) En cualquier caso, estoy de acuerdo con el Sr. Knesek. Por lo general, solo necesita dependencias en su contenedor en su clase de nivel superior. – TrueWill

+0

Eso parece un poco exagerado por lo que estoy tratando de lograr. Solo quiero minimizar el impacto del cambio si elijo cambiar los contenedores (en mi proyecto actual o en proyectos futuros). No quiero presentar otra biblioteca de terceros para lograr esto. –

+0

Directed substaintly uin http://davybrion.com/blog/2009/11/integrating-your-ioc-container-with-agatha/ –

Respuesta

7

Hágalo más tarde, y solo si realmente tiene la necesidad de cambiar los contenedores IOC.

Elija un contenedor IOC que no sea invasivo. Es decir, una donde los objetos que se conectan entre sí no tienen ninguna dependencia en el contenedor IOC. En este caso, no hay nada que encapsular.

Si tiene que elegir un contenedor IOC que requiere que tenga dependencias en el contenedor, elija uno con las API/dependencias más simples que pueda. Si necesita reemplazar este contenedor IOC (y probablemente no lo haga), implemente adaptadores que conecten la nueva API con la anterior.

En otras palabras, que el primer contenedor IOC sea el que define las interfaces para cualquier contenedor futuro para que no tenga que inventar el suyo propio, y puede retrasar cualquiera de este tipo de trabajo hasta que absolutamente lo necesito

EDIT:

no veo una forma de garantizar la seguridad de tipo corto-de cualquiera:

  1. El diseño de una aplicación relativamente complejo del Builder junto con las implementaciones de los visitantes que escribir la configuración del COI archivos, o algo equivalente.
  2. Implementación de una configuración de IOC de tipo seguro DSL. (Mi elección si tenía varias aplicaciones que requerían contenedores IOC intercambiables).
+0

La resolución de tipo no suele ser invasiva, por naturaleza; es el registro que generalmente requiere una gran cantidad de código específico del contenedor. Es este código (suponiendo que prefiero la seguridad de tipo sobre la configuración XML) que estoy tratando de protegerme a mí mismo (y a mi (s) aplicación (s)) Estoy de acuerdo en que el alejarse del mapeo de tipo declarativo es peligroso (como a través de anotaciones o atributos). –

+0

Además, no estoy totalmente satisfecho con ninguna de las interfaces de los contenedores IoC actuales, por lo que no sé si deseo el que elija dictar. –

+1

@Ryan: aunque estoy de acuerdo con la seguridad de tipo sobre XML, creo que encontrará que tiene una clase (posiblemente incluso un método) que realiza todo el registro para un proyecto determinado. Dependiendo de la cantidad de proyectos que tenga, el registro de resúmenes puede proporcionar pocos beneficios. – TrueWill

1

Sí, hazlo. No es mucho esfuerzo adicional y, como dices, te ofrece un mejor aislamiento de los componentes de terceros.

También significa que puede cambiar fácilmente el contenedor IoC si encuentra algo que es mejor. Hace poco hice esto cambiando el contenedor de Spring.net IoC por structuremap.

El proyecto ASP.NET MVC Contrib en codeplex es un muy buen lugar para comenzar. Esto es de lo que basé mi implementación.

1

Lo mejor es hacer algo solo si hay una necesidad real y nunca codificar algo que suponga que se requerirá a veces en el futuro (ese es el llamado YAGNI -principio). Si su arquitectura está bien, puede cambiar fácilmente el contenedor, si realmente fuera necesario ...

Si cree que necesita este tipo de flexibilidad, puede consultar Common Service Locator project en CodePlex. Hace exactamente lo que busca: proporcionar una fachada común para varios contenedores de IoC.

HTH!

+0

En ocasiones, necesita hacer una estimación educada sobre las necesidades de mantenimiento de su aplicación en el futuro. Prefiero tener algún nivel de prueba de futuro, aunque estoy guiado de todo corazón por el principio de YAGNI. Una sola biblioteca de encapsulación reutilizable (y las pruebas asociadas) requieren un esfuerzo mínimo que vale la pena considerar ahora. –

+1

Estoy con Thomas (y Doug) - solo * parece * como un esfuerzo mínimo ahora. Agregaría más código para probar, más código que se puede romper y más código para mantener. ¿Y para qué? Para ahorrar un poco de tiempo en algo que nunca podría suceder. Incluso diría que * probablemente * nunca sucederá, porque el tipo de cosas para las que cambiarías los contenedores (por ejemplo, pasar de la inyección controlada por atributos a las asignaciones declarativas) son el tipo de cosas que no serían cubierto por una interfaz de encapsulado. –

+1

Solo por curiosidad: ¿Qué tipo de aplicación tendría que "cambiar la implementación del contenedor IoC" como una necesidad de mantenimiento? Y, por cierto: si se requiere "un esfuerzo mínimo" para encapsular el contenedor ahora, requerirá un esfuerzo aún menor para cambiarlo en el futuro, si esta necesidad realmente surgiera ... –

1

En lugar de encapsular el contenedor de IOC, prefiero aislar el lugar de interacción con el contenedor de IOC. Por ejemplo, en ASP.Net MVC, generalmente limito la exposición al contenedor a la fábrica del controlador y al archivo global.aspx.cs, donde generalmente está configurado.

En mi opinión, tener un montón de código que sabe sobre el contenedor de IOC es un antipatrón que aumenta la complejidad. He visto una gran cantidad de código en el que los objetos pueden solicitar al contenedor del COI sus dependencias, y básicamente han reducido el contenedor del COI a un localizador de servicios de alto mantenimiento.

Dado que los contenedores IOC pueden resolver dependencias hasta un grado arbitrario de profundidad, es bastante fácil hacer que el controlador sea el componente responsable de la inversión de los contenedores de control. El constructor de cada controlador especifica esencialmente los servicios/repositorios/puertas de enlace que necesita.

Para cualquiera de mis aplicaciones, intercambiar el contenedor IOC sería esencialmente una cuestión de reescribir el código que configura el contenedor (especifica los enlaces, etc.) y conecta la fábrica del controlador.Para las aplicaciones expuestas como servicios, la misma idea básica debe ser razonablemente manejable, aunque, dependiendo de las limitaciones de su tiempo de ejecución, es posible que tenga que usar la inyección de setter en lugar de la inyección del constructor.

Cuestiones relacionadas