原文地址
英文原文地址
最近我对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
那就有点傻了。
最后,记着这些命名习惯对于定义程序变量和定义文件名同样适用。 我通常也不愿意花太多的时间去考虑文件的命名,当然这是另外一个话题了。
还有什么其他的让你抓狂的命名现象?