命名:为什么在C++/Java中命名常量应该全部大写?

48

我知道对于C++和Java来说,有一个被广泛接受的命名规范,即常量应该全部大写,用下划线分隔单词。比如这样(Java示例):

public final static Color BACKGROUND_COLOR = Color.WHITE;
public final static Color TEXT_COLOR = Color.BLACK;

这种命名约定易于理解和遵循,但我问自己,为什么选择这种命名约定而不是普通的变量命名约定:

public final static Color backgroundColor = COLOR.WHITE;
public final static Color textColor = COLOR.BLACK;

似乎没有必要改变常量的外观。如果我们想给它们分配一个值,编译器会阻止这样做。事实上,如果以后将常量更改为适当的变量(例如,因为颜色变得可配置),则会出现问题。

那么为什么要将命名常量全部大写呢?是出于历史原因吗?


35
在C++中,将常量命名为全大写并不是一个好主意。ALL_UPPER_CASE是预处理器宏的约定。因此,您的常量可能会与预处理器符号冲突并被覆盖掉。 - Brian Neal
1
这可能最好作为社区维基来服务。 - lothar
15个回答

37

我认为这不是一个技术问题,而是一个心理问题。命名约定不是供编译器处理的(计算机实际上并不介意名称),而是为了使浏览代码的程序员尽可能获得更多信息,尽可能少的付出努力。

使用不同的命名约定明显告诉读者,你正在阅读的是在编译时被固定的东西,你不需要沿着代码跟踪确定值是如何到达那里的。


1
“尽可能少的付出努力,获得尽可能多的信息”:我同意这个观点。 结合使用“纯文本”作为编程媒介,这可能会导致大写约定。如果编辑器只能以不同的颜色显示常量,则不需要特殊情况。 现在,大多数编程工具都显示更多信息,因此我想命名约定将逐渐消失。 - xtofl
7
它真的必须在编译时固定吗?比如运行时常量,例如程序开始执行的时间?还有固定集合,虽然编译器无法理解但仍然是有效的常量。 - Jon Skeet
2
@Jon Skeet:这是一个很好的观点:如何处理边界。常量的定义是什么?在这里,你正在与你使用的语言作斗争。对我来说,它们应该是大写的,因为它们是常量……无论语言/编译器的限制,它们都是常量。 - David Rodríguez - dribeas
3
将枚举按其类型作用域划分,比全大写更清晰地表明了它的常量性质,因为它不仅显示其为常量,而且还显示了何种类型的常量。全大写通常用于语言外部的符号,但Java和C#没有预编译器。此外,全大写难以阅读且难看。 - Steven Sudit
这只是回答了“为什么常量需要不同的约定”的问题,而不是回答“为什么要采用这种特定的约定”的问题。毫无疑问,后者可能有一个答案,因为我们正在谈论两种具体的编程语言(即我们不需要一般化的答案)。 - Guildenstern

21

我认为在C++中,这是一种从使用预处理器定义常量值的日子延续下来的惯例。当时这样做是为了避免预处理器践踏源代码,因为C函数和变量名通常是混合大小写或小写。

从C++的角度来看,我会说把所有常量都大写是个坏主意。我曾经因此调试过多个构建问题 - 记住,C++预处理器对命名空间和名称范围一无所知,并且会很愉快地替换它认为适当的东西,尽管它是相当不恰当的。


10
这正是我想说的。在 C++ 中,使用全大写字母表示常量是一个反模式,因为预处理器可能会使用你没有预料到的某些宏来覆盖你的常量(例如来自供应商的 C 操作系统头文件)。 - Brian Neal
4
这可能就是为什么谷歌在它们的命名规范中使用 kConstantName 的原因。一个在某种程度上保留旧风格的替代方案是 k_CONSTANT_NAME。 - Emile Cormier

17

我可以想象在 C 语言的早期,人们会使用预处理器来以符号方式实现"常量":

typedef unsigned int Color;
#define BACKGROUND_COLOR 0xffffff

这样的“常量”只是装饰过的文字,因此它们的行为与变量并不完全相同。例如,您无法获取此类“常量”的地址:

Color *p = &BACKGROUND_COLOR; // Breaks!

因此,让它们“突出显示”是有意义的,因为它们真的不仅仅是“无法更改的变量”。


3
但是现在不是IDE的工作吗?让它们脱颖而出? - xtofl
2
即使在今天,也不是每个人都一直使用集成开发环境。我仍然花费相当大的一部分时间(约10%)在vi中。 - dagorym
7
不要忘记 #define 宏可能会导致令人讨厌的副作用。将它们全部大写可以为“危险!”提供视觉提示。 - Skizz
我非常建议您进行谷歌图片搜索“syntax on”(摩托车图片)。 - yeoman

17

如果我知道某个东西是一个常量,我可以多次引用它并且知道它不会改变。换句话说,我知道:

Color black = Colors.BLACK;
foo(black);
foo(black);

与以下代码等效:

foo(Colors.BLACK);
foo(Colors.BLACK);

有时候了解这点信息会很有用。就我个人而言,我更喜欢使用.NET的命名约定,即对于常量(和方法)使用Pascal case:

Foo(Colors.Black);
Foo(Colors.Black);

我不是很喜欢大声的命名方式...但我确实喜欢常量显然是常量。


4
问题是关于:为什么要使用不同的命名方案来表示常量?而不是关于为什么常量有用。 - xtofl
8
我的回答并没有讨论为什么恒定性很有用,而是讨论了为什么了解恒定性很有用。这就是命名的作用所在。 - Jon Skeet
4
我也更喜欢我的代码不要大喊大叫,因此倾向于使用帕斯卡命名法——它更易读!!!!!11 - yeoman
我认为@JonSkeet,任何负评都是因为你发布了一个不回答所提出问题的答案:“为什么在C++/Java中命名常量应该全部大写?” 你没有说明为什么它们应该全部大写。甚至展示了枚举类型作为替代方案,但并没有回答这个问题。 - Rodney S. Foley
1
@RodneyS.Foley:我不确定你为什么认为我在提到枚举 - 我根本没有提到枚举。但是我认为我回答了这个问题,通过说明能够区分常量和非常量的差别有何用处。 - Jon Skeet

16

不要仅仅因为常量曾经被定义为宏而使用全大写的字母。

这来自于 C++ 核心指南 (引用链接),总结了所有内容。


8
在C语言(然后是C++)中,使用预处理器指令#define定义的符号都是大写的,这是向开发人员发出的响亮信号,表明代码并不像看起来那样,并且不能将其视为正常符号。在K&R C中最初不存在常量(尽管后来从C++中引入了const),因此开发人员使用#define代替,因此采用了大写字母的方式。
由于某种原因,这种做法被扭曲为Java中的“常量必须是大写字母”,因此导致了当前错误的(在我看来)约定。

7

我认为大写常量是从C语言遗留下来的不好习惯。其背后的逻辑与在私有成员前使用下划线前缀相同。这些都是技术性的细节,已经通过Java关键字(如private)或常量的情况下static final表达出来了。


5
实际上,大多数C ++命名指南(包括ISO、Boost、Sutter&Stroustrup和Google)强烈反对使用全大写字母来命名常量。这是因为宏也使用全大写字母,它们可能会散布在标头文件中,潜在地造成奇怪的行为。人们仍然使用所有大写字母,因为他们从旧的C / K& R或旧的遗留代码中学到了。然而,在现代C++新代码中,您应该避免除宏以外的任何情况使用全大写字母。

我个人认为全大写字母存在的原因是,在非常老的机器上,使用数字键盘直接输入机器码。当汇编语言出现时,它只使用全大写字母,因为当时的键盘没有标准化,有些键盘受限,例如将相同的数字键盘用于像功能手机那样输入字母。这被延续到许多早期的语言中,如BASIC,其中一切都是大写字母。当实际终端可用并且键盘开始标准化时,人们开始使用混合大小写字母而没有保留全大写字母用于某些不太常见的情况,例如与函数和变量相比常量。

现在大多数C ++指南都同意使用“k”作为常量前缀,后跟下划线或CamelCase命名。我个人更喜欢kCameCase,因为它可以轻松区分变量,这些变量使用下划线命名。

const float kFixedRadius = 3.141;

3

基本上,早在人们热爱C语言时,C ++和Java要么是新的,要么尚未创建,人们使用全部大写字母来表示预处理器常量名称,以表明它们实际上并不是变量。

#define INT_CONST 4
#define STRING_CONST "Yello."
#define FLOAT_CONST 3.6122448

考虑到这是在C语言中定义真正常量的唯一方式(如果你知道如何,仍然可以更改const变量),因此像这样的预处理器常量只被视为常量,因此全大写名称的含义从预处理器常量转变为普通常量。这种做法随后在后来的语言中得以延续,成为了标准的“大写字母表示常量”的惯例。
然而,其他语言有自己的首选风格(例如,C#和.NET偏好PascalCase),因此如果有首选风格,最好使用该风格。

2

使用大写常量可以使长公式更易读,您不需要猜测哪个元素可以变化,哪个元素不能变化。这当然只是一种惯例,但是非常有帮助。


1
可以通过许多表示常量的方法来实现,因此并不唯一需要使用大写名称。其他方法也没有这样的强调。 - Max Waterman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接