很多明星从艺之后都要起个艺名,最好能过目成诵的。比如施瓦辛格就曾经给自己起名叫做"斯壮
(Strong)"。这反映了命名中最困难的部分。命名中最困难的部分不是名字容易被忘记,而是名字与那个人的对应更难。凡是初高中背过政治题的同学可能都有同感,答案并不难背,关键这答案是哪道题的呢。
题外话。不少同学问我,你咋不整个笔名啥的呢。像"杨贵福"这样的名字,简直比最好的艺名还要好,能真正过目不忘,而且重名巨少,万万改不得。
1. 命名的意义所在
那么,我们为什么要为万物 (也包括万事)命名呢。命名使我们在讨论对象时更简洁,是一种重要的抽象方法。比如,提到一个地名,"我下午张守备修筑的城墙那开工啊"就很麻烦,如果简称为"张家口"就简单多了。类似的,石家庄、二道沟?
这也是为什么程序员要为变量命名的原因。不然,"我打算向内存地址8000写入一个值,恩,作为表达范围0至65535的一个整数42",这确实挺麻烦。于是,我们把这种特别常用的功能抽象出来,起个名字。"unsigned
int a=42;"。8000呢?因为不重要,所以屏蔽了,不让程序员看到,这样更易于集中注意力于真正的业务逻辑。
所以,当我们打算再次提到某个变量的时候,就需要为它命名;或者说,当我们意识到将要再次提到某个变量的时候,我们就应该命名它了。
2. 名字的变迁
使用名字的一个前提,是对话的大家对这个名字有共同的认识。即这个名字对应相同的概念的内涵和处延,不然也挺麻烦。
因为俺们计算机学科也是有历史的学科了,好几十年,诸侯纷争,所以也颇有些历史原因的名字了。比如到底啥是"实时"就有好几种观点,大家都说别人是错的。
人类历史也挺长的,所以类似的事也不少。比如希腊北面有个国家,叫马其顿。当年马其顿是个巨牛的主儿,打遍当时的"人类"所知的天下无敌手,而且没几年就完成了,只一代人的时间。可能有些同学对马其顿这个名字有点陌生,提一下它的领袖大家一定印象深刻,他们的头目名叫亚历山大。对,就是那个亚历山大。问题来了,直到今天,希腊仍然不承认北面这个叫"马其顿"的国家与历史上那个巨牛的"马其顿"有关系,而马其顿人民当然不这么看。是不是有同学想起了韩国?
亚历山大的另一个与名字有关的事。这位大哥当年曾经向波斯王大流士索要过亚洲的主权。注意,不是波斯的主权,而是亚洲的。索要什么东西,对话的另一方自然得是全权所有者。这就让人猜测,亚历山大心里的亚洲,可能就是到印度前的那么大块地方。西伯利亚、中国、甚至印度,可能在他的概念中根本不算亚洲的一部分。至少日本韩国东南亚什么的,可能都不存在吧。
但是时值今日,亚洲的概念大家估计都能背下来了。乌拉尔山-乌拉尔河-高加索山-里海-黑海-土耳其海峡,苏伊士运河,白令海峡。
程序代码在成长的过程中,也经常发生这样的事。最初以为某个变量、函数是干这个的,过了一段时间发现,其实它是干那个的。如果名字不变,引用它的时候就会觉得非常奇怪,为什么一个叫做
PaintProc 的函数,即不是消息响应函数,同时也 不是/不只是 用来画图的呢?
有的时候,我们嫌麻烦,就不改了,留给后人无穷的麻烦。
比如 c++ stl中有个 endl。看名字,它的含义再清楚不过了, end
line。但是有一次,刘同学还是王同学,调程序的时候发现,printf ("\n") 与 cout << endl
的行为很有些不同。有的同学看到这里可能皱眉头不以为然了,因为你可能看过这两段代码的运行行为,没啥不一样。它们二者相同的,是功能性需求部分,但是非功能性需求方面略有不同。有同学可能以为只是性能不同。不仅是这样。
手册说:"Additionally, for buffered streams, endl flushes the
buffer",参见[http://www.cplusplus.com/reference/iostream/manipulators/endl/]。而printf中的"\n"可没有flush缓冲区的作用。
这就导致刘或王同学发现,在某个时刻,上位机程序读设备时输出的东西不一样。因为printf那个还没有flush,看不到。
应对这种需要,"重构"中有一个专用于改名的方法。
3. 名字的意义
之所以要改名,因为名字除了唯一标识的作用以外,还带有别的意思。比如"杨贵福""霍去病"这样的名字,大家一看便知命名者的意图。
改过名字的施瓦辛格后来把名字又改回去了,据说是因为他认为如果真的牛了,观众自然会记住他的名字。我恶意的猜测,可能还有个理由,他的名字对于美国观众而言,似乎具有异国情调。
用不同的名字称呼同一个东西,还能标识出一个人的身份
(或者自我认同吧)。比如《中国好声音》中就有人把"小样"称为"demo",后来一期又改为"小样"了。再比如吊威亚,以及所有在汉语流中使用英文的家伙。他们要么是太习惯了,要么是在标明什么。
类似的表态包括这样的一些词,它们都在表明,我们不是可啥啥那么俗的东西:理念 (不是哲学) 、举措 (不是措施) 、BL (不是同性恋)
、波希米亚 (不是捷克或者吉普赛) 、披头士 (不是 甲壳虫)。
这很重要:) 要不然,韩国也不会把首都的中文译名改来改去,把日本海改名为东海。这些,都体现了命名者和名字使用者的意图。
所以,程序代码中的变量命名,是依据用途、意图、动机,其次其次其次才是依据 实现手段。
所以,printf 这名字中,print占了主要部分。f是format,也是实现的效果,而不是方法。类似的,puts估计是 put string。
回顾一下我们自己在程序代码中的变量名,多少有点向 int_a 靠拢。
使用什么名字,有时能表明你的立场,如下;有时,能表明你对学科或项目的的理解。比如,某个同学的项目可能这样命名,"android游戏开发",这一看就是重点在于练习android,或者注意开发平台上与众不同。老师就可能得出结论,这一项目的动机是提高同学自己,而不是解决一个他人的问题。
4. 名字空间
因为大家都起名字,名字就越来越多了。我们的词汇量都不大,而命名不允许重名,所以,如何命名就成了个难题。需着工程生成,代码里这样的名字越来越多:
list1, list2, list3... list_ok, list_real_ok。
这让我想起几件事来。一件是周老师前两天博客里提到的。暖房子改造的时候要求房顶不能有热水器,但是热水器的主人们拒绝临时拆掉,甚至拒绝承认那个热水器是自己的。后来周老师一家家跑,说尽好话,种种麻烦,总算都整好了。周老师很是感叹了一翻。关同学看了我转的周老师博客,第一天很奇,杨老师啥时候变这么温柔了呢,第二天一看,恩,果然,转的博客。
我会怎么处理。没有认领的,贴个条,24小时自己拆了。不然直接推楼下扔垃圾堆里。有人认领的,告诉他一个常识,楼顶是大家公用空间,他没有权利独占,24小时自己拆了,不然我拆。如果我住楼顶的话,我可以把楼顶也拆了。
类似的,在写程序代码中,全局变量要特别慎重使用。原因无他,那是大家的名字空间,你用了,别人就不能用了。而独占公众资源,必须经过所有人的同意,因为你剥夺了别人使用的权利。
zhumao同学提到,在大型一些的项目中,他看到专业C程序员的函数都会声明为static。为什么?因为这样就限制了这个函数名只在这一个文件中起作用。为什么要限制自己,给自己添麻烦呢?为了方便别人。或者说,我们没有权利限制别人的权利,名字空间是大家的。
再类似的,小区的绿地为什么不能种蔬菜。因为那是大家的地方,你不能假设大家看着你的黄瓜茄子土豆会心情愉快,尤其有时还有泥土和粪的清香。"你的"黄瓜茄子土豆长在"大家的"土地上,长出来以后随便摘着吃么?我猜有的同学可能会说,"随便啊,大家随便吃。"我想问,我可以不打招呼就吃么。如果那是大家的,为什么必须应该向你打招呼呢。
小资们把自己家阳台向外扩出半米的时候,我在他们的脸上看到了几十年前农民把自己家的篱笆向别人家推进一垅沟时的窃笑。
还有,以前在电影电视看到过跑步的老外常戴个耳机听音乐,我就想,这玩意不安全呐,有汽车在身后听不到。最近我看到了中国特色的版本,完全避免了这个问题。中国特色的MP3是有外放喇叭的,可以声闻二十余米,根本不需要把自己的耳朵包起来。使用者洋洋得意地放歌的时候忘了,空间是公共的,而不是他一个人的。我热切地盼望着这玩意人手一个,然后大家开始掐架,"你TM地小点声,我的听不到啦!"
--------------------
博客会手工同步到以下地址: