0 Comments

避免像tmp和retval这样泛泛的名字

发布于:2013-01-10  |   作者:广州网站建设  |   已聚集:人围观

 

使用像tmp、retval和foo这样的名字往往是“我想不出名字”的托辞。与其使用这样空洞的名字,不如挑一个能描述这个实体的值或者目的的名字。

例如,下面的JavaScript函数使用了retval:


  1. var euclidean_norm = function (v) {  
  2.     var retval = 0.0;  
  3.     for (var i = 0; i < v.length; i += 1)  
  4.         retval += v[i] * v[i];  
  5.     return Math.sqrt(retval);  
  6. }; 

当你想不出更好的名字来命名返回值时,很容易想到使用retval。但retval除了“我是一个返回值”外并没有包含更多信息(这里的意义往往也是很明显的)。

好的名字应当描述变量的目的或者它所承载的值。在本例中,这个变量正在累加v的平方。因此更贴切的名字可以是sum_squares。这样就提前声明了这个变量的目的,并且可能会帮忙找到缺陷。

例如,想象如果循环的内部被意外写成:


  1. retval += v[i]; 

 

如果名字换成sum_squares这个缺陷就会更明显:

  1. sum_squares += v[i]; //我们要累加的"square"在哪里?缺陷! 

建议

retval这个名字没有包含很多信息。用一个描述该变量的值的名字来代替它。

然而,有些情况下泛泛的名字也承载着意义。让我们来看看什么时候使用它们有意义。

tmp

请想象一下交换两个变量的经典情形:


  1. if (right < left) {  
  2.     tmp = right;  
  3.     right = left;  
  4.     left = tmp;  

在这种情况下,tmp这个名字很好。这个变量唯一的目的就是临时存储,它的整个生命周期只在几行代码之间。tmp这个名字向读者传递特定信息,也就是这个变量没有其他职责,它不会被传到其他函数中或者被重置以反复使用。

但在下面的例子中对tmp的使用仅仅是因为懒惰:


  1. String tmp = user.name();  
  2. tmp += " " + user.phone_number();  
  3. tmp += " " + user.email();  
  4. ...  
  5. template.set("user_info", tmp); 

尽管这里的变量只有很短的生命周期,但对它来讲最重要的并不是临时存储。用像user_info这样的名字来代替可能会更具描述性。

在下面的情况中,tmp应当出现在名字中,但只是名字的一部分:


  1. tmp_file = tempfile.NamedTemporaryFile()  
  2. ...  
  3. SaveData(tmp_file, ...) 

 

请注意我们把变量命名为tmp_file而非只是tmp,因为这是一个文件对象。想象一下如果我们只是把它叫做tmp:

  1. SaveData(tmp, ...) 

只要看看这么一行代码,就会发现不清楚tmp到底是文件、文件名还是要写入的数据。

建议

tmp这个名字只应用于短期存在且临时性为其主要存在因素的变量。

循环迭代器

像i、j、iter和it等名字常用做索引和循环迭代器。尽管这些名字很空泛,但是大家都知道它们的意思是“我是一个迭代器”(实际上,如果你用这些名字来表示其他含义,那会很混乱。所以不要这么做!)

但有时会有比i、j、k更贴切的迭代器命名。例如,下面的循环要找到哪个user属于哪个club:


  1. for (int i = 0; i < clubs.size(); i++)  
  2.     for (int j = 0; j < clubs[i].members.size(); j++)  
  3.         for (int k = 0; k < users.size(); k++)  
  4.             if (clubs[i].members[k] == users[j])  
  5.                 cout << "user[" << j << "] is in club[" << i << "]" << endl

 

在if条件语句中,members[]和users[]用了错误的索引。这样的缺陷很难发现,因为这一行代码单独来看似乎没什么问题:

  1. if (clubs[i].members[k] == users[j]) 

 

在这种情况下,使用更精确的名字可能会有帮助。如果不把循环索引命名为(i、j、k),另一个选择可以是(club_i、members_i、user_i)或者,更简化一点(ci、mi、ui)。这种方式会帮助把代码中的缺陷变得更明显:

  1. if (clubs[ci].members[ui] == users[mi]) #缺陷!第一个字母不匹配。 

 

如果用得正确,索引的第一个字母应该与数据的第一个字符匹配:

  1. if (clubs[ci].members[mi] == users[ui])  #OK。首字母匹配。 

对于空泛名字的裁定

如你所见,在某些情况下空泛的名字也有用处。

建议

如果你要使用像tmp、it或者retval这样空泛的名字,那么你要有个好的理由。

很多时候,仅仅因为懒惰而滥用它们。这可以理解,如果想不出更好的名字,那么用个没有意义的名字,像foo,然后继续做别的事,这很容易。但如果你养成习惯多花几秒钟想出个好名字,你会发现你的“命名能力”很快提升。

标签:
飞机