acm-header
登录

ACM通信

观点

Kode Vicious:美丽的代码是存在的,如果你知道去哪里看


亲爱的KV

我一直在看你的咆哮队列已经有一段时间了,我忍不住问,你有什么密码吗像什么?你看起来总是那么消极;我真的很想知道你是否真的相信编程的世界是一个如此丑陋的地方,或者是否有某个地方,有一些快乐的地方,你去了却从不告诉你的读者。

快乐的程序员

亲爱的快乐先生

虽然我尽量不反对你把我的文章称为“咆哮”,但我不得不说,我对你的问题感到惊讶。KV是一个快乐、开朗、外向的人,他不仅有一个“快乐的地方”,而且走到哪里都带在身边,和身边的人分享快乐和笑声,给小孩子们送糖果。(咳嗽)

现在我的大脑已经漂白了,我可以更诚实地回答了。是的,事实上,有很好的系统,我也见过很好的代码,有时甚至是很棒的代码。我现在就来介绍一段这样的好代码。不幸的是,它需要一些背景知识来解释什么是代码,但请继续听我讲。也许你可以先去你的“快乐之地”放松一下。

我最近的一个项目是在FreeBSD上扩展对硬件性能监视计数器(hwpmc)的支持,FreeBSD是我工作的操作系统。顾名思义,hwpmc是在硬件中实现的,在这种情况下,硬件意味着在CPU上。我不知道你是否读过CPU或芯片文档,但在我们的行业中,几乎没有比这更难写或读起来更不愉快的文档了。这个主题就像月球表面一样干燥,这已经够糟糕的了,更糟糕的是,编写此类文档的人要么不了解技术,要么是糟糕的作者,通常这两者是致命的结合。从这个基础开始,典型的软件工程师编写的代码在某种程度上反映了规范,当有毒土壤中生长的东西本身变成有毒的时候,代码常常和规范一样令人困惑。

hwpmc是什么?它是驻留在CPU上的一组计数器,可以记录工程师感兴趣的各种类型的事件。如果您想知道您的代码是否在冲击L2缓存,或者编译器是否生成了破坏管道的次优代码,那么您应该使用这个系统。尽管这些东西看起来很深奥,但如果您正在从事高性能计算,它们是极其重要的。正如你所想象的,这样的计数器是特定于CPU的,但不只是根据公司,英特尔与AMD不同:甚至CPU的模型都与当前的计数器有关,以及它们的访问方式。

Intel当前手册中关于hwpmc的部分,Intel®64和IA-32架构软件开发人员手册3B卷:系统编程指南,第2部分包括249页:81页描述各种芯片上的各种系统,168页涵盖你可以在芯片上使用的所有计数器。这是一本不错的小说,但当然没有有趣的故事情节。向英特尔的技术作者致敬,因为这不是我读过的最差的芯片手册,但我仍然宁愿读其他的东西。当我读完所有这些背景材料后,我有点担心打开文件时会看到什么。

但我并不太担心,因为我认识亲自编写代码的程序员。他是一个非常勤奋的工程师,不仅是一个优秀的程序员,而且还能解释他做了什么和为什么。当我告诉他我将尝试在他编写的系统中添加更多的芯片模型时,他给我发了一封1300字的电子邮件,详细介绍了如何在系统中添加对新芯片和计数器的支持。

这个软件有什么了不起的?好吧,让我们看看代码的几个片段。总是在代码之前阅读头文件是很重要的,因为头文件是定义结构的地方。如果结构没有在头文件中定义,那么从一开始就注定要失败。看看我打开的第一个头文件的顶部,我们看到的代码片段显示在图1.为什么这些行对我来说表示代码质量高?是大写吗?间距?使用标签?不,当然不是!而是有版本号的事实。工程师清楚地知道,他的软件不仅会被他自己修改,还会被其他人修改,并且他通过设置主要版本号、次要版本号和补丁版本号专门考虑到了这一点。简单的?是的。 Found often? No.

下面的一组行——记住,这只是我打开的第一个文件——也具有指导意义,如图所示图2.KV的老读者可能认为是这条评论让我高兴,但他们错了。它是把常量翻译成可理解的文本名称。在开发一款软件时,没有什么比不得不记住另一个愚蠢的,通常是十六进制的常量更令人沮丧的了。我对那些能够记得从0x100开始编号并且0x105恰巧很重要的程序员没有印象。谁在乎呢?我不喜欢。我想要的是使用描述性名称的代码。还要注意,代码中的常量不是很长,但足够长,可以很容易地在代码中知道我们谈论的是哪个芯片。

图3显示了头文件中的另一个很好的示例。我使用这个代码片段是为了避免包含整个文件。在这里,依赖于机器的结构与独立于机器的结构是分开的。很明显,您希望将特定于特定类型的CPU或设备的数据位与独立的数据分隔开来,但在实践中似乎很明显的事情很少做。工程师考虑哪些位应该放在哪里,这一事实表明代码的质量很高。阅读每个元素的描述性注释,并指出在哪里可以找到适当的类型,例如pmd_cputype来自enum pmc_cputtype

这个文件的最后一个注释。注意,程序员正在用C语言编写对象。操作系统内核和其他底层代码位仍然是用C语言编写的,尽管现在有很多例子表明人们试图在这方面有不同的想法(比如苹果的Mac OS X驱动程序是用c++编写的),但底层代码将继续用C语言编写。更重要的是在可能的情况下做正确的事情。这里列出的结构是一个对象。它有数据和方法来对其进行操作。到目前为止,BSD内核已经使用这种方法20多年了,这是其他人应该学习和记住的一课。

这些只是这段代码的几个例子,但在一个又一个文件中,我发现了同样的质量水平,同样漂亮的代码。如果您真的有兴趣看看好的代码是什么样子的,那么我建议您自己阅读代码。如果有一个地方是“快乐的地方”,那么它就是这样的代码。

KV

注:包括FreeBSD在内的许多操作系统内核的完整代码交叉引用可以在http://fxr.watson.org/上找到,您要查找的代码可以在http://fxr.watson.org/fxr/source/dev/hwpmc/上找到。

在codespelunking网站上可以找到一组类似的交叉引用:http://www.codespelunking.org/freebsd-current/htags/。

亲爱的KV

在他的书中神话中的人月,弗雷德里克·p·布鲁克斯(Frederick P. Brooks)以祖父般的耐心告诫我们计划建造一个原型,然后把它扔掉。反正你会的。

这一度导致了一种叫做原型设计(以前称为试错的编程方法)的流行,证明过少和过多都一样糟糕。

你对创建原型有什么看法,特别是关于原型需要有多忠实才能解决真正棘手的细节问题,而不是让营销部门获得截图,这样他们就可以展示东西了?

签署,
A,典型的工程师

亲爱的非典型

你说的“以前叫做试错”是什么意思?你是说这种时尚已经过时了吗?据我所知,它仍然存在,而且很好,尽管可能许多实践者实际上并不知道他们的智力出身。事实上,我怀疑大多数实践者都不会拼写知识分子出身。

唉,一条好建议往往被过分采纳,在一段时间内变成了口头禅。任何重复多次的东西似乎都会成为真理。布鲁克斯的建议,我相信你知道,是为了克服在计算机科学中太普遍的“必须完美”的咒语。在设计阶段你就能知道一切的想法是一种谬论,我认为这种谬论起源于数学家,他们是世界上最早的程序员。如果您每天都在研究纸上的符号,只是偶尔才需要将这些符号构建到工作系统中,那么当您的系统的美丽与真实硬件的丑陋现实相遇时,您很少会欣赏到会发生什么。

从这个起点出发,很容易看出50年代和60年代的程序员是如何希望把所有东西都先写下来的。问题是,一张纸并不能很好地代替计算机。纸张不会因为铜中电子的速度、电线的长度或磁鼓的速度(现在是磁盘,很快就会变成闪存)而产生奇怪的延迟。因此,在当时告诫人们只去建造该死的东西,不管它是什么,然后从原型中吸取教训并将其整合到真正的系统中是非常有意义的。

自从这个建议提出以来,计算机的速度不断提高,这使得人们可以在过去构建单个系统的相同时间内,构建更大、更快、当然也更多的原型。患原型炎的人简直就是胆小鬼。不划清界限是工程师或团队怯懦的表现。“这只是一个原型”经常被用作逃避系统设计中困难问题的借口。在某种程度上,这样的原型设计与布鲁克斯想要做的完全相反。原型的目的是找出困难的问题在哪里,一旦它们被识别出来,就有可能完成整个系统。这不是给营销部门一些漂亮的东西来展示潜在的客户——这是纸餐巾和大量威士忌的用途。


在设计阶段你就能知道一切的想法是一种谬论,我认为这种谬论起源于数学家,他们是世界上最早的程序员。


我的原型在哪里?这与我对分层或将系统分解成越来越小的物体的看法是一样的。你应该只构建必要数量的原型,以发现和解决你试图构建的任何东西所带来的困难问题。其他的一切都是盲目的。现在,不要误会我的意思,我和旁边的人一样喜欢凝视,也许更喜欢,但我在钻研我的迷幻收藏时所做的事,我向你保证,与编写软件无关。

KV

回到顶部

作者

乔治·v·内维尔·尼尔(kv@acm.org)是Neville-Neil咨询公司的所有者。他从事网络和操作系统代码方面的工作,教授各种与编程相关的课程,并鼓励您的评论、俏皮话和与他相关的代码片段通信列。

回到顶部

脚注

DOI: http://doi.acm.org/10.1145/1364782.1364791

回到顶部

数据

F1图1。显示版本号的头文件。

F2图2。将常量转换为描述性名称。

F3图3。与机器相关的结构与与机器无关的结构是分开的。

回到顶部


©2008 acm 0001-0782/08/0700 $5.00

允许为个人或课堂使用本作品的全部或部分制作数字或硬拷贝,但不得为盈利或商业利益而复制或分发,且副本在首页上附有本通知和完整的引用。以其他方式复制、重新发布、在服务器上发布或重新分发到列表,需要事先获得特定的许可和/或付费。

数字图书馆是由计算机协会出版的。版权所有©2008 ACM, Inc.


没有找到条目

Baidu
map