Devo devolver Collection ou ImmutableCollection de um método?

5

Ao escrever uma API em Java, retornando uma coleção imutável de algum tipo, eu tenho a opção de retornar Collection (ou List , Map , etc) do método, ou% deImmutableCollection da goiaba (ou ImmutableList , ImmutableMap , etc):

private final ImmutableMap<> _immutableMap = ...

public Collection<T> getValues() {
    return _immutableMap.values();
}

ou

public ImmutableCollection<T> getValues() {
    return _immutableMap.values();
}

Qual é o melhor?

Definir o valor de retorno como ImmutableCollection me restringe a usar esse tipo exato para sempre mais, para que eu não possa trocar _immutableMap por meu próprio tipo imutável posteriormente, o que significa, digamos, uma visão imutável dos valores que isn t an ImmutableCollection (construir um requer copiar os valores, e não posso subclassificá-lo para fornecer uma visão imutável de uma coleção mutável).

Mas há um benefício para as pessoas que chamam o método para ver que o valor de retorno é realmente imutável e têm os métodos add e remove marcados como reprovados, em vez de tentar adicionar ou remover itens e falhar em tempo de execução .

Geralmente, eu gosto de retornar o tipo de interface mais específico de um método, para que eu possa alterar a implementação subjacente mais tarde, se necessário, sem quebrar o contrato. Mas há um benefício para os chamadores que retornam um ImmutableCollection , ao custo de restringir o desenvolvimento futuro do método e causar futuros possíveis problemas de desempenho devido à cópia de todos os valores em ImmutableCollection em vez de fornecer uma visão imutável.

    
por thecoop 17.12.2013 / 11:31
fonte

2 respostas

5

Eu normalmente recomendaria usar os tipos mais abstratos ( Collection , List etc) nesse caso.

Razões:

  • Ele fornece mais flexibilidade para retornar um tipo concreto diferente no futuro. Alguém pode encontrar um ImmutableList melhor que Guava, por exemplo.
  • Collection , List etc são mais familiares para os usuários.
  • Ele evita uma dependência em Goiaba em sua API pública. Evitar dependências externas geralmente é bom, use as APIs padrão sempre que puder.

Se você está feliz em se comprometer a sempre usar coleções da Guava, ou se esta é apenas uma API interna que não será amplamente usada por pessoas diferentes, então eu acho que não importa muito.

P.S. se sua preocupação é sinalizar ao usuário que o valor de retorno é imutável, sugiro encontrar outra forma de comunicar isso (anotações, documentação, nomeação de método, etc.). O sistema de tipos Java não foi projetado para comunicar fatos arbitrários sobre tipos (alguns tipos de sistemas mais sofisticados tentam isso, mas ainda é um tópico de pesquisa)

    
por 17.12.2013 / 16:43
fonte
1

Generally, I like to return the most-specific interface type from a method

Você provavelmente quer dizer o tipo menos específico, porque é isso que permite que você troque o tipo de resultado concreto por algo mais específico.

Em geral, se você quiser permanecer aberto assim, você tem que procurar o ancestral comum mais adequado aos tipos que você tem em mente, então caminhe todo o caminho até a raiz até achar que não é mais adequado para o tipo de retorno do seu método.

Vamos tornar esse exemplo concreto com suas duas classes:

ImmutableCollection extends Collection extends Iterable extends Object

e

List extends Collection extends Iterable extends Object

O seu ancestral comum é claramente Collection , por isso deve perguntar-se a seguinte questão:

Would it be ok, if my callers got a Collection back instead of ImmutableCollection?

Eu acho que seria bom, pois eles já estão assumindo uma coleção de qualquer maneira. Então, digamos que você escreve com Collection<T> como tipo de retorno. É fácil ver que agora você pode simplesmente mudar a implementação para um java.util.List não modificável, sem precisar de nenhuma alteração no código do cliente.

Você realmente perde algumas informações, como você observou, não sabendo do tipo, se o seu Collection pode ser modificado ou não. Mas, isso é realmente uma espécie de arenque, porque se você abrir o Javadoc f.ex. do método add , você pode ler facilmente:

Throws:

UnsupportedOperationException - if the add operation is not supported by this collection

Portanto, embora não seja mais possível ver do tipo em si, que a coleção é imutável, você também não possui um tipo que diga claramente que é mutável. Em outras palavras, Collection pode ser lido como manipular com cuidado de qualquer forma.

    
por 17.12.2013 / 15:16
fonte