偶尔,我会遇到一段优秀的代码,并想花点时间来认可这个事实,哪怕只是为了在年度体检前保持低血压。
第一段吸引我眼球的优秀代码是 Linux 中的 clocksource.h。Linux 通过一组像俄罗斯套娃一样组合在一起的结构与硬件时钟(例如主板上的晶振)进行交互。
最核心的是 cyclecounter,这是一个非常简单的抽象,它从底层硬件返回当前计数器。cyclecounter 不知道当前时间、时区或任何其他信息;它只知道在被询问时硬件中寄存器的值。cyclecounter 有两个状态,有助于将周期转换为纳秒,但仅此而已。下一个套娃是 timecounter。timecounter 包含一个 cyclecounter,并将抽象级别提升到以纳秒为单位测量的单调递增时间级别。在这些结构之上还有其他结构,最终使系统有足够的抽象来了解一天中的时间等等。
那么,这段代码有什么了不起的呢?嗯,有两点:第一,它结构良好,因为它是由可以协作的小组件构建的,而不会互相越界或违反分层结构;第二,它的编写和文档风格清晰明了,以至于我第一次阅读就能够理解它的工作原理。
cyclecounter 的注释和结构让您体会到我为什么如此乐于阅读这段代码
/**我想您能明白我为什么喜欢这段代码,但以防万一您不明白,让我更具体地说明一下。代码布局良好,缩进整齐,变量简短但可读。没有 Bouncy Caps 或 very_long_names_that_read_like_sentences。注释足够长,不仅描述了结构的用途,还描述了它的使用方式,甚至提到了如果多个线程需要同时访问这些结构之一时需要做什么。如果所有代码都像这样有良好的文档就好了!您可以在以下网址在线阅读更多此代码:
http://lxr.free-electrons.com/source/include/linux/clocksource.h.
我的另一个优秀代码示例需要更多解释,所以我将把它留到以后的专栏中。毕竟,我不想在同一期中浪费所有的镇静效果。
亲爱的 KV,
在过去一年中,我们公司在生产网络中购买和部署了一套监控系统后,我们在制造商的系统软件中遇到了第一个错误。在我们报告错误后,制造商要求我们将系统升级到最新版本。结果证明,升级过程要求我们将设备重置为出厂默认设置,从而丢失每个系统上的所有配置信息,并需要在升级后由人员重新输入所有配置数据。
起初,我们认为这可能只是这次特定升级所必需的,因为它跨越了一个主要版本,但事实证明,每次我们升级这些系统上的软件时,都必须重新输入配置数据。我想我们应该在购买系统之前问这个问题,但这从来没有发生在我们身上,有人会出售一个声称可以充当设备但无法在现场轻松升级的盒子。我们组里的另一个人建议我们直接退回盒子并要求退款,但令人沮丧的是,这些是我们找到的用于网络监控的最佳系统。
升级困境
亲爱的困境,
看来你认为的产品——也就是说,由关心客户的人们精心组装的一组组件——实际上只是一堆零件的集合,在正常情况下它们可以勉强正常工作。不幸的是,考虑到他们的系统 1.0 版本之后会发生什么的公司数量非常少。
我很幸运——或者也许我应该说,在过去 10 年左右与我打交道的销售人员很幸运——没有遇到太多以您描述的方式运行的系统。制造商会要求用户或系统管理员在升级后重新输入已保存数据的想法是愚蠢的、荒谬的,以及我的编辑们不允许在这份出版物中出现的其他一堆词语。
即使在设计最糟糕的产品中——而且我已经用过很多——通常也会有一些 perl 脚本,它可以获取旧的配置数据并将其转换为对最新版本基本有效的东西。
事实上,多年前我参与了一个网络交换机项目,系统团队(负责在盒子上安装合理的操作系统和应用程序)做的第一件事就是想出一种现场升级系统的方法。任何配置过交换机或路由器的人都知道,在升级时你不会直接丢弃配置。
可悲的是,正确地做到这一点并不难。现在大多数嵌入式系统都使用精简的 Unix 系统,例如 Linux 或 BSD,所有这些系统都将其配置存储在众所周知的文件中。诚然,这不是存储配置数据的最佳方式,因为它往往有点分散,但编写一个可以处理版本之间的差异并协调它们的脚本并不难。在 FreeBSD 上有 etcupdate,Linux 有 etc-update 和 dispatchconf。在一个设计合理的系统中,配置很可能存储在一个简单的数据库或 XML 文件中,这两者都可以通过相当简单的脚本进行现场升级。
这些问题区分了设备(可以部署和维护,几乎不需要人工干预)和系统(必须不断摆弄才能使其正常运行)。可悲的事实是,许多程序员和工程师并不看重设备,更倾向于认为他们的用户应该“坚强起来”,并花时间弥补原始设计师的考虑不周。
我仍然记得我见过的第一批全数字立体声系统之一。它是围绕 Sun 工作站设计的,成本约为 15,000 美元。从您看到控件的那一刻起,就很明显,人们真正想要从音响系统中获得什么,几乎没有或根本没有考虑过。大多数人对立体声系统的期望是高质量的声音,并且只需最少地按按钮即可获得他们想要的东西。我看到的系统呈现的是大量的按钮操作,但音质与我从放大器和 CD 播放器中获得的音质大致相同。如果说用户界面很糟糕,那与系统性能相比根本不算什么。在我最终走出商店之前,盒子崩溃了三次。我从那次经历中学到的一件事是,系统和产品不是同一回事。
系统是为了完成一项工作而组合在一起的组件集合。产品是一个系统,它的设计和构建旨在使执行工作的过程对用户来说流畅自然。我当然可以拼凑软件在计算机上翻录、存储和播放我的 CD;这是一个系统,而 iPhone 是一个产品。当我升级我的手机时,我不会重新输入我的数据。如果我这样做,产品将在第一个版本中消亡。更可能的是,如果史蒂夫·乔布斯被告知升级路径需要重新输入数据,他会让人掉脑袋。考虑到现代设备的复杂性——让我们面对现实,您的电视可能有一个以太网插孔——很明显,人们已经考虑并解决了这个问题。
真正的问题在于设计这些设备的人。不知何故,设备将与一群计算机(例如,在托管中)一起使用的事实使得实施者可以接受使他们的盒子看起来更像开源桌面,这将由经验丰富的 IT 人员或用户自己摆弄。这是一种真正需要停止的做法,即使只是因为我不希望每个人都像我一样秃顶。我的头发不是掉下来的,是我自己拔掉的!
KV
喜欢它,讨厌它?请告诉我们
KODE VICIOUS,凡人称之为乔治·V·内维尔-尼尔,出于乐趣和利益从事网络和操作系统代码工作。他还教授与编程相关的各种主题的课程。他感兴趣的领域是代码探查、操作系统和重写你的糟糕代码(好吧,也许不是最后一个)。他获得了马萨诸塞州波士顿东北大学的计算机科学学士学位,并且是 、Usenix 协会和 IEEE 的成员。他是一位狂热的自行车爱好者和旅行家,目前居住在纽约市。
© 2012 1542-7730/12/0400 $10.00
最初发表于 Queue 第 10 卷,第 4 期——
在 数字图书馆 中评论本文