Contents

我承认我是其中的一员。要向发明者 Charles Simonyi 道个歉。

长期以来,不问出处,不求起源,只是单纯接受一些看起来是常识或事实的结论,导致此问题发生。这是我有的一点不足,要改进。多思考,多看书是良方,庆幸在不断服药中。如果不是看到 More Joel On Software软件随想录)里 I’m Hungary 那一节,我会继续误解下去。扯远了,回归。

估计可能 90% 的人都只是知道**匈牙利命名法**要求在变量名前面加上类别。这里用类别,而不是 type,也正是书里所说的,这个关键点就是使得不少人误解和背弃这种用法的原因。

多数人的用法是加上变量所代表的数据类型作用域,如:

  • n 表示 number
  • s 表示 string
  • g 表示全局变量

这种用法,在弱类型语言或者使用之前一些并不完善的 IDE 时,用处还是明显的。可以避免把数据赋值到不同类型的变量中而产生错误,或者养成不好的编程习惯。但是,其实更深层的意思应该是在书中提到的:

Make wrong code look wrong

这是什么意思呢?就是让错误的代码更容易暴露出来。一些不符合命名规范或非约定俗成的变量的使用,或者不恰当的方法调用,应该使得它们只要我们的眼睛一扫过,就可以判断出来。而这个基本原则,正是匈牙利命名法真正的用意所在。

在书中提到的关于用前缀来区别一些字符串是用户输入(Unsafe)的,还是已经处理过的(Safe)的例子,就很好的说明了这种意图。在当前很多大型的企业级系统里面,数据交换在用户,数据库,和不同子系统之间的交换需求是那么多且复杂,判断数据是否已经恰当处理就显得很重要。什么是用户提供的原始数据,什么是从数据库中拿出来的数据,有没有经过HTML编码,XML编码等。这些如果处理不好,就会产生一些隐藏很深的Bug。

还有一个适合这个应用场景的例子,我想就是时间数据的存储。在一些供跨国企业或用户协作的系统里面,时间数据的存储和显示,往往伴随着 TimeZone 的处理。一般来说,时间数据都是把 ISO 时间,也就是不包含时区的时间,存储到数据库里面,当需要显示的时候,再根据用户的时区来转换处理。当然,也有一些系统在业务上的需求是把已经考虑了时区的时间存储在数据库的。这样的话,什么时间是包含了时区信息的,什么时间是没有包含的,也是关键点。加上恰当的命名前缀,再结合业务需求,很容易就可以判断代码处理的对不对了,而不需要再翻看一系列的代码。

当然,你可以说,我可以把变量名写的很详尽,如 unsafeContent 而不是 _usContent_。 这是可以的。只是这样就使得我们的手和眼睛需要处理更多的字符,而且也混合了变量名中的类别意义和业务意义两部分在一起。个人感觉还是分开好点。

回想起来,很多对 Code Convention 上的要求,除了让程序员可以更容易理解代码以外,另一层意思也是更容易发现错误或问题所在,比如:

  • 简短的方法体
  • 有意义的变量和方法名称
  • Self-Documentary Code 或者是加注释
  • 恰当缩进和使用括号{}

所以说,我们也不应该一棍打死匈牙利命名法。有需要的话,只要整个团队一致认为某些情况确实可以增加代码清晰度和容易看出问题,那么定义清楚什么时候该用就行了。

Contents