Estoy refactorizando una aplicación PHP , y estoy tratando de hacer que la inyección de dependencia (DI) sea lo más posible.
Siento que tengo una buena comprensión de cómo funciona, y ciertamente puedo ver que mis clases se vuelven mucho más delgadas y robustas.
Estoy refactorizando para poder inyectar una dependencia en lugar de crear un nuevo objeto dentro de la clase, pero en algún momento tendré que crear algunos objetos, es decir, usar la new
palabra clave temida .
El problema con el que me he encontrado ahora es ¿en qué punto puedo realmente crear nuevos objetos? Parece que terminaré en una clase de nivel superior, creando montones de objetos nuevos ya que no hay otro lugar a donde ir. Esto se siente mal.
He leído algunos blogs que usan clases de fábrica para crear todos los objetos, y luego se inyecta la fábrica en otras clases. Luego puede llamar a los métodos de fábrica, y la fábrica crea el nuevo objeto para usted.
¡Mi preocupación por hacer esto es que ahora mis clases de fábrica serán new
gratuitas! Supongo que esto puede estar bien, ya que son clases de fábrica, pero ¿hay algunas reglas a seguir cuando se usa un patrón de fábrica y DI, o estoy yendo muy lejos de aquí?
fuente
new
. Por supuesto, hay algunos puntos de entrada donde debe llamar al contenedor de IoC, pero no debería haber muchos. Por lo general, configura el IoC una vez y luego solicita que se resuelva una clase por solicitud. En el caso de MVC, ese es típicamente el controlador.Respuestas:
Después de buscar un poco en Google para esto, parece que (como se mencionó en un comentario anterior) la clase de nivel superior de la que hablaba se llama la raíz de composición .
De hecho, parece ser la solución aceptada para agregar la creación de todos los objetos dentro de esta raíz de composición (o haciendo referencia a un contenedor de IoC desde aquí).
Mi preocupación original con esto era que esta clase de nivel superior terminaría siendo un poco desordenada. Esto es cierto hasta cierto punto, pero las ventajas sopesan las desventajas. Por ejemplo, puedo ver que la legibilidad, la capacidad de prueba y el mantenimiento de todas mis otras clases ha mejorado.
La clase de nivel superior puede ser un poco desordenada, llena de
new
y,set_property()
pero tengo que decir que en realidad prefiero tener todo este código en un lugar, en lugar de estar disperso por todas las otras clasesOtra página útil que trata los éxitos de rendimiento de este método aquí
fuente
Una clase de Fábrica se habrá
new
esparcido por todas partes. Estaría creando cualquier objeto que esté solicitando y probablemente las dependencias de ese objeto. Dado que el trabajo de las fábricas es crear una instancia del objeto correcto para ustednew
en esta clase, no es algo malo.DI es para que tenga un diseño suelto. Puede realizar cambios en su aplicación cambiando la dependencia que se proporciona a cada objeto. Hacer su aplicación flexible, extensible y fácil de probar.
En el nivel superior, tendrá un código que instanciará un par de fábricas, configurará conexiones a los servicios y enviará una respuesta. Tendrá una buena cantidad de
new
llamadas estáticas para crear instancias de objetos necesarios para su aplicación. Eso sería donde pertenece.fuente
Mis dos centavos aquí:
No indica si está utilizando un marco de inyección de dependencia. Creo que definitivamente deberías. Use algo que le brinde las funciones que necesita: /programming/9348376/guice-like-dependency-injection-frameworks-in-php .
Normalmente utiliza la configuración o un punto central para la creación de instancias de los objetos iniciales que componen su aplicación. El contenedor creará los objetos por ti.
Luego accede a objetos (servicios, proveedores, controladores ...) a través del contenedor IoC. Si es necesario, creará un objeto transparente para usted o le dará una referencia a la instancia existente adecuada.
Por supuesto, dentro de su implementación particular de objetos, puede crear instancias de otros objetos en los que no necesita DI (estructuras de datos, tipos personalizados, etc.), pero esa es la programación normal.
Normalmente, utiliza una Fábrica si desea que el marco IoC cree instancias de algunos objetos IoC a través de sus fábricas (esto es necesario cuando la creación de instancias de un objeto en particular requiere un trabajo adicional). Si simplemente puede crear sus objetos con "new Object ()" y establecer algunas propiedades, no necesariamente quiere usar un patrón Factory.
En otras palabras, diría que el uso de un patrón Factory para una clase o grupo de clases depende de cómo desee modelar esas clases, no de si usa DI (a menos que su implementación DI explícitamente requiera fábricas, lo cual es inusual).
También configura su marco IoC para usar una Fábrica cuando está utilizando una biblioteca de terceros que ya requiere el uso de una Fábrica. En este caso no tiene control sobre esto y necesita decirle a su contenedor de IoC: "oye, cuando solicito una de estas interfaces, debe usar esta fábrica para proporcionarme una instancia apropiada".
En este caso, parece que no necesita usar patrones de Fábrica para estos objetos / servicios / controladores / lo que sea, y simplemente puede configurar su IoC para instanciar con "nueva" la clase apropiada e inyectar todo lo demás.
Espero que ayude.
fuente
doing DI manually beats the whole purpose of using an Inversion of Control container
- Si con eso te refieres a "... que es centralizar tus dependencias en un archivo de configuración" , tienes razón, porque eso es todo lo que realmente hace un contenedor de IoC. El objetivo real de DI es el desacoplamiento, y puede hacerlo proporcionando sus dependencias en un método constructor. No necesita un marco DI para hacer eso.