COMMA
到BRACKET_OPEN
的所有内容。想知道这是否必要;我读了一篇“文章”,它暗示将单字符文字转换为常量可能会有所帮助。因此,我对此表示怀疑。使用常量的主要吸引力在于,当需要更改时,它们可以最大程度地减少维护。但是,什么时候开始使用不同于','的符号来表示逗号呢?
我看到使用常量而不是文字的唯一原因是使代码更具可读性。但是,例如
city + CharacterClass.COMMA + state
真的比city + ',' + state
更具可读性吗?对我而言,弊大于利,主要是因为您介绍了另一个类和另一个导入。而且我相信尽可能减少代码。所以,我想知道这里的普遍共识是什么。
#1 楼
重言式:
很清楚,如果您阅读问题的第一句话
,则该问题与诸如
消除魔术数字,充其量是关于可怕的,无意识的愚蠢一致性。该答案针对的是什么
常识告诉您
const char UPPER_CASE_A = 'A';
或const char A = 'A'
除了给您的系统增加维护和复杂性之外,什么都没有。 const char STATUS_CODE.ARRIVED = 'A'
是另一种情况。常量应该表示在运行时不可变的事物,但将来可能需要在编译时进行修改。
const char A =
何时能正确等于A
以外的其他值?如果您在Java代码中看到
public static final char COLON = ':'
,请找出编写该代码的人并破坏键盘。如果COLON
的表示形式从:
发生变化,您将遇到维护的噩梦。混淆:
将某人更改为
COLON = '-'
会发生什么,因为他们在哪里使用它, -
到处都是?您是否要编写基本针对每个assertThat(':' == COLON)
引用都说const
的单元测试,以确保它们不会被更改? 如果只是有人让他们在更改测试时修正测试?
如果有人实际上认为
public static final String EMPTY_STRING = "";
是有用和有益的,那么您只需限定他们的知识,并在其他所有内容上都忽略它们。具有命名版本的每个可打印字符都表明,无论执行此操作的人是谁,都没有资格在不受监督的情况下编写代码。
内聚力:
它也人为地降低了内聚力,因为它使事物脱离了使用它们并与之相关的事物。
在计算机编程中,内聚性是指模块中
元素的程度永远在一起。因此,凝聚力可以衡量
内部功能之间的关系强度。给定的模块。例如,在高度内聚的系统中,功能紧密相关。
耦合:
它还将许多不相关的类耦合在一起,因为它们都结束了
紧密耦合是指一组类高度依赖于另一个
。当一个类承担太多的责任时,或者一个问题分散到多个类而不是拥有自己的类时,就会出现这种情况。
一个更好的名称,例如
DELIMITER = ','
,您仍然会遇到相同的问题,因为该名称是通用名称,不包含语义。重新分配该值仅比搜索和替换文字','
没有更多帮助进行影响分析。因为有些代码使用它并需要,
,而另一些代码使用但现在需要;
?仍然必须手动查看每次使用并进行更改。在野外:
我最近重构了一个18岁的
1,000,000+ LOC
应用程序。它具有类似public static final COMMA = SPACE + "," + SPACE;
的内容。这绝对比仅在需要的地方内联" , "
更好。 如果您想证明可读性,则需要学习如何将IDE配置为显示
whitespace
字符,以便您可以看到它们或其他内容,这只是将熵引入系统的极其懒惰的原因。 br /> 它还多次定义了
,
,并在多个包和类中多次拼写了单词COMMA
。与所有变体的引用在代码中混合在一起。尝试修复某些问题而不破坏完全无关的东西简直就是一场噩梦。与字母相同,存在多个
UPPER_CASE_A
,A
,UPPER_A
,A_UPPER
,大多数时间等于A
但在某些情况下不是。对于几乎每个字符,但不是所有字符。 从编辑历史来看,似乎没有一个在18年中曾被编辑或更改过,因为现在应该是显而易见的原因是它将破坏太多无法追踪的内容,因此您有新的变量名称指向同一事物,出于相同的原因,这些变量永远都不会更改。
在任何理智的现实中,您都不能认为这种做法没有做任何事情,而是从最大熵开始的。 br />
我将所有这些混乱因素进行了重构,并内联了所有的重言式,新的大学员工的工作效率更高,因为他们不必通过
const
参考文献实际指向的多个间接层次进行搜寻,因为它们在它们的名称与所包含的内容之间是不可靠的。评论
也许您应该添加一个反例:const char DELIMITER =':'实际上是有用的。
–贝尔吉
16年7月6日在19:03
我会提出几个论点,认为EMPTY_STRING是有益的。 (1)与找到“”的所有用法相比,我可以更容易地在文件中找到EMPTY_STRING的所有用法。 (2)当我看到EMPTY_STRING时,我非常清楚地知道开发人员打算将该字符串为空,并且以后提供该字符串不是错误的编辑或占位符。现在,您声称通过我提出此论点,您可以限定我的知识,并永远永远无视我。那么,您如何鉴定我的知识呢?您是否打算永远忽略我的建议?两种方式我都没问题。
–埃里克·利珀特
16年7月6日在22:32
@immibis:我们可以停止将这些事情视为对管理变更有用。他们是常数。他们没有改变。认为它们在人类搜索和理解代码语义的上下文中很有用。知道某物是一个键值对定界符比知道它是一个冒号有用得多。那是关于程序所关注的语义域而不是其语法的事实。
–埃里克·利珀特
16年7月6日在23:14
@EricLippert:我在这里看到了其他人的观点,他们指出const提供的唯一保证是它不会在运行时(编译后)更改,尽管我确实同意您的观点, const比将其用作变更管理工具更为重要。就是说,我当然可以想象一个常量EARLIEST_OS_SUPPORTED,它不仅在语义上是一致的,而且随着程序的发展和旧文件的删除将随着时间的推移而变化。
–罗伯特·哈维(Robert Harvey)
16年7月6日在23:23
@DanielJour:所以这是EMPTY_STRING的第三个参数;精心设计的IDE将浮出水面,这些工具使我可以象征性地而非语法上地对待该实体。将其概括为第四个参数:位于IDE下方的代码分析工具库可允许在符号级别进行高级的代码正确性程序分析。希望利用比40年前实际编写的工具更高级的工具的开发人员,只需对自己的习惯进行一些更改,即可获得高级工具的收益。
–埃里克·利珀特
16年7月7日在19:23
#2 楼
使用常量的主要吸引力在于,当需要更改时,常量可以最大程度地减少维护。
绝对不是。这根本不是使用常量的原因,因为常量在定义上不会更改。如果常量曾经发生变化,那么它不是常量吗?
使用常量的吸引力与变更管理没有任何关系,而与使程序适合于编写,理解和编写程序无关。由人维护。如果我想知道程序中使用冒号作为URL分隔符的所有地方,那么如果我有定义常量URLSeparator的准则,就可以很容易地知道这一点,并且如果必须使用grep可以完全不知道这一点。
:
,并获取代码中的每个单独位置,其中:
用于指示基类,?:
运算符或任何其他内容。 我完全不同意其他答案,这些答案指出这是浪费时间。命名常量为程序增添了意义,人类和机器都可以使用这些语义来更深入地理解程序并更有效地维护程序。
这里的诀窍不是避免常量,而是用它们的语义属性而不是句法属性来命名它们。该常数用于什么?除非程序的业务领域是印刷术,英语分析等,否则请不要称之为
Comma
。称它为ListSeparator
或诸如此类,以使事物的语义清晰。 评论
虽然我同意您在此所说的精神,但您的第二/第三句话并不是很正确。常量可以在文件的版本之间改变。实际上,我编写的大多数程序都有一个名为MY_VER的常量,它包含程序的当前版本号,然后可以在程序的其余部分中使用它,而不是像“ 5.03.427.0038”这样的魔术字符串。正如您所说,附加的好处是它提供了语义信息。
– Monty Harder
16年7月6日在19:50
公平地说,常量的要点是它在初始化后在运行时不会更改,而不是在编译之间不会更改。从编译器的角度来看,关键是编译器可以假设程序无法对其进行修改;在重新编译时是否允许程序员对其进行修改不会改变其常量性。在某些情况下,软件可能会通过将const volatile T *指针解引用到预定地址来从硬件获取只读值。虽然程序无法更改,但硬件可以更改。
–贾斯汀时间-恢复莫妮卡
16年7月6日在20:01
@MontyHarder:好点。我的意见是基于这样一个事实,即我通常使用一种语言来区分常数(必须永远不变)和可以分配一次的变量(可以随版本而改变,运行到运行等)之间的区别。常量和变量是不同的东西;一个保持不变,一个随着时间变化。
–埃里克·利珀特
16年7月6日在20:04
@SteveCox:我同意; C / C ++表征“ const”的方式很奇怪并且用途有限。我想要的常量属性是它们的值不会更改,不是在某些函数中不能更改它们,而在其他函数中则不能更改它们。
–埃里克·利珀特
2016年7月6日在22:27
“这根本不是使用常量的原因,因为常量在定义上不会更改。如果常量曾经更改,那么它不是常量,是吗?”在编译时更改常量(显然不是在运行时)是完全正常的。这就是为什么首先要使它们成为带有明显标签的“事物”的原因。当然,OP的常量是垃圾,但是请考虑类似const VERSION ='3.1.2'或const KEYSIZE = 1024之类的东西。
– AnoE
16年7月7日在9:14
#3 楼
不,那是愚蠢的。不一定是愚蠢的是出于本地化的原因将类似的东西拖入命名标签中。例如,千位分隔符在美国(1,000,000)是逗号,但在其他语言环境中不是逗号。将其放入命名标签(带有适当的非逗号名称)中,可使程序员忽略/抽象这些细节。
但是由于“不可思议的字符串不好”而使之成为常数仅是一种习惯。
评论
本地化通常比仅字符串常量更复杂。例如,某些语言要在所有列表项之间使用列表定界符,而另一些语言则要在最后一项之前排除定界符。因此,通常不需要局部常量,而是局部规则。
– Vlad
16年7月7日在8:51
实际上,千位定界符不一定是其他地区(中国/日本)中的千位定界符。固定位数后甚至没有设置(印度)。哦,取决于它是1000分隔符还是1000000分隔符(墨西哥),可能会有不同的分隔符。但是,与在某些语言环境中不使用ASCII数字0-9相比,这没有什么问题(Farsi)。 ux.stackexchange.com/questions/23667/…
–彼得
16年7月7日在9:43
@Vlad本地化要比这复杂得多,但是,千位分隔符是人们公认的众所周知的示例。
–user22815
16年7月7日在15:27
这取决于本地化策略...您是否更改程序中的所有常量以进行翻译?还是应该从文件(或其他数据存储)中读取值,使其有效地成为运行时变量?
–PaŭloEbermann
16年7月9日在20:03
那么,这对于一个常量根本没有用。该程序将需要针对区域设置进行重新编译,这是很糟糕的做法。它们应该是从定义文件加载的变量,并根据需要进行查找。并非我不同意这一点(我对答案投了赞成票),但我会在此问题上持更严格的立场。
–user236808
16年7月11日在19:45
#4 楼
有一些字符可能是模棱两可的,或用于几种不同的目的。例如,我们将'-'
用作连字符,减号或破折号。您可以单独命名为:static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '-';
static const wchar_t EM_DASH = '-';
以后,您可以选择将代码重新定义为以下内容来修改代码以消除歧义:
static const wchar_t HYPHEN = '-';
static const wchar_t MINUS = '\u2122';
static const wchar_t EM_DASH = '\u2014';
这可能就是为什么要考虑为某些单个字符定义常量的原因。但是,以这种方式模棱两可的字符数很少。最多看来,您只会为那些人这么做。我还认为,您可以等到实际需要区分歧义字符后再按这种方式分解代码。
由于印刷约定可能会因语言和地区而异,因此可能最好从翻译表中加载此类歧义的标点符号。
评论
对我来说,这是可能会创建字符常量的唯一有效原因
– F.P
16年7月7日在8:03
将-用作破折号是很容易引起误解的……对于大多数字体来说,简而言之就是很多。 (它甚至比破折号还短。)
–PaŭloEbermann
16年7月9日在20:04
好的,不是最好的例子。我从字符串而不是wchar_ts开始,并使用标准的手稿约定“-”作为破折号。但是最初的示例使用的是单个字符,因此我转而保持对这个问题的忠诚。有些人键入-连字符,尤其是在使用固定间距字体时。
–阿德里安·麦卡锡(Adrian McCarthy)
16年7月11日在21:15
@PaŭloEbermann不,传统上,破折号是字体的'm'字符的宽度,而破折号是'n'字符的宽度。
–迪兹利
16年7月12日在13:48
@Dizzley是的,连字符宽度
–PaŭloEbermann
16年7月12日在15:01
#5 楼
常量必须添加含义。将COMMA定义为逗号不会添加含义,因为我们知道逗号是逗号。相反,我们破坏了含义,因为现在COMMA可能实际上不再是逗号。
如果您出于目的使用逗号,并且想要使用命名常量,请在目的之后对其进行命名。示例:
city + CharacterClass.COMMA + state
=不好city + CITY_STATE_DELIMITER + state
=很好使用函数进行格式化
我个人更喜欢
FormatCityState(city, state)
,并且不在乎该函数的主体看起来如何,只要它简短且通过测试用例即可。评论
啊,但是逗号并不总是相同的逗号。我可以定义COMMA ='\ u0559'或'\ u060C'等(请参见Unicode),甚至以后将其转换为变量并从配置文件中读取。这样,它仍然具有相同的含义,但只是不同的值。那个怎么样。
–李斯特先生
16年7月9日在15:48
@MrLister:YAGNI。如果您有此需求:太好了!您有一个好的解决方案。但是,如果您不这样做,请-不要使代码混乱,因为也许您有一天可能会这样做。同样,根据我的经验,如果您尝试在代码库中引入没有任何功能的抽象,那么人们就不会在保持一致性方面做得很好。因此,即使您确实出于使用一些其他代码点的方式定义COMMA的目的,在具有足够大小和年龄的程序中也是如此,以至于选择很重要,您仍可能会发现该常量并未在应有的位置使用过曾经(相反,可能也被不适当地使用)。
–Eamon Nerbonne
16年7月11日在20:50
#6 楼
常数COMMA优于','
或","
的想法很容易被揭穿。当然,在某些情况下这是有道理的,例如,使final String QUOTE = "\"";
在没有所有斜杠的情况下大大节省了可读性,但是除非使用诸如\
,'
和"
之类的语言控制字符,否则我认为它们没有什么用处。使用
final String COMMA = ","
不仅格式不好,而且很危险!当有人想要将分隔符从","
更改为";"
时,他们可能会将常量文件更改为COMMA = ";"
,因为这样做的速度更快,并且可以正常工作。除了,您知道,现在使用COMMA的所有其他东西也都是分号,包括发送给外部使用者的东西。因此它通过了所有测试(因为所有编组和解组代码也都使用COMMA),但外部测试将失败。给它们起有用的名字是有用的。是的,有时多个常量将具有相同的内容但名称不同。例如
final String LIST_SEPARATOR = ","
。 因此,您的问题是“单个char常量比文字常量好吗?”的答案肯定是不,不是。但是比这两个都更好的是一个狭窄范围的变量名,它明确说明了它的用途。当然,您将在这些额外的引用上花费一些额外的字节(假设它们可能不会在您身上编译出来),但是在长期维护中(这是应用程序大部分成本的来源)值得花时间。
评论
取决于目标平台,如何有条件地将DISP_APOSTROPHE定义为ASCII 0x27或Unicode单右引号字符(这是一个更适合印刷形式的撇号)?
–超级猫
16年7月6日在21:21
实际上,QUOTE示例也证明了它是一个坏主意,因为您将其分配给通常/通常称为DOUBLE QUOTE的对象,而QUOTE则包含SINGLE_QUOTE,其更正确地称为APOSTROPHE。
–user7519
16年7月6日在21:38
@JarrodRoberson我个人认为引号并不意味着单引号-但这是消除歧义的另一个好理由!
– corsiKa
16年7月6日在21:59
由于另一个原因,我不喜欢QUOTE示例-它使读取使用它构造的字符串更加困难“您好,我的名字是“ + QUOTE +” My Name“ + QUOTE,这是一个琐碎的示例,但看起来仍然很糟糕。哦,可以,当然也可以使用替换标记代替串联,“您好,我的名字是%sMy Name%s”。format(QUOTE,QUOTE)可能更糟。但是,嘿,让我们尝试索引令牌“你好,我的名字是{0}我的名字{0}”。format(QUOTE)ugh,没有那么好。任何带有引号的非平凡字符串都会更糟。
– VLAZ
16年7月8日在18:18
@corsiKa-我将使用转义的实际报价。如果我错过了转义,我使用的IDE将立即抱怨。代码很可能也不会编译。这很容易发现。进行“我的名字是” + QUOTE +“我的名字” + QUOTE时犯错误的难易程度实际上,我在上面的评论中写了3次相同的错误。你能发现吗?如果需要一点时间,那么之后就是缺少的空间。您格式化字符串吗?在这种情况下,要替换的带有多个标记的字符串将变得更加糟糕。我该如何使用它以使其更具可读性?
– VLAZ
16年7月8日在18:29
#7 楼
我已经完成了一些编写词法分析器和解析器的工作,并使用整数常量表示终端。为了简单起见,单字符终端碰巧以ASCII码作为其数字值,但是该代码本来可以完全是别的东西。因此,我有一个T_COMMA,它被分配了ASCII码“'”作为其常量值。但是,非终端也有常量,这些常量被分配为ASCII集以上的整数。通过查看诸如yacc或bison之类的解析器生成器,或使用这些工具编写的解析器,我得到的印象基本上是每个人的操作方式。所以,与其他人一样,我认为这毫无意义。定义常量是为了在整个代码中使用常量而不是文字来表达的目的,我确实认为在某些极端情况下(例如解析器),您可能会遇到充满常量的代码,例如您所描述的。注意,在解析器的情况下,常量不仅仅代表字符常量。它们表示可能恰好是字符文字的实体。
我可以想到其他一些孤立的情况,在这些情况下使用常量而不是相应的文字可能是有意义的。例如,您可以将NEWLINE定义为unix框上的文字“ \ n”,但如果是在Windows或mac框上,则将其定义为“ \ r \ n”或“ \ n \ r”。解析表示表格数据的文件也是如此;您可以定义FIELDSEPARATOR和RECORDSEPARATOR常量。在这些情况下,您实际上是在定义一个常量,以表示可以发挥某种功能的字符。不过,如果您是新手程序员,也许您会将字段分隔符命名为COMMA,而没有意识到应该将其命名为FIELDSEPARATOR,到您意识到的时候,该代码将投入生产,而您将继续下一个工作。项目,因此名称错误的常量将保留在代码中,以供他人稍后查找并摇头。
最后,您描述的做法在某些情况下可能是有意义的,在这种情况下,您编写代码来处理以特定字符编码(例如iso-8859-1)编码的数据,但希望以后会更改编码。当然,在这种情况下,使用本地化或编码和解码库来处理它会更有意义,但是如果由于某种原因您不能使用此类库来为您处理编码问题,则只使用常量必须重新定义一个文件,而不是在源代码中乱七八糟的硬编码字面量,这可能是一种方法。
关于链接到的文章:我认为它不会尝试为用常量替换字符文字提供理由。我认为它试图说明一种使用接口将常量提取到代码库其他部分的方法。用于说明此问题的示例常量选择得很糟糕,但我认为它们没有任何关系。
评论
我认为它试图说明一种使用接口将常量提取到代码库其他部分的方法。这是更糟糕的反模式,并且紧密耦合且内聚力也很低,也没有充分的理由这样做。
–user7519
16年7月6日在21:26
#8 楼
除了这里所有好的答案之外,我还想补充一下,好的编程是关于提供适当的抽象,这些抽象可以由您本人甚至其他人构建,而不必一遍又一遍地重复相同的代码。好的抽象一方面使代码易于使用,另一方面又易于维护。
我完全同意
DELIMITER=':'
本身并不是一个很好的抽象,并且仅比COLON=':'
好(因为后者完全贫困)。 涉及字符串和分隔符的良好抽象将包括一种方法,该方法首先将一个或多个单独的内容项目打包到字符串中,然后从打包的字符串中解压缩它们,然后再告诉您要做什么。定界符是。这样的抽象将被捆绑为一个概念,在大多数语言中都是一个类。例如,为了使它的使用实际上是自我记录的,您可以搜索使用该类的所有位置,并对每种使用某种抽象的情况下程序员对打包字符串格式的意图有信心。
一旦提供了这样的抽象,它将很容易使用,而无需咨询
DELIMITER
或COLON
的值是什么,并且更改实现细节通常将限于实现。因此,简而言之,这些常量实际上应该是隐藏在适当抽象中的实现细节。使用常量的主要吸引力在于,在需要更改时,它们可以最小化维护。
好的抽象通常是由几个相关功能组成的,可以更好地减少维护。首先,他们清楚地将提供者与消费者分开。其次,它们隐藏了实现细节,而是提供直接有用的功能。第三,它们在何时何地使用它们的高级文档。
#9 楼
我曾经看到有效使用这样的常量的一次是匹配现有的API或文档。我已经看到使用诸如COMMA
之类的符号,因为某个特定的软件直接连接到了解析器,该解析器使用COMMA
作为抽象语法树中的标记。我还看到它曾经与正式规范匹配。在正式规范中,有时会看到诸如COMMA
之类的符号,而不是','
,因为它们希望尽可能清晰。在两种情况下,使用诸如
COMMA
之类的命名符号有助于使原本不相交的产品。该值通常会超过过于冗长的符号的代价。#10 楼
观察到您正在尝试列出一个列表。因此,将其重构为:
String makeList(String[] items)
换句话说,将逻辑而不是数据分解出来。
语言在表示列表的方式上可能有所不同,但是逗号始终是逗号(这是重言式)。因此,如果语言发生变化,那么更改逗号字符将无济于事-但这会有所帮助。
#11 楼
如果这是您的开发人员作为应用程序的一部分编写的类,那么几乎可以肯定这是一个坏主意。正如其他人已经指出的那样,定义常量(例如SEPARATOR = ','
)是有意义的,您可以在其中更改值,而该常量仍然有意义,但其名称仅描述其值的常量要少得多。在至少两种情况下,有必要声明其名称准确描述其内容的常量,并且在没有适当更改常量名称的情况下不能更改值:
数学或物理常量,例如
PI = 3.14159
。在这里,常量的作用是充当助记符,因为符号名称PI
比其表示的值短得多并且可读性强。解析器中的符号或键盘上的键的详尽列表。列出具有大多数或所有Unicode字符的常量甚至可能是有意义的,这就是您的情况所在的地方。有些字符(例如
A
)很明显,并且可以清晰识别。但是,您可以轻松区分А
和A
吗?第一个是西里尔字母А,而第二个是拉丁字母A。它们是不同的字母,由不同的Unicode代码点表示,即使在图形上它们几乎相同。我宁愿在代码中使用常量CYRILLIC_CAPITAL_A
和LATIN_CAPITAL_A
而不是两个看起来几乎完全相同的字符。当然,如果您只知道使用不包含西里尔字母的ASCII字符,那么这毫无意义。同样:我每天都使用拉丁字母,因此,如果我正在编写需要中文字符的程序,我可能更喜欢使用常量而不是插入我不理解的字符。对于每天使用汉字的人来说,汉字可能是显而易见的,但拉丁字母可能更易于表示为命名常量。因此,如您所见,它取决于上下文。不过,库可能包含所有字符的符号常量,因为作者无法事先知道该库将如何使用,以及哪些字符可能需要常量以提高特定应用程序的可读性。但是,这种情况通常是由系统类或专用库处理的,除非您正在处理一些非常特殊的项目,否则在应用程序开发人员编写的代码中很少出现这种情况。
#12 楼
也许。单个字符常量相对难以区分。因此,很容易错过添加句点而不是逗号的事实
city + '.' + state
而使用
city + Const.PERIOD + state
根据您的国际化和全球化环境,ASCII撇号和Windows-1252打开和关闭撇号(或ASCII双引号和Windows-1252打开和关闭)之间的区别
现在,大概地,如果错误地加上句号而不是逗号是一个重要的功能问题,您将拥有一个自动化测试那会发现错字。如果您的软件正在生成CSV文件,那么我希望您的测试套件会很快发现您在城市和州之间有一段时期。如果您的软件应该为具有各种国际化配置的客户端运行,则假设您的测试套件将在每种环境中运行,并且如果您打算使用单引号,那么如果您使用Microsoft公开报价,则该测试套件将开始使用。
我可以想象一个项目,选择更多冗长的代码可以避免这些问题,这更有意义,尤其是当您有没有完整测试套件的较旧代码时,即使我在绿色领域开发项目中可能不会这样编码。而且,为每个标点符号添加一个常量,而不只是为您的特定应用中可能存在问题的标点添加一个常量,可能会造成严重的后果。
评论
当某些白痴将Const.PERIOD更改为等于〜时会发生什么?重命名命名的字符是没有道理的,它只是增加了维护和复杂性,而现代编程环境中并没有这些。您是否要编写一套基本上说assert(Const.PERIOD =='。')的单元测试?
–user7519
16年7月6日在17:54
@JarrodRoberson-肯定会的。但是,如果有人添加了看起来几乎完全像逗号而不是实际逗号的Unicode常量,您将遇到同样的麻烦。就像我说的那样,这不是我在新建项目中要做的事情。但是,如果您的旧代码库带有参差不齐的测试套件,并且您在逗号/句号或撇号/ Microsoft讨厌的撇号问题上跳了几次,则创建一些常量并告诉人们使用它们可能是一种合理的方法无需花费一年的时间编写测试代码就可以使代码更好。
–贾斯汀·凯夫(Justin Cave)
16年7月6日在17:58
您的旧示例很糟糕,我刚刚重构了18年以上的1,000,000+ LOC代码库。它多次定义了每个这样的可打印字符,甚至具有不同的冲突名称。很多时候实际上设置了名为COMMA的东西= SPACE +“,” + SPACE。是的,一些白痴有一个SPACE常数。我将它们全部重构了,代码更加清晰易读,大学录用人员更能够追踪和修复它们,而无需进行6级间接查找来确定实际设置的内容。
–user7519
16年7月6日在18:02
#13 楼
单字符常量比文字常量好吗?
这里有很多合并。让我看看是否可以将它们分开。
常量提供:
语义
在开发期间进行更改
间接
>
只使用一个字符名只会影响语义。名称应作为注释并在上下文中清晰可用。它应该表达含义,而不是价值。如果可以用一个字符完成所有操作。如果不能,请不要。
在开发过程中,文字和常量都可能会改变。这就是出现幻数问题的原因。字符串也可以是幻数。
如果存在语义,并且由于两者都是常量,则常量是否比文字具有更大的价值就取决于间接寻址。
间接可以解决任何问题,而不是解决很多间接问题。
间接可以解决幻数问题,因为它使您可以在一个地方决定一个想法的价值。从语义上说,要使该名称有价值,必须使该名称明确。名称应与想法有关,而不是价值。
间接性可能过高。有些人更喜欢搜索和替换文字以进行更改。只要42显然是生命的意义并且不与42(钼的原子序数)混合在一起就可以了。
您可以根据单个字母做出有用的区分,这很大程度上取决于上下文。但是我不会养成习惯。
评论
语义是关键。如果和“ A”的语义比简单地成为“ A”多,那么将相同的语义绑定到相同的“引用”是值得的。是否为常数都没有关系。我完全同意。
–oopexpert
16年7月13日在17:57
#14 楼
作为多数派观点的哲学对立面,我必须指出,我们当中有些人欣赏这位朴实的19世纪法国农民程序员,并且回想起他单调,永恒的清醒,他对一切事物的愚蠢而明智的看法。 ,他对真理的巨大满足仅仅是因为它们是真实的。 “把一切都弄乱了!”特恩布尔对自己喊道:“如果他在庇护中,外面就不会有人。”G.K.切斯特顿,《球与十字架》
欣赏真理没有错,陈述真理也没有错,尤其是当与计算机聊天时。
如果你说谎到计算机上,它会为您带来帮助。
Perry Farrar-马里兰州日耳曼敦(来自More Programming Pearls)
但是,在大多数情况下,我同意那些认为哑。我还太年轻,还没学会编程FORTRAN,但是听说可以重新定义
'A' = 'Q'
并提出各种奇妙的密码。您没有这样做。除了之前提到的i18n问题(不是重新定义字形“ COMMA”,而是真正地重新定义DECIMAL_POINT的字形)。构建法国的胡萝卜引号或英国的单引号来传达对人类的意义是关于事物的事情,而这些真正应该是变量,而不是常量。常量将是
AMERICAN_COMMA := ','
和comma := AMERICAN_COMMA
,并且,如果我使用构建器模式来构造SQL查询,那么我比其他任何事情都更希望看到
sb.append("insert into ")
.append(table_name)
.append(" values ")
.append(" ( ")
.append(val_1)
.append(",")
.append(val_2)
.append(" ); ")
,但是如果要添加常量,它将是
INSERT_VALUES_START = " ( "
INSERT_VALUES_END = " ) "
INSERT_VALUES_SEPARATOR = " , "
QUERY_TERMINATOR = ";"
sb.append("insert into ")
.append(table_name)
.append(" values ")
.append(INSERT_VALUES_START)
.append(val_1)
.append(INSERT_VALUES_SEPARATOR)
.append(val_2)
.append(INSERT_VALUES_END)
.append(QUERY_TERMINATOR)
但是,如果您曾经看过其他任何程序(或键入),则可能会注意到一些有趣的怪癖。并非我们所有人都是出色的打字员。我们中的很多人都迟到了编程,或者是使用苏维埃键盘(键在您的键盘上输入的)长大的,我们喜欢剪切和粘贴单个字母,而不是尝试在键盘上查找它们和/或依靠自动完成功能。
没有什么可以自动为您完成字符串的操作,因此,如果我可以通过按'con',alt空格,下,下,下,下,输入,输入报价并按'con',alt空格,下,向下,进入。我可能只是这样做。
关于字符串文字的另一件事要记住的是它们的编译方式。至少在Delphi中,(这是我一直迷恋于堆栈的唯一语言),您将把文字直接弹出到每个函数的堆栈中。因此,大量的文字=大量的函数开销;为了解决这个问题,在function_A中的“,”与在function_B中的“,”不是相同的内存。要解决这个问题,可以横向构建和链接一个“资源字符串”,这就是他们做i18n事情的方式(杀死两只鸟,只有一个灌木丛。)在Python中,所有的字符串文字都是对象,使用
utils.constants.COMMA.join(["some","happy","array","strings"])
看起来似乎不错,但是对于在此页面上重复一遍的问题并不是一个好主意。#15 楼
但是什么时候我们要开始使用不同于','的符号来表示逗号?
用于本地化。
英语-在讲语言的国家/地区,将小数部分的全部和小数部分分开的符号是“。”,我们称其为“小数点”。在许多其他国家/地区中,该符号为“,”,在本地语言中通常称为“逗号”的等价物。同样,英语国家/地区使用“,”将三位数的组以大数字分隔(例如1,000,000表示一百万),而使用逗号作为小数点的国家/地区则使用点(1.000.000)。 >
因此,在进行全球化的情况下,有必要使DECIMAL_POINT和COMMA常量。
评论
但是,COMMA和DECIMAL_POINT并不是实体的正确名称(这可能就是为什么您被否决的原因)。
–凯尔·斯特兰德(Kyle Strand)
16年7月11日在14:28
您需要编译特定的本地化版本。文字常量不适合这种情况;该用例将需要定义文件并在其中进行查找(可能涉及常量,但是查找常量,而不是常量字符)。
–user236808
16年7月11日在19:52
评论
密切相关:programmers.stackexchange.com/questions/221034/…嗯...对于不同的地区可能有用,也许吗?例如,某些语言使用guillements(角引号,«和»)作为引号,而不是英语的标准“(或更好看的“和”)。除此之外,它听起来像是一组魔术字符,假设有两个实例的CharacterClass的名称为englishChars和frenchChars,很可能englishChars.LEFT_QUOTE可能是“,而frenchChars.LEFT_QUOTE可能是«。
逗号上有很多不同的变体:en.wikipedia.org/wiki/Comma#Comma_variants-也许这不是一个愚蠢的主意,尤其是如果您的源代码可以编码为utf-8。
在您的情况下,这就像调用变量“数字”一样。您的常数应称为DELIMITER。否则应为CITY_STATE =“ {0},{1}”
您链接的那篇文章非常糟糕。绝对不要将常量丢进这样的桶中。将它们放在具有上下文的类上:本质上,具有常量的类提供了使用常量的上下文。例如,Java的File.separator。该类告诉您分隔符的类型。具有名为Consts或Constants的类不会提供任何上下文,并使常量更难以正确使用。