Capa de acceso a datos: lista de exposición <>: ¿mala idea?

Actualmente estoy codificando una capa de acceso a datos simple, y me preguntaba qué tipo debería exponer a las otras capas.

I am going to internally implement the Data as a List<>, but I remember reading something about not exposing the List type to the consumers if not needed.

public List GetAllUsers()//non C# users: that means List of User :)

¿Sabes por qué (google no ayudó)? ¿Qué expone normalmente para ese tipo de cosas? IList? IEnumerable?

3

3 Respuestas

Usually it's best to expose the least powerful interface that the user can still meaningfully work with. If the user just needs some enumerable data, return IEnumerable. If that's not enough because the user needs to be able to modify the list (attention! shouldn't often be the case), return an IList.

/EDITAR:

Joel hace una pregunta válida en su comentario: ¿por qué exponer la interfaz menos poderosa en lugar de otorgarle al usuario la máxima potencia? (Parafraseado)

La idea detrás de esto es que el método que devuelve los datos puede no esperar que el usuario modifique su contenido: otro método de la clase aún podría esperar que la lista no esté vacía después de que se devolvió una referencia a ella. Imagine que el usuario elimina todos los datos de la lista. El otro método ahora tiene que hacer una comprobación adicional de que ele podría haber sido innecesario.

Más importante aún, esto expone partes de la implementación interna a través del tipo de devolución. Si necesito cambiar la implementación en el futuro para que ya no use un contenedor IList , tengo un problema: o necesito cambiar el contrato del método, introduciendo un cambio de construcción. O necesito copiar los datos en un contenedor de lista.

Como ejemplo, imagina que una implementación eficiente usa un diccionario y simplemente devuelve la colección Values ​​ que no implementa IList .

6
agregado
Además, tiene la opción de devolver ReadOnlyCollection cuando desee controlar eso en el lado del destinatario.
agregado el autor CVertex, fuente
No he aceptado la idea de "menos poderosa" todavía; ¿Qué tal hacer que cada bloque de código sea lo más útil posible?
agregado el autor Joel Coehoorn, fuente

Definitivamente un ISomething. El uso de una interfaz reducirá el acoplamiento y facilitará el cambio de los detalles de la implementación de la capa de datos más adelante. Qué interfaz depende de las circunstancias. IList es bueno, pero a veces puede necesitar funcionalidad ICollection o quiere especificar valores que son ReadOnly.

3
agregado

Debería pensar detenidamente antes de devolver IEnumerable. Si el código subyacente usa "rendimiento" para generar IEnumerable, o está utilizando LINQ, terminará manteniendo abiertos los recursos utilizados.

Debe copiar IEnumerable en otro IEnumerable antes de devolverlo. Al usar IList, hace esto un requisito, para que nadie pueda devolver un IEnumerable inadvertidamente.

Por otro lado, devolver un IList implica para la persona que llama que pueden cambiar la lista devuelta.

2
agregado
Buen punto. Tal vez podrías agregar un ejemplo que ilustre tal caso para mayor completud.
agregado el autor Konrad Rudolph, fuente