从公共方法返回哈希表有什么问题,什么时候才有意义?


9

当您要返回多个项目而不是创建一个类并返回该对象时,从公共方法返回哈希表有哪些设计问题?

如果确实有问题,那么在什么情况下才有意义?

这个问题的答案如何根据语言是否动态而变化?

编辑:这是为了澄清键将是常量,并且是代码而不是数据的一部分。我们通常为之创建类的东西。问题是,如果创建类确实确实是正确的选择,那么为什么使用哈希表却会出错呢?

Answers:


11

使用比将任意数量的值作为名称/值对保存的哈希表更好的定义的类作为返回类型。

  1. 首先,最重要的一点是-可维护性。通过查看代码,新程序员永远无法说出该方法返回的值是什么。如果新手无法通过查看代码来理解这些内容,那么当有人要向该数据添加更多键/值或增强应用程序时,该代码将无用且容易出错。

  2. 方法是调用者与服务之间的合同。方法中最重要的是它们的输入和输出。此输入和输出应易于阅读和理解,并具有自记录功能。如果您使用Person类作为具有名字,姓氏,年龄的返回值-这是自我记录。如果为此生成了Javadoc,则用户可以在各类之间导航以更好地理解这一点。如果您使用哈希表,则必须在注释中对其进行解释,当情况发生变化时,任何人都不会阅读或更新该哈希表。

  3. HashMap<String,String>如果要在return语句中添加数字(例如age),则不能使用泛型。如果不使用泛型,则必须在对象与实际类型之间来回转换。如果您使用动态类型,则可以保存。

  4. 与在编译时发现问题相比,运行时失败的可能性也更大。例如,如果某人从哈希图中删除了一个条目,而一个旧调用者期望该条目,则客户端在运行期间会失败。最好在编译时捕获此问题。

  5. 如果要使用hashmap作为返回类型,则很难返回不可变类型。但是,如果您使用用户定义的自己的类型,则可以控制此类型。

将hashmap用作返回类型将很诱人,因为您可以避免在开始时创建几个类,但是将来维护代码将是一场噩梦。面向对象!!!


1
您似乎已经正确理解了这个问题。谢谢。
穆罕默德·哈桑·汗

8

问题之一是,在许多情况下,哈希表的键是字符串。因此,该方法的使用者必须事先知道要使用哪些键来提取数据。在访问数据时,这可能会由于拼写错误而产生错误。

另一个缺点是可重构性。如果您以后决定更改成员的名称,那么您将有一堆需要更改的魔术字符串。使用大多数优秀IDE所提供的重构工具来重命名类成员要容易得多。使用哈希表,您可能必须对所有源文件进行查找/替换操作,这可能会出现问题。

最后,您将失去对成员访问权限的编译时检查-无论是名称还是类型。如果您的哈希表仅包含一种类型的对象,但如果它包含许多类型的对象(即使在同一层次链中),那么后者就不是问题,您真的想利用语言的类型系统并在那里进行编译时检查。在大多数IDE中,您将具有某种智能/自动完成功能-这些功能可以通过查看类型系统来实现,但它们将无法为您提供哈希表键。

至于时候,它是适当返回一个哈希表(或键值对其他类似的集合),当这两个值,你可以使用这个和按键并不在编译时已知。例如,如果您有一个解析查询字符串并返回键和对应值的方法,则哈希表将是一个不错的选择。在这种情况下,您还需要考虑返回某种不可变或只读哈希表。

编辑 -在谈论动态语言时,此答案中提出的大多数观点不再适用:)


如果语言是动态的怎么办?
穆罕默德·哈桑·汗

我不是动态语言方面的专家,因此其他人可能可以为此提供更好的答案。但是我知道动态语言无论如何都不会编译时间类型检查。但是,在这种情况下,返回一个对象,并返回一个哈希表并非如此不同..
MattDavey

3
@Hasan Khan:在那种情况下,哈希表和类实例之间实际上可能没有任何区别。例如,在Javascript中的所有对象都是哈希表,并object.property是完全一样的东西为对象[“财产”]
迈克尔博格瓦特

“使用散列表,您可能必须对所有源文件进行查找/替换操作,这可能会出现问题。” 仅当您选择了错误的密钥并且从未尝试过将标准的密钥
分解

7

对此最重要的论据是您向消费者暴露了太多信息。消费代码只需要知道它是某种键值集合(字典)即可;无论是将其实现为哈希图,关联列表,特里还是任何东西,都相对没有意思。因此,正确的方法是通过合适的接口(IDictionary或您选择的语言使用的任何值)而不是实际类型返回。

所有这一切都假定您实际上需要一个字典来表示数据,即,您的数据由键/值对组成,其中键在数据集中是唯一的,并且不能在编译时固定。如果您具有预先知道的密钥,则应该为数据创建一个适当的类型(或根据需要创建多个)。这取决于您是否将密钥本身视为数据的一部分或代码的一部分。

编辑

为了澄清起见,我在这里使用术语字典来表示键值数据结构的最通用类型。我的意思不是任何特定于语言的实现,例如Python dict或.NET Dictionary


1
+1表示“这取决于您将密钥本身视为数据的一部分还是代码的一部分。” -这是个好方法。例如,不确定“字典”一词与“地图”相对通用。
MattDavey 2012年

不希望返回字典。键是代码而非数据的一部分。
穆罕默德·哈桑·汗

真正的问题是“您应该创建适当的类型”背后的原因。问题是为什么?
穆罕默德·哈桑·汗

2

我会问自己一个问题:“此词典中的键是否正在更改?” 如果它们是常量,则应返回一个对象或其他适当的数据结构。如果它们是动态的,则您可能需要返回某种字典样式结构。最后,如果有一些将保持不变的键和一些未知的动态键集,则您可能希望返回一个混合数据结构,包括一些固定值和某种针对溢出的字典。


确实,您的建议是正确的,但问题是,当类是更好的选择时,选择使用哈希表有什么问题?
穆罕默德·哈桑·汗

它不是/或;如果需要,一个类可以轻松地包含字典。
Wyatt Barnett'1
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.