最近我对Steve McConnell的著作《代码大全(Code Complete)(第二版)》做了技术校对,这本书将在六月份出版。 他真是用心良苦,竟然用掉了整整一章的篇幅来讨论如何给变量命名。 但有个问题,他只是点到为止,并没有深入的探讨,这个问题就是:有两个世上最糟糕的变量名称。 请允许我就此问题发表拙见。
糟糕的变量名几乎到处都是。 常见的一种情况是人们喜欢把变量名的到很短、但变量的生存范围又太大,比如,有人会在整个程序里使用像 $n
这样的变量。 有些程序员可能会知道,在 TRS-80 BASIC语 言里, 只是变量名的前两位字符是有意义的,以至于我们编程是必须把一个手抄本的变量名表格放在键盘旁边参考。
有些时候你会发现某些人命名变量的简化策略是把单词中的元音去掉,用此来替换简单的截取的方式,于是本来是 $cust
的变量名变成了 $cstmr
。我很怀疑人们能否分清这个变量是代表 customers 呢,还是表示 costumers!
有时候你会发现有些变量名是故意起的很怪,作者觉得这样做非常有趣,而不是非常有用。我曾经看到一个循环语句里被命名为 $crap(屎)
的变量。我的一位同事在维护旧代码时,把一个函数命名为 THE_LONE_RANGER_RIDES_AGAIN() (“徘徊者”号航天器又能起飞了)
。 这类变量名都不是我在这里要说的糟糕的变量名。
关于变量命名规范之争通常会演化为一场关于宗教信仰的战争,但是,我确有十足的信心来宣布这 世上最糟糕的变量名 是:
$data
当然,它确实表明这是个数据!它表明变量里能放什么东西!它表明变量里什么都能放!就像是你收拾打包你的物品,把它们移到一个新房子里,你在包箱外 面写着,用很粗的黑字写着:“东西”。
即使这个变量是个函数指针,它里面的数据也是告诉程序何处去运行这个函数。 即使这个变量是 undef
或 NULL
, 包含这种值的变量本身就具有特殊意义。
变量名应该表明变量里装载了什么数据。 问问自己“是什么数据”,这是优化你的变量命名最简单的方法。我曾经看到有人用 $data
表示从数据表里读取的一条记录。写法就像这样:
$data = read_record(); print "ID = ", $data["CUSTOMER_ID"];
问问自己”是什么数据“将会立即给你一个好的命名思路。 命名成 $record
就好多了。 $customer_record
那就更好了。
我开篇就说过有两个最糟糕的变量名,我相信没有人会反对我提出这 世上第二糟糕的变量名 是:
$data2
非常普遍,当任何一个变量依赖于序列号来区别跟它相似的数据时,你需要立即重新考虑这个变量命名。 常常你会看到像这样的代码:
$total = $price * $qty; $total2 = $total - $discount; $total2 += $total * $taxrate; $total3 = $purchase_order_value + $available_credit; if ( $total2 < $total3 ) { print "You can't afford this order."; }
让我们用考古学的方式挖掘这段代码。 首先,这段代码只是指明了订单的总额, $total
。如果没有其它的,这个 $total
定义的无可挑剔。 可不幸的是,有人在此之后加了一段代码,用来处理折扣和税率,偷懒的将它们存到 $total2
里。 最后,有人又加了一段,用来检查用户支付的总值,并把变量命名为 $total3
。
这段代码里最关键的能反映问题的一句是:
if ( $total2 < $total3 )
如果你不回头看看这两个total都是存的什么,你不可能知道这句是在计算什么。
如果你正在面临着要给某变量命名成 $total2
的问题, 请先把已有的变量名变的更有意义。 花上几分钟的时间,给这些变量合适的名称。这个层面上的代码反省是你能做到的最简单的,成本最低的,形式最安全的反省, 特别是当这个变量在一个封闭的子程序里时,更需要这样。
让我们对上面这段糟糕的代码做一个简单的查找替换过程:
$order_total = $price * $qty; $payable_total = $order_total - $discount; $payable_total += $payable_total * $taxrate; $available_funds = $purchase_order_value + $availble_credit; if ( $payable_total < $available_funds ) { print "You can't afford this order."; }
变化的只有变量名,这样一来这段代码就很容易理解了。 现在所有的 _total
变量都不存在歧义了。 而且,你会发现: if
比较语句写颠倒了。 有效的命名让这种错误极易发现。
这种以数字结尾的变量并不是都不好,有个例外。如果这个实体本身就是以数字结尾的,变量也应该留下这个数字。对于跨省的国道的变量命 名就应该像 $route31
。如果你把它改成 $route_thirty_one
那就有点傻了。
最后,记着这些命名习惯对于定义程序变量和定义文件名同样适用。 我通常也不愿意花太多的时间去考虑文件的命名,当然这是另外一个话题了。
还有什么其他的让你抓狂的命名现象?
马上去改程序中的 data …
有意思,我本来也想讨论一下如何给变量命名,因为我发现当我要写一个方法或者函数的时候,我会花更多的时间在如何让方法名或函数名更好。
data也可以用,但最好用在某个小类里,或者小函数中
data2貌似比data多一個問題(混淆),所以其實data2也許更爛一些?
好端端的笑点就被戳中了…XDDDDDD
我也被戳中笑点了,“东西”,哈哈哈
$data 成为一个很烂的变量的理由有点过于牵强。起码要比 $var 好一点,而且在某些情况下 data 代表了一个很实际的东西,使用其他变量名未必是更好的选择。
我有一做.Net的老师,他喜欢将数据库中的表命名为table1、table2、table3。。。
躺枪了 – -data
data是一个有意义的命名,它的含义就是”数据”
这可以很清晰的与其它的那些”状态”、”用户”做出区分
在一个不公开的方法里使用data是没有任何问题的
只有当这个名字在公开方法中作为参数时它才有问题——这时候应当用source、target等词汇代替,以实现更进一步的区分:”是谁的数据”
至于这些数据究竟是什么类型,做什么用,这不是参数名字该做的事情,请在你的类、方法、变量类型上写清楚。
假如你的语言没有变量类型也没有类,那就用一个清晰地方法名解释一切。