Pregunta ¿La inyección de dependencia conduce a la proliferación de fábricas?


Siempre me he sentido incómodo al tratar con clases que necesitaban crear instancias de muchos objetos, ya que he estado usando los principios de Dependency Injection.

Por ejemplo, digamos que tengo una clase que se supone que genera muchos tipos de eventos diferentes. Cada evento tiene un tipo diferente, así que lo que haría es tener una fábrica diferente para cada tipo de evento diferente. Si tengo 10 eventos, entonces tendré que tener 10 fábricas. Eso no parece agradable. También podría tener una sola fábrica para todos los diferentes tipos de eventos, pero eso no parece demasiado correcto, también.

(Para el público de C #, no estoy hablando de los eventos de .NET aquí. Esto fue solo un ejemplo para llegar al punto, ¡solo piensen en ellos como clases regulares!)

Esto fue solo un ejemplo. No tengo problemas para tener una fábrica aquí o allá, pero en ciertos tipos de proyectos donde uno tiene que crear muchos objetos en tiempo de ejecución, ¡parece que tengo que hacer una fábrica para casi todas las clases que defino!

¿Cómo manejas esta situación? ¿Me estoy perdiendo de algo?

He visto gente que solo pasa una referencia al Contenedor de IoC que usan, pero eso no me parece bueno. ¡IMO, el modelo de dominio ni siquiera debería saber que se está utilizando un contenedor IoC!

Gracias


7
2018-05-24 11:59


origen


Respuestas:


No hay nada malo con una clase que ejemplifique muchos otros objetos. En cambio, esa clase debe ser tratada como una raíz agregada entidad de dominio. En cuanto a los diferentes "tipos" de entidad, si supone que implementan la misma interfaz o heredan de la misma clase base, pasan una type argumento para Factory.create(type) es la forma en que suelo enfocarme en este tema. El interior de create() puede delegar en otras clases al estilo de la Estrategia, pero la API del cliente es sencilla.

Ahora, si estás creando una fábrica para cada clase con la que estás lidiando, eso suena como algo anti-patrón. Estudie el patrón de raíz agregado mencionado anteriormente y vea si puede organizar sus entidades en gráficos, debería poder hacerlo, de modo que una fábrica sea suficiente para generar el gráfico completo.

En cuanto a IoC, el modelo de dominio no debería saber sobre el contenedor. Cuando tengo entidades que necesitan referencias a singletons (generalmente fábricas) en el contenedor, generalmente inyecté una fábrica a otra como tal:

class FactoryA {
    void setFactoryB(FactoryB factoryB) { /* sets into state */ }
    EntityA create(Enum type) {
        EntityA entityA = new EntityA();
        /* DI FactoryB - this method is probably default access */
        entityA.setFactoryB(getFactoryB());
    }
}

class FactoryB {}

Entonces, en el ejemplo anterior ambos FactoryA y FactoryB son singletons administrados por el contenedor IoC. EntityA necesita una referencia a FactoryB, asi que FactoryA se inyecta con una referencia a FactoryB eso se transmite dentro de la create() método.


2
2018-05-24 12:36



He sido un fanático de la inyección de constructores durante todo el tiempo que he sabido sobre DI, porque en mi opinión eso es lo que hace un constructor para. Indica "Necesito instancias de las siguientes clases / interfaces para hacer mi trabajo" - p. pasame un File y un PrintWriter y escribiré los contenidos de los primeros en este último.

Y, por supuesto, esto significa que el código no tiene conocimiento del marco DI, ya que la clase se acaba de construir con sus dependencias requeridas. Además, no veo la necesidad de fábricas en este escenario, ya que la clase es su propia fábrica a través del constructor.


En cuanto al escenario que ha identificado en el segundo párrafo, no estoy seguro de si eso está estrictamente relacionado con la inyección de dependencia, sino simplemente el diseño de la jerarquía de clases y las responsabilidades. Ya sea tu clase sabe específicamente cómo crear un Event eso corresponde a, p. un inicio de sesión fallido, en cuyo caso lo hace (es decir, llamando al constructor de la clase); o, no sabe cómo hacerlo, en cuyo caso tendrá que delegar en algunos tipo de fábrica para crear el Event.

Y en este caso, podría configurar su clase para usar la misma fábrica para crear los diez eventos (definir un EventFactory interfaz con 10 métodos), o podría definir una interfaz de fábrica separada (y la implementación) para cada tipo de evento que necesita ser contruido. En este último caso, también necesitaría pasar diez fábricas diferentes en el constructor de su clase principal.

Pero de nuevo, esto no tiene nada que ver con DI IMHO, se trata de cómo diseñar sus clases para la flexibilidad (o "business-ness") frente a la sencillez. Los dos son ortogonales, en mi opinión; primero define qué colaboradores necesita su clase (diez fábricas, una fábrica o cero fábricas) y entonces Usas DI para proporcionar esas dependencias. La presencia o no de DI no debería afectar el diseño de su clase.


6
2018-05-24 12:15