2011-11-15 17 views
7

Me gustaría saber cuál es la mejor práctica en el diseño de constructores de objetos DTO.C# D a constructor e inyección de dependencia

decir que tengo un objeto Dto así:

class CustomerDto 
{ 
    public string Name { get; set; } 
    public string Surname { get; set; } 
    public string Phone { get; set; } 
    ... 
} 

Hay varias maneras de construir el objeto:

pude declarar un constructor:

public CustomerDto(string name, string surname, string phone, ...) 
{ 
    this.Name = name; 
    this.Surname = surname; 
    this.Phone = phone; 
    ... 
} 

Cuando vea este constructor y de inmediato concluir una violación de SRP (responsabilidad única)?

Aunque estos atributos están todos relacionados.

También podría argumentarse que no es necesario validar las propiedades, ya que es una DTO y no tiene ningún comportamiento, y el comportamiento debería estar más bien en el objeto de dominio del que se asigna.

En C# también puede construir más elegante este objeto:

var dto = new CustomerDto() 
{ 
    Name = "Some name", 
    Surname = "Some surname" 
} 

O utilizar un constructor de fluidez o un marco como NBuilder.

También está el uso de marcos de mapeo automático como Automapper. El problema también es usar un contenedor Ioc, el código se vuelve complejo, así como el riesgo de intercambiar argumentos, por ejemplo, se pasa el nombre donde está el apellido o viceversa, la validación podría pasar por alto esta asignación más fácil que explícita como se indicó anteriormente.

Por favor ayuda a convencerme de cuál es la mejor manera.

+0

posible duplicado de [Inyección de dependencia: ¿uso con Objetos de transferencia de datos (DTO)?] (Http: // stackoverflow.com/questions/6297322/dependency-injection-use-with-data-transfer-objects-dtos) –

+0

Me encontré con este mismo problema, y ​​decidí contra el constructor ... Por una razón simple: más tarde, en un mes, o 6 meses, yo u otra persona lo voy a ver y tengo que pensarlo de la misma manera que yo mismo (y usted) estamos pensando ahora. He encontrado que pensar mientras leo código es una indicación de que es demasiado complicado. – dferraro

Respuesta

10

Los tipos de valores como en los ejemplos no son dependencias. Una dependencia proporciona una funcionalidad (o configuración) para el consumidor. En su caso, son solo valores normales que están asignados a su DTO. Siempre que los datos estén juntos, no violará el SRP incluso si asigna muchos valores en el constructor. La única responsabilidad en este caso es retener los datos.

Además, los DTO no deben crearse con un contenedor IoC y no tienen dependencias reales. Debe crearlos manualmente, mediante su marco de persistencia o mediante la asignación automática.

Si la asignación de los valores usando un constructor o propiedades es mejor depende del uso. Si se requieren, la variante del constructor es mejor. Si son opcionales, la propiedad es mejor.

+0

Lo que me gusta de esta respuesta es que confirma lo que pensé sobre una dependencia y que estas no son realmente dependencias, no son subsistemas externos a los que quiere que sustituya un contenedor Ioc. También la razón para la opción 2 es que realmente permite que el marco de mapeo automático haga lo suyo, simplemente transporta los datos entre los límites. Sentí que la preocupación del dto que requiere decir un argumento de nombre no es algo que realmente le preocupe. ¿de acuerdo? – Andre

3

Sugeriría el uso de estructuras de datos inmutables para que la entidad DTO no exponga a ningún setter, obviamente de esta manera el constructor debería proporcionar la capacidad de inicializar todas las propiedades subyacentes de un DTO dado.

así que prefiero:

public CustomerDto(string name, string surname, string phone, ...) 

DTO es un objeto de transferencia de datos, especialmente para representar un conjunto de propiedades que pasar a través de un sistema (distribuido también) las fronteras, por lo que no molesta demasiado con respecto SRP violación. Esto es como el patrón de diseño de Fachada, que incluye un conjunto de operaciones/servicios para simplificar el uso. Entonces en este kase Keep It Simple ganó.

+1

Lo que me pregunto es si Martin Fowler describe el objeto de transferencia de datos como un objeto que mantiene el estado y no tiene ningún comportamiento y realmente lo describe como una forma de reducir las llamadas a los métodos. Al introducir argumentos de constructor y validarlos, está agregando comportamiento. Tenga en cuenta que el objetivo es asignar desde el dominio a la vista y la validación ocurre con mayor probabilidad en el objeto de dominio. Entonces, ¿el dto realmente necesita preocuparse por los argumentos y lo que se requiere, ya que simplemente está llevando los datos a otro lado y la validación es una preocupación diferente? – Andre

+1

La validación de argumentos como 'not null' /' not empty' no es un comportamiento de objeto, considérelo como el material de servicio de su marco de aplicación. Pero si vas a encapsular la validación como 'if (customerRole == Roles.Vip) IncreaseBonus (x)' - esto sería un comportamiento y no debería estar en el DTO, DTO representa el satte FINAL de un objeto – sll

+0

Acabo de probar y parece que Automapper es REALMENTE inteligente, mapeará los nombres de los argumentos del constructor a las propiedades. Aunque creo que depende del uso, si mapea desde un objeto de dominio (ya validado) a una vista (que valida) no hay razón para crear los argumentos del constructor, parece que el enfoque del constructor tiene sin inconvenientes, pero puedo ver uno grande. ¿No puede detectar de inmediato si un argumento es el camino equivocado, o de hecho a qué propiedad se asigna un argumento? – Andre

Cuestiones relacionadas