3956 字
20 分钟
The Art of Naming the Variable Names
学习笔记

原B站up micro_frank 的视频课程,现已更名为 零界世访,且该视频已被其删除或隐藏。

一、总论#

身为IT行业的小白,我们不能仅仅沉浸于代码语言的层次上或算法与数据结构的快感中,我们应该思考:但在这些基本都搞定了呢!?我们又该何去何从?

实际上,最高深的层次往往不是代码的算法与数据结构的构建本身,而是编程的艺术。一些大师级别的人物,他们在谈到编程或软件构建上绝不仅停留在代码、语言、算法和数据结构上,而是提升到一个极高的层次——编程的艺术。也就是说:思维和艺术将会决定你写代码的高度。

而编程的艺术其中一个重要的点便是——变量名命名

变量名命名的重要性#

变量名真正的命名往往直接决定软件构建的效果、代码的性能,甚至可能影响到软件的安全和效益,以及所出现的问题一半都可能源于变量名命名。

我们为何如是说呢?“一个好的变量名命名不是一个即时的效果,而是一个长期的效益。”一个例子:我们设想下列情景:

(1)我养了一只狗🐕,它叫小黑,小黑死去之后,我又养了一只叫小白的狗🐕;这样并无问题,我们都能分清楚。

(2)可是,如果我养了10000只不同(这里说不同只是方便假设,因为这里不能用数组,而是无联系的10000个变量)的鸡,那么一万只鸡我该是这样命名吗?:a,b,c,d…aa,ab,………当第二天我们说鸡chicken下蛋了,那么鸡chicken是谁呢?我们还能搞清吗?所以说变量名命名的方式直接决定变量名的所带来的后果/效果。没有好的变量名命名,会导致程序难以理解和维护

变量名命名的规范

我们这里以C语言来进行代码部分的编写,以进行具体阐释。

关于常见的错误命名(🔺注意:这是在具有实际开发情景下的代码,不是无实际意义的语法展示示例):

一些规范示范

我们很容易发现,不同的变量名命名直接会导致阅读体验的分野

而一个标准规范的变量名命名应具备什么样的特质呢?

可读性好、便于记忆、见名知意;或者更直白的说:一眼就可以看出这是在干什么。我们应心怀这样一句话去命名变量——“优秀的代码命名都是自解释的”

仍是上述的例子:判断是否为闰年 -is_leap_year(),(关于为何不用中文拼音命名而采用英语命名,这是由语言自身和历史传统影响的,这里不做阐释),我们能否将其改为is_leap()呢?不能。leap还有跳跃之意,若是如此命名,必会造成歧义;而一个好的变量或函数名应准确表达含义,便于阅读与理解。

变量名命名的注意#

但是,准确表达含义并不是要求名字严格按照英文使其变得特别长。举个例子,我们定义一个变量unsigned int the_max_country_number_of_the_olympic_team = 20;如此定义变量名,我们一定会理解这样的变量是何种意思,但我们不难发现这样的问题:太长了!长到难以使用了!所以说,长度问题也是变量名的一个重要问题;如何对变量名的长度和完整性进行取舍,这是我们亟需掌握的能力。

上述论断中,我们认识到一个优秀的变量名可以使人“一眼就可以看出这是在干什么”,也就是说给予人最最直观的体验。所以说,一些变量名往往以动词开头,如:double checkTotal(User user){return 0.00;};但是一些诸如double CHECK(User user){return 0.00}double checks(User user){return 0.00}double havemoney(){}是不合常识与规范的。

这里,我们写一些好的变量名命名(驼峰命名法)。

// 关于速度
double trainVelocity = 310.25; // 高铁运行时速(km/h)
double velocityInMph = ; //
// 关于日期
Date currentDate = ;
// 一些行号
int lines;
int linesPerPage; // 每一页的行数

一个小结:我们的首要认识——变量名命名十分重要,乃至直接决定着我们代码的质量、性能;甚至如果我们的变量命名是有问题的,那么我们的项目到最后总是难以重构与维护。可谓说问题之大了。

我们不妨看看一些著名的项目如Linux的源码,向大师级别的人物学习。

二、更为恰当地命名#

我们肯定会有这样的疑问:使用像英语这样的语言,我们所要表达一个相同的意思常常会有不同的表述(比如说:表示钱💴,可能有人表示为double wallet = 100.00,而有些人表示为诸如 money balance等其他名称)。所以说,这种命名方式是否为规范或恰当呢?或者说我们是否有更好的命名方式呢?而当我们面对上述这样不同单词表达相同意思的情况,又该如何选择呢?

这里引入这样的”暴论“——一个好的名字应有2个意思1. 表达了什么(如:double balance; //表达的就是(用户/账户的)余额);2. 单词的立意(上述balance具有多个意思:平衡、保持平横、抵消……),单词的立意本质上说,它就是与前面的类型等因素相称,不造成歧义即仅表现出一种明确的意思。当一个变量名具备这两种性质,那么就会知道它所要表达的本意。

注意:关于变量,我们所要表达的东西一定不能是怎样的;如果是,那么问题出现,因为变量根本不是“怎样的”,而是表达一个”什么“

// 日常生活用语
studentData;
// input计算机界的学术语==》是更凸显IT界特指的变量
input_stu_data;
inputRec;
double sum;
// sum的意思?虽然名词词性上是金额总数;但实际上它是属于一种计算机术语还是其他的呢?我们的立意并不清晰
// 假设这个sum变量定义在财务报告系统,那么这个sum是什么?是求和函数还是要干什么?所以会产生歧义,会引起混淆
// 因此为了准确表达总额的含义,我们不妨可以这样定义:double calcValue;这样就会很清晰的知道这是一个值、一个计算总值

所以,我们还是回到上述的2个意思:1. 表达了什么2. 单词的立意。单词有各种各样的意思,在学术界它是怎样?它是否会有歧义?这是我们所要在乎与考虑的。

三、讲究长度的变量#

大家都知道像unsigned int the_max_country_number_of_the_olympic_team = 20;这样的变量名长度一定是有问题的。我们参考以下论文:Debugging effort estimation using software metrics和这个网站IFSQ—Poor Choice of Name的概述

Research Findings: The effort required to debug a program is minimized when variables had names averaging 10 to 16 characters long.

实际情况,在国内的企业命名长度要求大多为:9-15、10-16或8-20,还有些是8-16个。我们平常选取最大范围8-20的长度,可以说是问题不大。

这里,我们还可以参阅这篇文章博客Data Scientists Your Variable Names Are Awful Heres How To Fix Them的论述

于是,我们对上述极长的代码修改为numTeamMembers

注意,变量名往往和其所处的作用域来进一步补充完备意思,所以这里虽不呈现奥林匹克之意,但它应该仅作用于奥林匹克的命名空间之下。这是我们之后要谈的。

四、变量作用域与长度及规范#

for语句为例

// 变量作用域
// 函数(OOP 方法) 类
for(int i = length - 1;i >= 0;i --)
{
for(int j = 0;j < i;j ++)
{
}
}
// 我们会发现i和k的作用域或者说适用范围只在for语句中,这时候准确说来并无问题。
// 这时变量范围被局限住了

因此,我们会发现,变量名命名在什么地方会决定变量名该如何命名,函数(OOP 方法)、类、作用域都会决定你如何去命名变量

这里,我们或可以参阅这本书Software psychology: Human factors in computer and information systems

结果简要概述:特别短的名字(<8)我们常定义为局部变量,在for循环内可能会更短;它的作用域可能会决定它的长和短:当一个变量名越短,可能它的作用域就越小,甚至小到i,k这样的单字符。

但一些防御性编程会可能刻意绕开这些短的变量名。

变量名可能一样,我们会使用命名空间等所处的域不同来进行划分以区分变量

// 1. wallet
package com.goolgle.user;
// mysql sql引入要正确
public class Wallet {
}
// 2. wallet
package com.goolgle.dog;
public class Wallet {
}

更为学术的说,我们称作这为:划分全局命名空间

namespace User {
// Wallet
}
namespace Dog {
// Wallet
}

对于一些不支持上述划分全局命名空间的操作的语言如:C语言。我们可以:

design_Emp
dev_Emp

而对于可以使用packageJava语言,则更为简便:

package com.goolgle.design;
// mysql sql引入要正确
public class Employee {
}
package com.goolgle.dev;
public class Employee {
}

五、细化:关于变量计数词#

我们首先要明确:所要讨论的计数词是什么——这个计数不是循环中的ijk,而是我们经常所用的计数,如:总共的人数、总分数和平均数、最大及最小值等各种各样的东西。我们在设计这些涉及到计算的意思的变量名,我们该怎样比较确恰地命名,这是此段所要探讨的。

结论:常进行一种约束:名词提前-计数词放后

六、细化:对立词选择建议#

在计算机术语中,常有一些有意思的词,他们总是对立的,然后这些对立的词常相匹配组成一些完整的变量。

七、细化:常量、宏与指针#

建议直接参考伟大的项目linux的源码。

#define NUM_FIVE 5 // × 表示具体数字错误也就是说不能出现FIVE 可以改为数组的容量
// C++的常量:Google常声明常量以k开头
// constant
const int kDaysInYear = 100;
// 题外话:匈牙利命名法
int *pSize;

这只是一个约定

八、细化:循环计数器i,j,k#

#include <iostream>
int main(void)
{
for(int i = 0;i < totalEmp.count;i++)
{
data[i] = j;
}
}

从编程艺术来考虑,循环当中使用i,j,k是否规范?实际情况是允许的(前提是必须定义在循环里面,即作用域的界定范围在循环中,不会污染到其他东西)。例:JavaScript这门语言若定义为全局,它就会造成变量的污染

但是,如果i定义在循环之外,这么写是存在问题的,因为这样的i很可能被循环之后的代码运用到,那此时这个i是什么数据?它是垃圾数据,它并没有得到有效的管理。

如果我们的i不仅在循环内用到,还在其外用到,那么它就不能定义为i,而应定义为一个更具体的名称

还有一种情况

需要指明:项目工程的开发与维护不可能仅一个人搞,团队协作是常态,因此好的变量命名会带给其他人对你代码直观的理解,别人才更易接手这样的项目。

九、细化:枚举命名的讲究#

给人的感觉与常量相似,因为也是大写。

#include <stdio.h>
int main(void)
{
enum AlternateurlTableErrors {
OK = 0,
OUT_OF_MEMORY = 1,
MALFORMED_INPUT = 2
};
return 0
}

也有些语言、企业会规定加前缀等东西。

十、细化:临时变量的讲究#

The Art of Naming the Variable Names
https://blog.chaos-ljc.top/posts/variable-naming-art/
作者
Chaos
发布于
2025-04-29
许可协议
CC BY-NC-SA 4.0
评论