(点击上方公众号,可快速关注)
来源: 伯乐在线
如有好文章投稿,请点击 → 这里了解详情
【导读】:代码注释的作用,不需要对程序员解释了。有时在查看他人代码,能看到一些令人不禁大笑的注释。比如:
或者:
// 写这段代码的时候,只有上帝和我知道它是干嘛的
// 现在只有上帝知道
最近在 Quora 上看到一个帖子,号召程序员分享自己见过最有趣的代码注释。看到了各种有趣的注释,打算分多篇摘编分享给大家。
1. Bill Poucher 的分享(他是一位计算机科学教授)
我见过的最佳注释是以 HTML 格式写在源代码里的,任何想要阅读的人都能看得见。我管它叫“Cerny效应”。
曾经有一位很有天赋的捷克研究生 Tomas Cerny,在 Baylor 大学 ICPC(国际大学生程序设计竞赛)技术研发部主任 Jeff Donahoo 博士的领导下,负责将另外一位很聪明的研究生的设计原型转换成实际产品。
有一天,Jeff 到我的办公室跟我说,在他们ICPC实验室,冷战的格局正在形成。因为有人在源代码的注释里写了一些话,冒犯到了其他人。(为了看看情况,)我就随他一起去找了Tomas。
Jeff去了以后就开门见山地问:“Tomas,你是不是在Joel的代码上加了注释,说他的代码是愚蠢(retarded)的?”Tomas倒是很坦白地说:“是的。”Jeff又问:“你凭什么这么写呢?”Tomas回答说:“因为(他的代码)确实愚蠢(retarded)啊!”
我就站在一边看着,Tomas一脸懵逼,Jeff强压怒火,场面真是大写的尴尬。接着,Tomas拿出了他的《捷克语-英语词典》,打开,上面写着,词义:“开发中(under developed):retarded”(译注:其实retarded这个词有两个意思,既有“弱智,愚蠢”的意思,也有项目未完成,正在开发中的意思,这也是造成这个误会的原因。)
是的,开发确实还没完成……后来,Tomas就把注释修改为了“建设中(Under construction)”。然后我和Jeff都对Tomas拓展英语能力的热情捧腹大笑。我至今不知道当年这个误会是不是真的解决了。
跟你们说,我和Jeff都很爱讲这个段子,后来每当我们把Tomas介绍给ICPC新成员的时候,就一定会讲这个段子。Tomas现在已经是布拉格捷克技术大学的计算机科学系教授了,他还是学校ICPC技术部的奠基人,也是我非常好的朋友。
Tomas不仅在Baylor大学获得了硕士学位,而且他在这里找到了他的伴侣,一位音乐家,同时也是奥运会级别的田径选手。当然,这是另外一个关于奥林匹克的爱情故事了。
ICPI-ACM国际大学生程序设计竞赛,由IBM赞助。
2. Anirudha Bose 的分享:
谢尔盖.布林(Google的联合创始人之一)在斯坦福大学念计算机科学博士学位的时候,他的简历里并不含任何”待遇要求“(Objective)的字眼。但当你去查看他的简历的HTML源代码的时候,你会看到(他在简历HTML源文件里明确写了“待遇要求”,只是用注释注掉了,在浏览器页面上不显示。):
(其“待遇要求“的内容是:办公室要大,挣钱要多,干活要少。如果能经常去奇妙的地方旅行而且还能给报销的话,那就更好了。)
3. Abhinav Upadhyay 的分享
/* You are not expected to understand this */
/* 我们并不指望你能看懂这段话 */
这段注释并不是我亲眼所见,但是它在网上传得很厉害。这段注释是出自于贝尔实验室的Unix系统第六发行版,并在《Lions’ Commentary on UNIX 6th Edition, with Source Code》这本书中标注出来的。
代码和标注的细节如下:
/*
* 切换到新进程栈,并设置其段寄存器
*/
retu(rp->p_addr);
sureg();
/*
* 如果新进程因为被换出而暂停,则设置其栈级别为last call,并传至sayu(u_ssay).
* 这样做的目的是确保aretu方法被调用后立即返回的值实质上是上一次调用sayu的方法的返回值。
*
* You are not expected to understand this.
* 我们并不指望你能看懂这段话
*/
if(rp->p_flag&SSWAP) {
rp->p_flag =& ~SSWAP;
aretu(u.u_ssav);
}
/*
* The value returned here has many subtle implications.
* See the newproc comments.
*/
return(1);
4. Kalpesh Singh 的分享:
我有个坏习惯,每当我看到做得不错的网站,我就回去控制台看它的源代码。我想很多前端工程师都喜欢这么干吧。
我订购了Box8服务,并在他们的console里看到了如下信息。(伙计们,他们居然在console/源代码里面打招聘广告。我对广告什么的早就受够了,你们就不能搞点儿新花样?)
你们可以看看Box8.in的console。
不过这样真的是挺有趣的。
还有一个比较有意思的注释是target.com编程游戏网站的源代码
可查看:Code With Target via The Geekiest Contact Form (BETA)
好好享受乐趣吧!
5. Liu Wei 的分享[译注:这明显是一位来自中国的工程师]:
我在一周前在社交网站上看到很多人在讨论这个网站,网站的源代码包含了这些注释。
有人说,这家公司应该加强对代码的审核机制。有人则怀疑这家公司可能没有足够的人力资源来做代码审核,因为至少需要两个程序员才能完成这项工作。
6. Edwin Romero 的分享:
我不确认有多少人熟悉站点内的Robots.txt这个文件。其实这个文件不是运行必要的代码,但是它声明了爬虫/搜索引擎能爬到/搜到站点的哪些内容。
我在Nike网站上发现的Robots.txt文件非常有意思,如下:
如果你读一下文件头部的内容,你就会发现它是这么写的:
“…just crawl it.”
这种写法和Nike品牌著名的广告标语“Just Do It”不谋而合。
**更新**
Nike最近修改了他们的robots文件,并在里面加入了一个有趣的图案:
感谢Chris Shepherd 告诉我这个消息!
7. Soham Bhowmik 的分享:
好吧,这个回答其实并不完全是关于注释,而是关于代码。
我的第一个项目,一个为印度非常流行的新闻频道做的iOS应用,要求在交付之前制定规则。这件事情已经过去很久了,大约6年左右。当时iOS的最新版本还只是3.2。无论公司什么时候把应用交付给客户,应用都会被设置在5天之后过期,然后用户就不得不回头来找我们解决应用的问题。
代码是用Objective-C写的:
BOOL appExpired =........some code....;
if(appExpired )
{
[ NSString hahahahhaha ]; //will purposely crash now, will not use exit(1)
//这里故意让程序崩溃,而不使用exit(1)
}
当然,如果现在还这么写代码编译器就会报错,但是当时编译器只会给出警告信息,然后程序在运行的时候会因为调用未定义的方法而崩溃。
8. Ray Mullins 的分享:
曾经用过IBM的VSAM系统(包括z/OS和z/VSE以及其后续版本)的人,都应该体验过这个系统的逗比特性。
我曾经在一家德国的软件公司任职,负责对一个事务处理监测程序进行技术运维和研发,这个监测程序是美国开发的,有一个针对VSAM文件的接口,那么当然程序就需要一个控制模块负责对文件进行存取操作。明显写这个控制模块的人那天过得不太如意,因为在控制模块获取通用错误方法地址的那段代码里,写着这样的注释:”VSAM又SB了(FUCKED UP AGAIN), 到这里来。“ 更有趣的是,这些控制模块的代码被正式印到操作手册上(包括带有FUCK的那段文字),所以在差不多20年的实践里,这个注释就这么被写在那里然后发给客户。然后直到某一天有个客户想对控制模块进行替换,然后才发现有这么个注释,然后才告诉我们。
接下来的这个不是注释,而是来自于我的实际工作。我们当时有一套内部标准和方法文档。我们的系统程序员需要为一个什么渣渣的4GL产品的延迟方法编写文档,并进行演示。他的文档草稿第一版草稿大概是这么写的:
IF TIMEDIFF >=5
SAY "THE SYSTEM IS FUCKED, PLEASE BEAR WITH US" //如果系统 SB了,请和我们一起忍受
SLEEP(10)
ENDIF
草稿写完了以后他就去忙东忙西,根本没时间搞文档,接着突然发现文档的提交期限就在晚上了。于是他就直接把草稿发给文档管理人员了,根本都没看。一周以后,上百份文档就这么被打印出来分发出去了。并且,内容就是他草稿上写的那些,一个字都没改。
9. Terry Lambert 的分享:
我最喜欢的注释有两个,都是Bill Paul写的。这家伙为FreeBSD做了大量的工作,现在受雇于Wind River System,听说这个公司最近要被Intel收购了。Bill是一个非常有才华的程序员,但是他对愚蠢的容忍度也出奇的低,并且他的幽默感也很不同寻常。
下面是我喜欢的第一条注释,这是从RelTek 8129/8139 PCI NIC 驱动程序里找到的。
/*
* The RealTek 8139 PCI NIC redefines the meaning of 'low end.'
RealTek 8139 PCI NIC重刷了low逼的下限
* 这可能是史上写得最烂的PCI以太网控制器驱动
* with the possible exception of the FEAST chip made by SMC.
* The 8139 supports bus-master DMA, but it has a terrible
* interface that nullifies any performance gains that
* bus-master DMA usually offers.
*
* For transmission, the chip offers a series of four TX
* descriptor registers. Each transmit frame must be in a
* contiguous buffer, aligned on a longword (32-bit) boundary.
* This means we almost always have to do mbuf copies in order
* to transmit a frame, except in the unlikely case where a)
* the packet fits into a single mbuf, and b) the packet is
* 32-bit aligned within the mbuf's data area. The presence of
* only four descriptor registers means that we can never have
* more than four packets queued for transmission at any one
* time.
*
* Reception is not much better. The driver has to allocate a
* single large buffer area (up to 64K in size) into which the
* chip will DMA received frames. Because we don't know where
* within this region received packets will begin or end, we
* have no choice but to copy data from the buffer area into
* mbufs in order to pass the packets up to the higher
* protocol levels.
*
* It's impossible given this rotten design to really achieve
要让这么烂的设计去达到100Mbps的速度简直就是天方夜谭
* decent performance at 100Mbps, unless you happen to have a
除非你有一台CPU强劲的电脑去驱动
* 400Mhz PII or some equally overmuscled CPU to drive it.
*
* On the bright side, the 8139 does have a built-in PHY,
* although rather than using an MDIO serial interface like
* most other NICs, the PHY registers are directly accessible
* through the 8139's register space. The 8139 supports
* autonegotiation, as well as a 64-bit multicast filter.
*
这绝对是一个很爽的注释。传说为了让 Bill 能把这段注释删掉/修订/修改/更新等等,厂家用了各种条件去诱惑他,但是他都拒绝了。
第二段注释是写在一个修改版的BSD许可证的“限制伤害”条款里的,Bill在他的代码里引用了这个许可证协议。其实它并没有对原先的协议做大的修改,所以很多人看到这个协议以后,一看跟模板差不多,然后就跳过了,几乎没什么人仔细去看整个文字。
IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES
怎么样,你没见过这条吧。其实很容易就看掉了。有趣的地方正好在这里:
「Bill Paul以及他头脑中的想法绝不会直接,间接,偶然,特殊,典型或实质性地造成任何损害。」
总之,这哥们儿是个天才。
10. Boris Zamoruev 的分享
我曾经做过一个高性能分布式键/值存储的项目。这是一个设计很精巧的软件,API非常简洁。如果你要获取一个数值,那么你就用命令:GETN(get, 数值)即可。如果你要存一个数值,那就用命令:PUTN(put, 数值)即可。其他的命令也很简单,比如MGETN(get multiple, 数值),MPUTN(put multiple, 数值),INCR(增量), MINCR(多个增量),(基本上命令都可以自解释)。
所有的命令都会被送到一个dispatcher函数去进行解析,辨明逻辑,然后去调用相应的处理函数。处理函数基本上也是自解释风格的,因此代码里面也不需要太多注释,例如:
int Server::handle_getn(…) {…}
int Server::handle_mgetn(…) {…}
不过有一天,有人让我review一下下面这段代码:
// In Soviet Russia, Putn handles you!
// 在前苏联,Putn 就会搞定你!【译注:注意,Putn 和普京的英文拼写(Putin)非常接近。普京曾经是苏联的克格勃。】
int Server::handle_putn(…) {
}
我当即就选择了通过,然后合并到代码库并且发布了。据我所知,现在这段代码还在代码库里。
11. Nikunj Madhogaria 的分享
//drunk, fix later
//喝大了,一会儿再改
Catch (Exception e) {
//who cares? // ← 这不翻译了,估计都能看懂吧
}
我最喜欢的一个注释是:
long long ago; /* in a galaxy far far away */
读者如果不明白什么意思,请看下图:
12. Sasha Krassovsky 的分享
曾经有一次, 我从学生交给我的代码里随便挑了一份来看,然后发现了这么一条注释:
/* Do NOT delete this comment */
/* 不要删除这段注释 */
当然,我就是要试一下如果把注释删除了到底会怎么样。所以我就删除了,然后重新编译。结果程序真的就不能运行了。然后我把注释重新加回去,结果又好了。
删掉注释以后会报错 LINK1000,根据链接器错误文档的说明,错误的原因直接就是:“未知错误;请参考文档或寻求技术支持。”
为什么这个注释不能去掉呢?我估计这个问题对我来说一直就是个谜。
13. Wojtek Swiatek 的分享
我看过一些数据分析的代码,然后就被下面的注释震惊了:
# 不要再用 anal 做变量名了[译注:写注释的人是想用 anal 这个缩写来表示analyze(分析),可是 anal 这个单词的意思是“肛门”]
# 我特么在哪都能看到 anal 这个词!
# 请不要再这么做了!
# 你们要用就用analyze,或者xbvvzr,要不然用什么其他的都可以。就是别写成 anal_insert 或者 anal_check了【译注:insert是插入的意思,check是检查的意思,其他的你们自行脑补吧】
14. Michael Dehmlow 的分享
我新入职了一个公司,然后发现了一段三周之前写的注释,这段注释是项目之前的研发团队写的,写的日期就是我来公司面试和正式入职的这段期间。
我有幸在原来负责这个项目的先生们被炒鱿鱼的前一天被派来参与这个项目。
/* 这坨代码写得像屎一样,写代码的SB做了很蠢的事情
* 他们让itvinserter.dll依赖egg_end470.dll。
* 然后又让egg_en470.dll依赖itinserter.dll. 简直是白痴!不过,
* 是有一个合理的办法能解决这个问题,而我正好打算做点儿深入研究去解决。
* 不过,真正唯一能解决问题的办法是,找到这个当初写代码的狗娘养的,
* 然后冲他的两腿之间狠狠踢上一脚。虽然这样解决不了问题,但是这样
* 能伸张正义。
*
*
*真TM是个SB
*
* *呵呵*
*
* The EEGEN470::TapeDeck is an abstract class for controlling tape
* decks....ah, fuck, I can't do it. I can't even fucking document the hack.
* Just figure out, you're a smart fellow.
*
*/
15. Ryan Jentzsch 的分享
好多年前我在一个公司工作,我现在都还保留着那时的磁盘,上面有我当时写的程序代码和我对前任CEO留下的注释。
/*
这个公司的CEO(也就是我的前任老板)告诉我可以随意写注释,而且我确实也该这么做。
我把前任CEO称为蘸屎(Dip Shit),简称DS.
DS觉得他自己是一个软件开发的天才。很遗憾对我来说(我是程序的维护者),我的
主要任务就是擦他没擦干净的屎。
DS是一个想一出是一出的开发者。就像Evel Khievel在他的代码做的一样,
大量使用GOTO语句,而且贸然直接从一个模块
跳到了另外一个模块的IF...THEN语言中间,况且这个模块
和第一个模块根本就没关系。
说到IF结构,DS真的很喜欢用。他根本就不知道还有
CASE或者SWITCH块这种东西。然后我就只能去当一个代码
考古学家,在深深的IF-ELSE嵌套层次(而且还是没有缩进的那种)中苦苦挖掘
indented) IF...THEN...ELSE logic blocks.
DS认为他自己很聪明,并且这在他给变量命名的时候就有体现:
global i=0;
global dateMyWife = 1;
datesAreAFruit = '12/12/98';
giveDatesToMyWife = datesAreAFruit + dateMyWife;
if (someStuid)
{
giveDatesToMyWife = false;
}
// Ryan. Why does this sometimes crash?
if (giveDatesToMyWife) goto :hotTub
// 好吧DS,因为你修改了giveDatesToMyWife数据类型
(不仅如此,你还把整型和字符串类型相加——编译器已经
警告你了)...总之在弱类型的语言里你获得了
脑残的能力,你时不时修改数据类型,把字符串改成布尔型,所以当
from a string to a Boolean, so that when the
if(giveDatesToMyWife) executes, when the variable is a string
if(giveDatesToMyWife) 运行时,里面的变量是一个字符串,
程序肯定会崩溃——因为字符串不是一个
可逻辑判断的类型。还有,因为someStuid是全局的,所以
只有你拥有超能力,才能知道这些全局变量在哪里定义,
或者是在哪里被修改过。
DS只会用全局变量,而不会用局部变量。引用他的原话:“
我用局部变量,或者私有成员变量的时候,我的程序老是报错,
说变量未找到什么的。所以我干脆就把所有东西都搞成全局的好了。”
我还有更多的例子,其实如果你也被这种天马行空的代码虐过的话,你就
能体会我是什么感受了。
*/
觉得本文有意思?请转发分享给更多人
关注「程序员的那些事」,编程更有趣