O que há de errado em retornar a hashtable do método público e quando faz sentido fazer isso?

9

Quais são os problemas de design ao retornar uma hashtable de um método público quando você deseja retornar vários itens em vez de criar uma classe e retornar um objeto disso?

Se houver problemas, em que circunstâncias faz sentido fazê-lo?

Como a resposta a essa pergunta muda dependendo se o idioma é dinâmico ou não?

Editar: Isso é para esclarecer que as chaves seriam constantes e fazem parte do código, não dos dados. Algo para o qual normalmente criamos uma classe. A questão é por que seria errado usar a hashtable, se criar uma classe realmente parece ser a escolha certa.

Muhammad Hasan Khan
fonte

Respostas:

11

Use uma classe melhor definida como um tipo de retorno do que uma hashtable que contém um número arbitrário de valores como pares nome / valor.

  1. O primeiro e o primeiro ponto mais importante é - Manutenção. Observando o código, um novo programador nunca pode dizer quais são os valores que o método está retornando. Se uma nova pessoa não entender isso olhando para o código, ele não será útil e propenso a erros sempre que alguém adicionar mais valores / chaves a esses dados ou aprimorar o aplicativo.

  2. Métodos são contratos entre o chamador e o serviço. A coisa mais importante em um método é sua entrada e saída. Essa entrada e saída devem ser facilmente legíveis, compreensíveis e auto-documentadas. Se você usar uma classe Person como um valor de retorno que tem nome, sobrenome, idade - é auto-documentável. Se você gerar um Javadoc para isso, o usuário poderá navegar entre as classes para entender isso melhor. Se você usa uma hashtable, precisa explicá-la nos comentários que ninguém lerá ou atualizará quando as coisas mudarem.

  3. Você não pode usar genéricos, como HashMap<String,String>no caso, se desejar adicionar um número (por exemplo, idade) à declaração de retorno. Se você não usar genéricos, será necessário transmitir entre o objeto e o tipo real. Você pode salvar isso se usar a digitação dinâmica.

  4. Além disso, há mais chances de falha no tempo de execução do que detectar problemas no tempo de compilação. por exemplo, se alguém excluir uma entrada do hashmap e um dos chamadores antigos estiver esperando a entrada, o cliente falhará durante o tempo de execução. É sempre melhor capturar esse problema em tempo de compilação.

  5. Será difícil retornar um tipo imutável se você quiser usar o hashmap como tipo de retorno e assim por diante. Mas se você usar um usuário definido seu próprio tipo, poderá controlar isso.

Será tentador usar um hashmap como tipo de retorno, porque você pode evitar a criação de duas classes no início, mas será um pesadelo manter o código no futuro. Vá orientado a objetos !!!!

java_mouse
fonte
11
Você parece ter entendido a pergunta corretamente. Obrigado.
Muhammad Hasan Khan
8

Um dos problemas seria que, em muitos casos, a chave da tabela de hash seria uma string. Portanto, os consumidores do método precisariam saber de antemão quais chaves usar para extrair os dados. Isso daria o potencial de erros devido a erros de ortografia ao acessar os dados.

Outra desvantagem é a refatorabilidade. Se você decidir mais tarde alterar o nome de um membro, terá várias sequências mágicas que também precisam ser alteradas. É muito mais simples renomear um membro da classe usando as ferramentas de refatoração fornecidas pela maioria dos bons IDE. Com uma tabela de hash, você provavelmente teria que fazer uma operação de localização / substituição em todos os arquivos de origem, o que poderia ser problemático.

Por fim, você perderá a verificação do tempo de compilação do acesso do membro - em termos de nome e tipo. O último não é um problema se a sua tabela de hash contiver apenas um tipo de objeto, mas se ela contiver muitos (mesmo na mesma cadeia hierárquica), você realmente deseja aproveitar o sistema de tipos do seu idioma e obter a verificação do tempo de compilação lá. Na maioria dos IDE, você terá algum tipo de recurso intellisense / autocomplete - eles funcionam analisando o sistema de tipos, mas não poderão ajudá-lo com as chaves da tabela de hash.

Quanto aos momentos em que seria apropriado retornar uma tabela de hash (ou outra coleção de pares de valores-chave), você usaria isso quando os valores e as chaves não fossem conhecidos no momento da compilação. Por exemplo, se você tiver um método que analise uma string de consulta e retorne as chaves e os valores correspondentes, uma tabela de hash seria uma boa opção. Nesse caso, você também gostaria de pensar em retornar algum tipo de tabela de hash imutável ou apenas de leitura.

Editar - A maioria dos pontos levantados nesta resposta deixa de ser aplicada quando você está falando sobre linguagens dinâmicas :)

MattDavey
fonte
E se o idioma for dinâmico?
Muhammad Hasan Khan
Eu não sou especialista em linguagens dinâmicas, então alguém provavelmente pode fornecer uma resposta melhor para isso. Mas eu sei que linguagens dinâmicas não fazem a verificação do tipo de tempo de compilação de qualquer maneira. Mas, nesse caso, retornando um objeto e retornando uma tabela hash não são tão diferentes ..
MattDavey
3
@ Hasan Khan: Nesse caso, pode não haver realmente nenhuma diferença entre uma hashtable e uma instância de classe. Por exemplo, em Javascript, todos os objetos são hashtables, e object.property é exatamente a mesma coisa que o objeto ['propriedade']
Michael Borgwardt
"Com uma tabela de hash, você provavelmente teria que fazer uma operação de localização / substituição em todos os arquivos de origem, o que poderia ser problemático". Só se você tiver escolhido chaves pobres e nunca tentou fator fora dos normais de modo que eles estão definidos em um lugar ...
Donal Fellows
7

O argumento mais importante contra isso seria que você está expondo muitas informações ao consumidor. O código consumidor apenas precisa saber que é uma coleção de valor-chave (dicionário) de algum tipo; seja implementado como um hashmap, uma lista de associações, um teste ou qualquer outra coisa, é relativamente desinteressante. Portanto, a maneira correta seria retornar por uma interface adequada ( IDictionaryou qualquer que seja o idioma de sua escolha) em vez do tipo real.

Tudo isso assumindo que você realmente precisa de um dicionário para representar seus dados, ou seja, seus dados consistem em pares de chave / valor, onde as chaves são únicas entre o conjunto de dados e não podem ser corrigidas em tempo de compilação. Se você possui chaves pré-conhecidas, deve criar um tipo adequado (ou vários, conforme necessário) para seus dados. Tudo se resume a considerar as próprias chaves como parte dos dados ou parte do código.

EDIT :

Para esclarecer, estou usando o termo dicionário para significar o tipo mais genérico de estrutura de dados de valor-chave aqui; Não me refiro a nenhuma implementação específica de linguagem, como Python dictou .NET Dictionary.

tdammers
fonte
11
+1 em "Tudo se resume a considerar as próprias chaves como parte dos dados ou parte do código". - Essa é uma boa maneira de dizer. Não tenho certeza de quão universal é o termo 'dicionário', em oposição a 'mapa', por exemplo.
precisa saber é o seguinte
O retorno do dicionário não foi intencional. chaves faziam parte do código, não dos dados.
Muhammad Hasan Khan
A verdadeira questão é o raciocínio por trás de 'Você deve criar um tipo adequado'. A pergunta é por que?
Muhammad Hasan Khan
2

Uma pergunta que eu me faria é "as chaves estão mudando neste dicionário?" Se eles são constantes, você deve retornar um objeto ou outra estrutura de dados apropriada. Se eles são dinâmicos, convém retornar algum tipo de estrutura de estilo de dicionário. Finalmente, se houver algumas chaves que serão constantes e um conjunto desconhecido de chaves dinâmicas, convém retornar uma estrutura de dados híbrida, incluindo alguns valores fixos e algum tipo de dicionário para o estouro.

Wyatt Barnett
fonte
De fato, seu conselho está correto, mas a questão é o que há de errado em escolher usar hashtable quando a classe é uma escolha melhor.
Muhammad Hasan Khan
Não é nem / ou; uma classe pode facilmente conter dicionário, se você precisar.
Wyatt Barnett