Inyección de dependencia: ¿debo usar un marco?


24

Recientemente trabajé en un proyecto de Python donde realizamos una gran inyección de dependencias (porque debemos hacerlo para que la aplicación sea comprobable), pero no utilizamos ningún marco. A veces era un poco tedioso conectar todas las dependencias manualmente, pero en general funcionó muy bien.

Cuando un objeto tenía que ser creado en múltiples lugares, simplemente teníamos una función (a veces un método de clase de ese objeto) para crear una instancia de producción. Esta función se llamaba cuando necesitábamos ese objeto.

En las pruebas, hicimos lo mismo: si varias veces necesitábamos crear una 'versión de prueba' de un objeto (es decir, una instancia real respaldada por objetos simulados), teníamos una función para crear esta 'versión de prueba' de una clase, para ser utilizado en pruebas.

Como dije, generalmente esto funcionó bien.

Ahora estoy ingresando a un nuevo proyecto Java, y estamos decidiendo si usar un marco DI o hacer DI manualmente (como en el proyecto anterior).

Por favor explique cómo será diferente trabajar con un marco DI y de qué manera es mejor o peor que la inyección manual de dependencia 'vainilla'.

Editar: También me gustaría agregar a la pregunta: ¿ha sido testigo de algún proyecto de 'nivel profesional' que realiza DI manualmente, sin un marco?


Al lado de mi respuesta. Ambas formas son compatibles. Puede dejar la inyección de dependencia flexible en el marco y conservar sus fábricas para componentes críticos. Componentes relacionados con el modelo o negocio.
Laiv

44
Supongo que ya lo revisó, solo en caso de que no lo haga ¿Por qué necesitamos marcos para DI?
Laiv

Respuestas:


19

La clave de los contenedores DI es la abstracción . Los contenedores DI resumen esta preocupación de diseño por usted. Como puede suponer, tiene un impacto notable en el código, a menudo traducido en un menor número de constructores, instaladores, fábricas y constructores. En consecuencia, hacen que su código esté más débilmente acoplado (debido a la IoC subyacente ), más limpio y simple. Aunque no sin un costo.

Antecedentes

Hace años, tal abstracción requería que escribiéramos varios archivos de configuración ( programación declarativa ). Fue fantástico ver que el número de LOC disminuía sustancialmente, pero aunque los LOCS disminuyeron, el número de archivos de configuración aumentó ligeramente. Para proyectos medianos o pequeños no fue un problema en absoluto, pero para proyectos más grandes, tener el "ensamblaje del código" disperso al 50% entre el código y los descriptores XML se convirtió en una molestia en ... Sin embargo, el problema principal fue paradigma en sí mismo. Era bastante inflexible porque los descriptores dejaban poco espacio para las personalizaciones.

El paradigma cambió progresivamente hacia la convención sobre la configuración , que intercambia archivos de configuración por anotaciones o atributos. Mantiene nuestro código más limpio y simple a la vez que nos proporciona la flexibilidad que XML no podría.

Probablemente, esta es la diferencia más significativa con respecto a cómo trabajaba hasta ahora. Menos código y más magia.

A la baja...

La convención sobre la configuración hace que la abstracción sea tan pesada que apenas se sabe cómo funciona. A veces parece mágico y aquí viene un inconveniente más. Una vez que funciona, a muchos desarrolladores no les importa cómo funciona.

Esta es una desventaja para aquellos que aprendieron DI con contenedores DI. No entienden completamente la relevancia de los patrones de diseño, las buenas prácticas y los principios abstraídos por el contenedor. Le pregunté a los desarrolladores si estaban familiarizados con DI y sus ventajas y respondieron: Sí, he usado Spring IoC . (¿¡¿Que demonios significa?!?)

Uno puede estar de acuerdo o no con cada uno de estos "inconvenientes". En mi humilde opinión, es imprescindible saber qué está pasando en su proyecto. De lo contrario, no tenemos una comprensión completa de ello. También es saber para qué sirve la DI y tener una idea de cómo implementarla es una ventaja a tener en cuenta.

En el lado positivo...

Una palabra de productividad . Los marcos nos permiten centrarnos en lo que realmente importa. El negocio de la aplicación.

A pesar de las deficiencias comentadas, para muchos de nosotros (qué trabajo está condicionado por plazos y costos), estas herramientas son un recurso invaluable. En mi opinión, este debería ser nuestro argumento principal a favor de implementar un contenedor DI. Productividad .

Pruebas

Ya sea que implementemos DI o contenedores puros, las pruebas no serán un problema. Todo lo contrario. Los mismos contenedores a menudo nos proporcionan los simulacros para las pruebas unitarias fuera de la caja. A lo largo de los años he usado mis pruebas como termómetros. Me dicen si he dependido mucho de las instalaciones de contenedores. Digo esto porque estos contenedores pueden inicializar atributos privados sin establecedores o constructores. ¡Pueden inyectar componentes casi en cualquier lugar!

Suena tentador ¿verdad? ¡Ten cuidado! ¡No caigas en la trampa!

Sugerencias

Si decide implementar contenedores, le sugiero que siga las buenas prácticas. Siga implementando constructores, setters e interfaces. Aplicar el marco / contenedor para usarlos . Facilitará las migraciones posibles a otro marco o eliminará el actual. Puede reducir significativamente la dependencia del contenedor.

Con respecto a estas prácticas:

Cuándo usar contenedores DI

Mi respuesta estará sesgada por mi propia experiencia, que está principalmente a favor de los contenedores DI (como comenté, estoy muy centrado en la productividad, por lo que nunca he tenido la necesidad de una DI pura. Todo lo contrario).

Creo que encontrará interesante el artículo de Mark Seeman sobre este tema, que también responde a la pregunta sobre cómo implementar la DI pura .

Finalmente, si estuviéramos hablando de Java, consideraría primero echar un vistazo al JSR330 - Inyección de dependencia .

Resumiendo

Beneficios :

  • Reducción de costos y ahorro de tiempo. Productividad.
  • Un menor número de componentes.
  • El código se vuelve más simple y más limpio.

Inconvenientes :

  • DI se delega a librerías de terceros. Debemos ser conscientes de sus compensaciones, fortalezas y debilidades.
  • Curva de aprendizaje.
  • Rápidamente te hacen olvidar algunos buenos hábitos.
  • Aumento de las dependencias del proyecto (más libs)
  • Los contenedores basados ​​en la reflexión requieren más recursos (memoria). Esto es importante si estamos limitados por los recursos.

Diferencias con DI pura :

  • Menos código y más archivos de configuración o anotaciones.

1
"Estos marcos no son privados para hacer pruebas unitarias o pruebas de integridad, así que no te preocupes por las pruebas". ¿Qué significa esto exactamente? La redacción me hace pensar que es un error tipográfico, pero tengo problemas para decodificarlo.
candied_orange

Significa que la depuración difícil o el uso de los marcos para la prueba no son suficientes inconvenientes para descartar el uso de estos marcos. Porque incluso si no te gustan, todavía tienen beneficios que realmente vale la pena probar. Los grandes inconvenientes no son marcos por sí mismos. Así es como los usas. Todavía se requieren algunas buenas prácticas como interfaces y configuradores, incluso si su marco no lo hace. Finalmente, hay buenas bibliotecas para pruebas que se integran fácilmente con este tipo de Frameworks (DI)
Laiv

Si eso es lo que quiere decir, considere: "Estos marcos no le impiden realizar pruebas unitarias o pruebas de integridad, así que no se preocupe por cómo impactan las pruebas"
candied_orange

Srry. Trato de decir que podrá probar su código incluso con estos marcos. A pesar de la abstracción, las pruebas aún son factibles. Siéntase libre de editar mi respuesta. Como ves, mi inglés aún está lejos de ser decente :-)
Laiv

1
Tenga en cuenta que Dagger2 hace DI ligeramente diferente. El código de pegamento se genera en tiempo de compilación como fuentes Java normales y legibles, por lo que es mucho más sencillo seguir cómo se unen las cosas en lugar de tener que lidiar con la magia de tiempo de ejecución.
Thorbjørn Ravn Andersen

10

En mi experiencia, un marco de inyección de dependencia conduce a una serie de problemas. Algunos de los problemas dependerán del marco y las herramientas. Puede haber prácticas que mitiguen los problemas. Pero estos son los problemas que he encontrado.

Objetos no globales

En algunos casos, desea inyectar un objeto global: un objeto que tendrá solo una instancia en su aplicación en ejecución. Esta podría ser una MarkdownToHtmlRendererer, una DatabaseConnectionPool, la dirección de su servidor api, etc. Para estos casos, los marcos de inyección de dependencias funcionan de manera muy simple, simplemente agrega la dependencia necesaria a su constructor y lo tiene.

¿Pero qué pasa con los objetos que no son globales? ¿Qué sucede si necesita al usuario para la solicitud actual? ¿Qué sucede si necesita la transacción de base de datos actualmente activa? ¿Qué sucede si necesita el elemento HTML correspondiente al div que contiene un formulario en el que hay un cuadro de texto que acaba de disparar un evento?

La solución que he visto empleada por los marcos DI son los inyectores jerárquicos. Pero esto hace que el modelo de inyección sea más complicado. Se hace más difícil determinar qué se inyectará desde qué capa de la jerarquía. Se hace difícil saber si un objeto dado existirá por aplicación, por usuario, por solicitud, etc. Ya no puede simplemente agregar sus dependencias y hacer que funcione.

Bibliotecas

A menudo querrás tener una biblioteca de código reutilizable. Esto también incluirá las instrucciones sobre cómo construir objetos a partir de ese código. Si usa un marco de inyección de dependencia, esto generalmente incluirá reglas vinculantes. Si desea utilizar la biblioteca, agregue sus reglas vinculantes a las suyas.

Sin embargo, pueden surgir varios problemas. Puede terminar con la misma clase vinculada a diferentes implementaciones. La biblioteca puede esperar que existan ciertos enlaces. La biblioteca puede anular algunos enlaces predeterminados haciendo que su código haga cosas extrañas. Su código puede anular algunos enlaces predeterminados haciendo que el código de la biblioteca haga cosas extrañas.

Complejidad oculta

Cuando escribe fábricas manualmente, tiene una idea de cómo encajan las dependencias de la aplicación. Cuando usa un marco de inyección de dependencia, no ve esto. En cambio, los objetos tienden a crecer más y más dependencias hasta que tarde o temprano todo depende de casi todo.

Soporte IDE

Su IDE probablemente no comprenderá el marco de inyección de dependencias. Con las fábricas manuales, puede encontrar todas las personas que llaman de un constructor para descubrir todos los lugares donde el objeto podría construirse. Pero no encontrará las llamadas generadas por el marco DI.

Conclusión

¿Qué obtenemos de un marco de inyección de dependencia? Podemos evitar algunas repeticiones simples necesarias para crear instancias de objetos. Estoy a favor de eliminar repeticiones simples. Sin embargo, mantener una placa repetitiva simple es fácil. Si vamos a reemplazar esa placa repetitiva, debemos insistir en reemplazarla con algo más fácil. Debido a los diversos problemas que he discutido anteriormente, no creo que los marcos (al menos tal como están) se ajusten a la ley.


Esta es una muy buena respuesta, pero no puedo imaginar usar un contenedor de IoC para una biblioteca de clases. Eso se siente como un mal diseño para mí. Esperaría que una biblioteca me diera explícitamente cualquier dependencia que requiera.
RubberDuck

@RubberDuck, en mi caso, trabajé para una gran empresa con una gran cantidad de proyectos de Java, todos estandarizados en el mismo marco de inyección de dependencias. En ese momento, resulta tentador para algunos equipos exportar una biblioteca que espera ser creada por el marco DI, en lugar de proporcionar una interfaz externa sensible.
Winston Ewert

Eso es lamentable @ WinstonEwert. Gracias por completar el contexto para mí.
RubberDuck

Sería genial para IDE parte, con el marco de unión de tiempo de ejecución de inyecciones en lugar de la unión de tipo de tiempo de diseño de inyecciones manuales. El compilador evita las inyecciones olvidadas cuando son manuales.
Basilevs

IntelliJ entiende CDI (DI estándar Java EE)
Thorbjørn Ravn Andersen

3

¿Se requiere Java + dependency injection = framework?

No.

¿Qué me compra un marco DI?

Construcción de objetos que ocurre en un lenguaje que no es Java.


Si los métodos de fábrica son lo suficientemente buenos para sus necesidades, puede hacer DI en java completamente sin marco en pojo java 100% auténtico. Si sus necesidades van más allá, tiene otras opciones.

Los patrones de diseño de Gang of Four logran muchas cosas grandiosas, pero siempre han tenido debilidades cuando se trata de los patrones de creación. Java en sí tiene algunas debilidades aquí. Los marcos DI realmente ayudan con esta debilidad creacional más de lo que lo hacen con las inyecciones reales. Ya sabes cómo hacerlo sin ellos. Cuánto bien le harán dependerá de cuánta ayuda necesite con la construcción de objetos.

Hay muchos patrones de creación que surgieron después de la Banda de los Cuatro. El constructor Josh Bloch es un truco maravilloso en torno a la falta de parámetros con nombre de Java. Más allá de eso están los creadores de iDSL que ofrecen mucha flexibilidad. Pero cada uno de estos representa un trabajo significativo y repetitivo.

Los marcos pueden salvarte de algo de este tedio. No están exentos de inconvenientes. Si no tiene cuidado, puede depender del marco. Intente cambiar marcos después de usar uno y compruébelo usted mismo. Incluso si de alguna manera mantiene el xml o las anotaciones genéricas, puede terminar admitiendo lo que son esencialmente dos lenguajes que debe mencionar uno al lado del otro cuando anuncia trabajos de programación.

Antes de enamorarse demasiado del poder de los marcos de DI, tómese un tiempo e investigue otros marcos que le brinden capacidades para las que de otro modo podría pensar que necesita un marco de DI. Muchos se han ramificado más allá de la simple DI . Considere: Lombok , AspectJ y slf4J . Cada uno se superpone con algunos marcos DI pero cada uno funciona bien por sí solo.

Si la prueba es realmente la fuerza impulsora detrás de esto, investigue: jUnit (cualquier xUnit realmente) y Mockito (cualquier simulación realmente) antes de comenzar a pensar que un marco DI debería tomar el control de su vida.

Puedes hacer lo que quieras, pero para un trabajo serio prefiero una caja de herramientas bien poblada a una navaja suiza. Desearía que fuera más fácil dibujar estas líneas, pero algunos han trabajado duro para desenfocarlas. No tiene nada de malo, pero puede hacer que estas elecciones sean un desafío.


PowerMock ha resuelto algunos de estos casos. Al menos te permite
simular

Meh Si está haciendo DI correctamente, debería ser relativamente simple cambiar un marco de Contenedor de IoC por otro. Mantenga esas anotaciones fuera de su código y estará bien. Básicamente, use el contenedor IoC para hacer DI en lugar de usar el contenedor como un localizador de servicios.
RubberDuck

@RubberDuck correcto. A falta de probar y mantener su base de código constantemente bajo múltiples marcos DI, ¿conoce una manera simple y confiable de verificar que "está haciendo DI correctamente"? Incluso si uso nada más que pojo's en java, si se ha hecho un esfuerzo significativo para hacer el XML, todavía no es un simple intercambio cuando el XML depende del contenedor de IoC.
candied_orange

@CandiedOrange Estoy usando "simple" como un término relativo. En el gran esquema de las cosas, reemplazar una raíz de composición por otra no es una tarea demasiado difícil. Unos días de trabajo como máximo. En cuanto a asegurarse de que está haciendo DI correctamente, para eso están las revisiones de código.
RubberDuck

2
@RubberDuck La mayoría de las "raíces de composición" que he visto son aproximadamente 5 líneas de código en main. Entonces no. No es una tarea demasiado difícil. Es el material patentado que escapa a esas líneas contra las que advierto. Lo llamas "hacer DI correctamente". Le pregunto si usaría para probar un problema en una revisión de código. ¿O simplemente dirías "Meh"?
candied_orange

2

Crear clases y asignarles dependencias es parte del proceso de modelado, las partes divertidas. Es la razón por la cual la mayoría de los programadores disfrutan de la programación.

Decidir qué implementación se usará y cómo se construirán las clases es algo que tendrá que implementarse de alguna manera y es parte de la configuración de la aplicación.

Escribir fábricas manualmente es un trabajo tedioso. Los marcos DI lo hacen más fácil al resolver automáticamente las dependencias que pueden resolverse y requieren configuración para aquellas que no.

El uso de IDEs modernos le permite navegar a través de métodos y sus usos. Tener fábricas escritas manualmente es bastante bueno, porque simplemente puede resaltar el constructor de una clase, mostrar sus usos y le mostrará todos los lugares donde y cómo se está construyendo la clase específica.

Pero incluso con el marco DI, puede tener un lugar central, como la configuración de construcción de gráfico de objetos (OGCC de ahora en adelante), y si una clase depende de dependencias ambiguas, simplemente puede mirar en OGCC y ver cómo se está construyendo una clase específica justo ahí.

Podrías objetar, que personalmente crees que poder ver los usos de un constructor específico es una gran ventaja. Diría que lo que te resulta mejor no solo es subjetivo, sino que proviene principalmente de la experiencia personal.

Si siempre hubiera trabajado en proyectos que se basaran en marcos DI, solo lo sabría y cuando quisiera ver la configuración de una clase, siempre miraría en OGCC y ni siquiera trataría de ver cómo se usan los constructores , porque sabría que todas las dependencias están conectadas automáticamente de todos modos.

Naturalmente, los marcos DI no se pueden usar para todo y de vez en cuando tendrá que escribir uno o dos métodos de fábrica. Un caso muy común es construir una dependencia durante la iteración sobre una colección, donde cada iteración proporciona un indicador diferente que debería producir una implementación diferente de una interfaz común.

Al final, lo más probable es que todo se reduzca a cuáles son sus preferencias y a lo que está dispuesto a sacrificar (ya sea tiempo escribiendo fábricas o transparencia).


Experiencia personal (advertencia: subjetiva)

Hablando como desarrollador de PHP, aunque me gusta la idea detrás de los marcos DI, solo los he usado una vez. Fue entonces cuando se suponía que un equipo con el que estaba trabajando desplegaría una aplicación muy rápidamente y no podríamos perder el tiempo escribiendo fábricas. Así que simplemente recogimos un marco DI, lo configuramos y funcionó, de alguna manera .

Para la mayoría de los proyectos, me gusta que las fábricas se escriban manualmente porque no me gusta la magia negra que ocurre dentro de los marcos DI. Yo fui el responsable de modelar una clase y sus dependencias. Yo decidí por qué el diseño se ve como se ve. Así que seré yo quien construya correctamente la clase (incluso si la clase toma dependencias difíciles, como clases concretas en lugar de interfaces).


2

Personalmente no uso contenedores DI y no me gustan. Tengo un par de razones más para eso.

Por lo general, es una dependencia estática. Por lo tanto, es solo un localizador de servicios con todos sus inconvenientes. Luego, debido a la naturaleza de las dependencias estáticas, se ocultan. No necesita tratar con ellos, de alguna manera ya están allí, y es peligroso, porque deja de controlarlos.

Se rompe los principios de programación orientada a objetos , como la cohesión y David West Lego-ladrillo metáfora 's.

Así que construir el objeto completo lo más cerca posible del punto de entrada del programa es el camino a seguir.


1

Como ya habrás notado: dependiendo del lenguaje que uses, hay diferentes puntos de vista, diferentes enfoques sobre cómo lidiar con problemas similares.

Con respecto a la inyección de dependencia, todo se reduce a esto: la inyección de dependencia es, como dice el término, nada más que poner las dependencias que un objeto necesita en ese objeto , lo que contrasta de otra manera: dejar que el objeto mismo instale instancias de objetos de los que depende. Desacopla la creación de objetos y el consumo de objetos para ganar más flexibilidad.

Si su diseño está bien diseñado, generalmente tiene pocas clases con muchas dependencias, por lo tanto, el cableado de las dependencias, ya sea a mano o mediante un marco, debería ser relativamente fácil y la cantidad de repeticiones para escribir las pruebas debería ser fácil de manejar.

Dicho esto, no hay necesidad de un marco DI.

Pero, ¿por qué quieres usar un marco de todos modos?

I) Evite el código repetitivo

Si su proyecto obtiene un tamaño, donde siente el dolor de escribir fábricas (e instancias) una y otra vez, debe usar un marco DI

II) Enfoque declarativo de la programación

Cuando Java una vez estaba programando con XML , ahora es: rociando polvo de feria con anotaciones y sucede la magia .

Pero en serio: veo una clara ventaja de esto. Comunicas claramente la intención al decir lo que se necesita en lugar de dónde encontrarlo y cómo construirlo.


tl; dr

Los marcos DI no hacen que su base de código sea mágicamente mejor, pero ayuda a que el código de buena apariencia se vea realmente nítido . Úselo cuando sienta que lo necesita. En un momento determinado de su proyecto, le ahorrará tiempo y evitará las náuseas.


1
¡Tienes razón! Tiendo a preocuparme demasiado por cómo funcionan las cosas bajo el capó. He tenido experiencias terribles trabajando con marcos que apenas entendía. No estoy abogando a favor de probar los marcos, solo entiendo lo que hacen y cómo lo hacen (si es posible). Pero depende de tus propios intereses. Creo que al comprender cómo funcionan, usted está en una mejor posición para decidir si son adecuados para usted. Por ejemplo, de la misma manera que compararía diferentes ORM.
Laiv

1
Creo que siempre es correcto saber cómo funcionan las cosas bajo el capó. Pero no debería molestarte sin saberlo. Creo que el punto de venta para Spring, por ejemplo, es que simplemente funciona. Y sí, tiene toda la razón, que para tomar una decisión informada sobre si usar un marco, debe tener algún grado de conocimiento. Pero veo con demasiada frecuencia un patrón de desconfianza hacia las personas que no tienen las mismas cicatrices que uno mismo, aunque no en su caso, donde existe la creencia, solo el que ha experimentado la caza manual puede ir al supermercado.
Thomas Junk

Afortunadamente, en estos días ni siquiera necesitamos marcos Spring o DI para Java. Ya tenemos el JSR330, que lamentablemente se ignora (al menos no vi un proyecto que lo implementara). Entonces, la gente todavía tiene tiempo para ganar sus cicatrices :-)
Laiv

He editado mi respuesta y tomé en consideración sus comentarios. He eliminado los "inconvenientes" relacionados con la depuración. Llegué a la conclusión de que tenías razón en eso. Eche un vistazo y considere actualizar su respuesta también, porque en este momento estaría citando partes que he eliminado de mi respuesta.
Laiv

1
¡La respuesta cambió muy poco! Nada que deba preocuparte :-). El mensaje y los argumentos siguen siendo los mismos. Solo quería que tu respuesta siguiera siendo como es. Supongo que solo te tomó eliminar una de las citas.
Laiv

0

Sí. Probablemente deberías leer el libro de Mark Seemann titulado "Inyección de dependencia". Él describe algunas buenas prácticas. Con base en algo de lo que ha dicho, podría beneficiarse. Debe intentar tener una raíz de composición o una raíz de composición por unidad de trabajo (por ejemplo, solicitud web). Me gusta su forma de pensar que cualquier objeto que cree se considera una dependencia (como cualquier parámetro de un método / constructor), por lo que realmente debe tener cuidado con dónde y cómo crear objetos. Un marco lo ayudará a mantener claros estos conceptos. Si lees el libro de Mark, encontrarás más que solo la respuesta a tu pregunta.


0

Sí, cuando trabaje en Java, recomendaría un marco DI. Hay algunas razones para esto:

  • Java tiene varios paquetes DI extremadamente buenos que ofrecen inyección de dependencia automatizada y, por lo general, vienen con capacidades adicionales que son más difíciles de escribir manualmente que la DI simple (por ejemplo, dependencias con ámbito que permiten la conexión automática entre ámbitos mediante la generación de código para buscar en qué ámbito debería estar) use d para encontrar la versión correcta de la dependencia para ese ámbito, por lo que, por ejemplo, los objetos con ámbito de aplicación pueden referirse a los con ámbito de solicitud).

  • Las anotaciones de Java son extremadamente útiles y proporcionan una excelente manera de configurar dependencias

  • la construcción de objetos java es demasiado detallada en comparación con lo que estás acostumbrado en python; El uso de un marco aquí ahorra más trabajo del que haría en un lenguaje dinámico.

  • Los frameworks java DI pueden hacer cosas útiles como generar automáticamente proxies y decoradores, que son más trabajo en Java que un lenguaje dinámico.


0

Si su proyecto es lo suficientemente pequeño y no tiene mucha experiencia con el DI-Framework, recomendaría no usar el framework y hacerlo manualmente.

Motivo: una vez trabajé en un proyecto que utilizaba dos bibliotecas que tenían dependencias directas a diferentes marcos de trabajo. ambos tenían un código específico de framework como di-give-me-an-instance-of-XYZ. Hasta donde sé, solo puede tener una implementación activa de marco de trabajo a la vez.

Con un código como este puede hacer más daño que beneficio.

Si tiene más experiencia, es probable que abstraiga el marco de trabajo mediante una interfaz (fábrica o localizador de servicios) para que este problema ya no exista y el marco de trabajo beneficiará más ese daño.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.