2009-12-31 20 views
13

Tengo una clase para la importación de productos desde el archivo CSV que requiere aproximadamente 7 parámetros. Esta es una información que definitivamente es necesaria para el importador.¿Es malo mezclar las inyecciones basadas en el constructor y las basadas en el colocador?

Todos estos parámetros tienen la misma duración. Al final debemos tener un Immutable Object.

Tenía demasiado miedo para enumerarlos todos en el constructor debido a su efecto sobre la legibilidad y decidí mover 3 de ellos a la inyección de setters. Pero obviamente no es una solución elegante.

Preguntas:

1) es la mezcla de inyecciones a base setter-a base de constructor y una mala práctica?

2) ¿Cómo se puede resolver este problema en particular?

Estaba pensando en aplicar la refactorización "Presentar objeto de parámetro" de Martin Fowler, pero hay un problema con esto.

4 Los parámetros se pueden mover fácilmente al objeto Parameter (customerId, projectId, languageId, etc.): todos los números enteros.

Otros 3 parámetros son un objeto que inyecto (se requiere para pruebas de unidad simuladas).

+0

Esto dependerá de su contenedor DI ... algunos lo hacen más fácil que otros. – skaffman

+4

@skaffmann: Estoy totalmente en desacuerdo. El uso de patrones DI no debe estar dictado por la elección de DI Container: el contenedor está ahí para ayudarlo, no para restringirlo. –

+0

@Nikita: ¿por qué no introduces el objeto de parámetro completo e inyectas tus simulaciones en el parámetro? –

Respuesta

22

No es necesariamente malo mezclar Inyección de constructor e Inyección de propiedades, pero puede que no sea tan común. Como estrategia general, evite Inyección de propiedades, ya que es mucho más difícil de implementar correctamente (esto puede parecer contra-intuitivo, pero es cierto).

Es importante entender cuándo usar cada patrón.

  • Constructor Inyección debe ser su patrón de inyección predeterminado. Es súper fácil de implementar y puede garantizar invariantes: asígnelo a un campo de solo lectura para garantizar las invariantes del consumidor.
  • La inyección de propiedad se puede utilizar cuando tiene una buena implementación de local predeterminada, pero desea seguir el Open/Closed Principle y permitir que los usuarios avanzados amplíen la clase proporcionando una implementación alternativa.

Nunca debe aplicar Property Injection debido a los cosméticos del constructor.

Cuando necesite demasiadas dependencias, es una señal de que puede estar violando el Single Responsibility Principle - la clase simplemente está tratando de hacer demasiado a la vez.

En lugar de la introducción de un objeto de parámetro (de lo contrario una buena sugerencia), una mejor opción es encapsular dos o más de las dependencias en un servicio agregación que orquesta la interacción de estas dependencias.

Imagínese que su constructor inicial tiene el siguiente aspecto:

public MyClass(IDep1 dep1, IDep2 dep2, IDep3 dep3, IDep4 dep4, IDep5 dep5) 

Después de aplicar un poco de análisis, a averiguar que en este caso IDep1, IDep3 y IDep4 se pueden utilizar juntos de una manera particular.Esto le permitirá introducir un servicio de agregación que encapsulan éstos así:

public class AggService : IAggService 
{ 
    public AggService(IDep1 dep1, IDep3 dep3, IDep4 dep4) 
    { 
     // ... 
    } 

    // ... 
} 

Ahora puede volver a escribir el constructor original a este:

public MyClass(IAggService aggSrvc, IDep2 dep2, IDep5 dep5) 

y así sucesivamente ...

Se Es muy común que el servicio agregado resulte ser un concepto adecuado por sí mismo, y de repente tiene una API más rica que cuando comenzó.

+0

¿Cómo se diferencia un servicio de agregación de un Objeto de parámetro? Parece que está sugiriendo que puede tener una relación más expresiva y concreta con el modelo de dominio, pero eso debería ser cierto para los objetos de parámetros bien diseñados, ¿no es así? –

+0

Muy claro e interesante. Gran respuesta. Gracias, Mark! – ep3static

+0

@Jeff Sternal: un servicio de agregación no puede diferir mucho de un Objeto de parámetro, pero los servicios de agregación tienden un poco más hacia el Principio de Hollywood (algo bueno). Los Objetos de parámetros normalmente son estructuras que contienen objetos relacionados que puede extraer y usar individualmente. Un servicio de agregación ocultará esas dependencias del consumidor y, en su lugar, ofrecerá una funcionalidad general. Sin embargo, no es una distinción clara ... –

Cuestiones relacionadas