Camada de acesso a dados: lista de exposição <>: má ideia?

No momento, estou codificando uma camada de acesso a dados simples e fiquei me perguntando qual tipo devo expor para as outras camadas.

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 :)

Você sabe por que (o Google não ajudou)? O que você costuma expor para esse tipo de coisa? IList? IEnumerable?

3

3 Respostas

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 faz uma pergunta válida em seu comentário: Por que, de fato, expor a interface menos poderosa em vez de conceder ao usuário o poder máximo? (parafraseado)

A ideia por trás disso é que o método que retorna os dados pode não esperar que o usuário modifique seu conteúdo: Outro método da classe ainda pode esperar que a lista fique vazia depois que uma referência a ela for retornada. Imagine o usuário remove todos os dados da lista. O outro método agora tem que fazer uma verificação adicional de que ele poderia ter sido desnecessário.

Mais importante, isso expõe partes da implementação interna por meio do tipo de retorno. Se eu precisar alterar a implementação no futuro para que ela não use mais um contêiner IList , eu tenho um problema: Eu preciso alterar o contrato do método, introduzindo uma alteração de quebra de construção. Ou eu preciso copiar os dados em um contêiner de lista.

Como exemplo, imagine que uma implementação eficiente usa um Dictionary e apenas retorna a coleção Values ​​ que não implementa o IList .

6
adicionado
Além disso, você tem a opção de retornar ReadOnlyCollection quando quiser controlá-lo no lado do receptor.
adicionado o autor CVertex, fonte
Eu ainda não comprei a idéia do 'menos poderoso'; Que tal tornar cada bloco de código tão útil quanto possível?
adicionado o autor Joel Coehoorn, fonte

Definitivamente um ISomething. O uso de uma interface reduzirá o acoplamento e facilitará a alteração dos detalhes da implementação da camada de dados no futuro. Qual interface depende das circunstâncias. IList é bom, mas às vezes você pode precisar de funcionalidade ICollection ou deseja especificar valores que são somente leitura.

3
adicionado

Você deve pensar cuidadosamente antes de retornar IEnumerable. Se o código subjacente estiver usando "yield" para gerar o IEnumerable ou estiver usando o LINQ, você acabará abrindo todos os recursos utilizados.

Você deve copiar o IEnumerable em outro IEnumerable antes de retorná-lo. Usando IList, você faz isso um requisito, para que ninguém possa inadvertidamente retornar um IEnumerable.

Por outro lado, retornar um IList implica ao chamador que eles podem alterar a lista retornada.

2
adicionado
Bom ponto. Talvez você possa adicionar um exemplo que ilustre esse caso por completo.
adicionado o autor Konrad Rudolph, fonte