序

books / 代码整洁之道 / 01-序

返回目录

乐嚼(Ga-Jol)是在丹麦最受欢迎的糖果品种之一,它浓郁的甘草味道,完美地弥补了此地潮湿且时常寒冷的天气。对于我们这些丹麦人,乐嚼的妙处还在于包装盒顶上印制的哲言慧语。今早我买了一包两件装,在其包装盒上发现这句丹麦谚语:

Æ rlighed i små ting er ikke nogen lille ting.

“小处诚实非小事。”这句话正好是我想在这里说的。以小见大。本书写到了一些价值殊胜的小主题。

神在细节之中,建筑师Ludwig mies van der Rohe(路德维希·密斯·范·德·罗)1如是说。这句话引发了有关软件开发、特别是敏捷软件开发中架构所处地位的若干争论。鲍勃(Bob)2和我时常发现自己沉湎于此类对话中。没错,Ludwig mies van der Rohe的确专注于效用和基于宏伟架构之上的永恒建筑形式。然而,他也为自己设计的每所房屋挑选每个门把手。为什么?因为小处见大。

就 TDD3话题展开目前仍在继续的“辩论”时,鲍勃和我认识到,我们均同意软件架构在开发中占据重要地位,但就其确切意义而言,我们之间还有分歧。然而,这种矛与盾孰利的讨论相对而言并不重要,因为在项目开始之时,我们理所当然应该让专业人士投入些许时间去思考及规划。20世纪90年代末期有关仅以测试和代码驱动设计的概念已一去不返。相对于任何宏伟愿景,对细节的关注甚至是更为关键的专业性基础。首先,开发者通过小型实践获得可用于大型实践的技能和信用度。其次,宏大建筑中最细小的部分,比如关不紧的门、有点儿没铺平的地板,甚至是凌乱的桌面,都会将整个大局的魅力毁灭殆尽。这就是整洁代码之所系。

架构只是软件开发用到的借喻之一,主要用在那种等同于建筑师交付毛坯房一般交付初始软件产品的场合。在Scrum和敏捷(Agile)的日子里,人们关注的是快速将产品推向市场。我们要求工厂全速运转、生产软件。这就是人类工厂:懂思考、会感受的编码人,他们由产品备忘或用户故事开始创造产品。来自制造业的借喻在这种场合大行其道。例如,Scrum 就从装配线式的日本汽车生产方式中获益良多。

即便是在汽车工业里,大量工作也并不在于生产而在于维护——或避免维护。对于软件而言,百分之八十或更多的工作量集中在我们美其名曰“维护”的事情上:其实就是修修补补。与其接受西方关于制造好软件的传统看法,不如将其看作建筑工业中的房屋修理工,或者汽车领域的汽修工。日本式管理对于这种事怎么说的呢?

大约在1951年,一种名为“全员生产维护”(Total Productive Maintenance,TPM)的质量保证手段在日本出现。它关注维护甚于关注生产。TPM的主要支柱之一是所谓的5S原则体系。5S是一套规程,用“规程”这个词,是为了读者便于理解。5S原则其实是精益(Lean)——西方视野中的一个时髦词,也是在软件领域渐领风骚的时髦词——的基石所在。正如鲍勃大叔(Uncle Bob)在前言中写到的,良好的软件实践遵循这些规程:专注、镇定和思考。这并非总只有关实作,有关推动工厂设备以最高速度运转。5S哲学包括以下概念:

整理(Seiri)4,或谓组织(想想英语中的sort(分类、排序)一词)。搞清楚事物之所在——通过恰当地命名之类的手段——至关重要。觉得命名标识无关紧要?读读后面的章节吧。

整顿(Seiton),或谓整齐(想想英文中的systematize(系统化)一词)。有句美国老话说:物皆有其位,而后物尽归其位(A place for everything, and everything in its place)。每段代码都该在你希望它所在的地方——如果不在那里,就需要重构了。

清楚(Seiso),或谓清洁(想想英文中的shine(锃亮)一词)。清理工作地的拉线、油污和边角废料。对于那种四处遗弃的带注释的代码及反映过往或期望的无注释代码,本书作者怎么说的来着?除之而后快。

清洁(Seiketsu),或谓标准化。有关如何保持工作地清洁的组内共识。本书有没有提到在开发组内使用一贯的代码风格和实践手段?这些标准从哪里来?读读看。

身美(Shitsuke)5,或谓纪律(自律)。在实践中贯彻规程,并时时体现于个人工作上,而且要乐于改进。

如果你接受挑战——没错,就是挑战,阅读并应用本书,你就会理解和赞赏上述最后一条。我们最终是在驶向一种负责任的专业精神之根源所在,这种专业性隶属于一个关注产品生命周期的专业领域。在我们遵循 TPM 来维护机动车和其他机械时,停机维护——等待缺陷显现出来——并不常见。我们更上一层楼:每天检查机械,在磨损机件停止工作之前就换掉它,或者按常例每1000英里(约1609.3km)就更换润滑油、防止磨损和开裂。对于代码,应无情地做重构。还可以更进一步,就像TPM运动在50多年前的创新:一开始就打造更易维护的机械。写出可读的代码,重要程度不亚于写出可执行的代码。1960年左右,围绕TPM引入的终极实践(ultimate practice),关注用全新机械替代旧机械。诚如Fred Brooks所言,我们或许应该每7年就重做一次软件的主要模块,清理缓慢陈腐的代码。也许我们该把重构周期从以年计缩短到以周、以天甚至以小时计。那便是细节所在了。

细节中自有天地,而在生活中应用此类手段时也有微言大义,就像我们一成不变地对那些源自日本的做法寄予厚望一般。这并非只是东方的生活观;英美民间也遍是这类警句。上引“整顿”(Seiton)二字就曾出现在某位俄亥俄州牧师的笔下,他把齐整看作是“荡涤种种罪恶之良方”。“清楚”(Seiso)又如何呢?整洁近乎虔诚(Cleanliness is next to godliness)。一张脏乱的桌子足以夺去一所丽宅的光彩。老话怎么说“身美”(Shitsuke)的?守小节者不亏大节(He who is faithful in little is faithful in much)。对于时时准备在恰当时机做重构,为未来的“大”决定夯实基础,而不是置诸脑后,有什么说法吗?及时一针省九针(A stitch in time saves nine)。早起的鸟儿有虫吃(The early bird catches the worm)。日事日毕(Don’t put off until tomorrow what you can do today)。在精益实践落入软件咨询师之手前,这就是其所谓“最后时机”的本义所在。摆正单项工作在整体中的位置呢?巨木生于树籽(Mighty oaks from little acorns grow)。如何在日常生活中做好简单的防备性工作呢?防病好过治病(An ounce of prevention is worth a pound of cure)。一天一苹果,医生远离我(An apple a day keeps the doctor away)。整洁代码以其对细节的关注,荣耀了深埋于我们现有、或曾有、或该有的壮丽文化之下的智慧根源。

即便是在宏伟的建筑作品中,我们也听到关注细节的回响。想想Ludwig mies van der Rohe的门把手吧。那正是整理(seiri)。认真对待每个变量名。你当用为自己第一个孩子命名般的谨慎来给变量命名。

正如每位房主所知,此类照料和修葺永无休止。建筑师Christopher Alexander——模式与模式语言之父——把每个设计动作看作是较小的局部修复动作。他认为,设计良好结构才是建筑师的本职所在,而更大的建筑形态则当留给模式及居住者搬进的家私来完成。设计始终在持续进行,不只是在新建一个房间时,也在我们重新粉刷墙面、更换旧地毯或者换厨房水槽时。大多数艺术门类也持类似主张。在寻找其他推崇细节的人时,我们发现,19世纪法国作家Gustav Flaubert(古斯塔夫·福楼拜)名列其中。法国诗人Paul Valery(保尔·瓦雷里)认为,每首诗歌都无写完之时,得持续重写,直至放弃为止。全心倾注于细节,屡见于追求卓越的行为之中。虽然这无甚新意,但阅读本书对读者仍是一种挑战,你要重拾久已弃置脑后的良好规则,自发自主,“响应改变”。

不幸的是,我们往往见不到人们把对细节的关注当作编程艺术的基础要件。我们过早地放弃了在代码上的工作,并不是因为它业已完成,而是因为我们的价值体系关注外在表现甚于关注要交付之物的本质。疏忽最终结出了恶果:坏东西一再出现。无论是在行业里还是学术领域,研究者都很重视代码的整洁问题。供职于贝尔软件生产研究实验室(Bell Labs Software Production Research)——没错,就是生产!——时,我们有些不太严密的发现,认为前后一致的缩进风格明显标志了较低的缺陷率。我们原指望将质量归因于架构、编程语言或者其他高级概念;我们的专业能力归功于对工具的掌握和各种高高在上的设计方法,至于那些安置于厂区的机器,那些编码者,他们居然通过简单地保持一致缩进风格创造了价值,这简直是一种侮辱。我在17年前就在书中写过,这种风格远不止是一种单纯的能力那么简单。日本式的世界观深知日常工作者的价值,而且,还深知工作者简单的日常行为所锻造的开发系统的价值。质量是上百万次全心投入的结果——而非仅归功于任何来自天堂的伟大方法。这些行为简单却不简陋,也不意味着简易。相反,它们是人力所能达的不仅伟大而且美丽的造物。忽略它们,就不成其为完整的人。

当然,我仍然提倡放宽思路,也推崇根植于深厚领域知识和软件可用性的各种架构手法的价值。但本书与此无关——至少,没有明显关系。本书精妙之处,其意义之深远,不该无人赏识。它正与Peter Sommerlad、Kevlin Henny及Giovanni Asproni等真正写代码的人现今所持的观念相吻合。他们鼓吹“代码即设计”和“简单代码”。我们要谨记,界面就是程序,而且其结构也极大地反映出程序结构,但也理应始终谦逊地承认设计存在于代码中,这至关紧要。制造上的返工导致成本上升,但重做设计却创造出价值。我们应当视代码为设计——作为过程而非终点的设计——这种高尚行为的漂亮体现。耦合与内聚的架构韵律在代码中脉动。Larry Constantine以代码的形式——而不是用UML那种高高在上的抽象概念——来描述耦合与内聚。Richard Garbriel在“Abstraction Descant”(抽象刍议)一文中告诉我们,抽象即恶。代码除恶,而整洁的代码则大抵是圣洁的。

回到我那个小小的乐嚼包装盒,我想要重点提一下,那句丹麦谚语不只是教我们重视小处,更教我们小处要诚实。这意味着对代码诚实、对同僚坦承代码现状,最重要的是在代码问题上不自欺。是否已尽全力“把露营地清理得比来时还干净”?签入代码前是否已做重构?这可不是皮毛小事,它正高卧于敏捷价值的正中位置。Scrum 有一种建议的实践,主张重构是“完成”(Done)概念的一部分。无论是架构还是代码都不强求完美,只求竭诚尽力而已。人孰无过,神亦容之(To err is human; to forgive, divine)。在Scrum中,我们使一切可见。我们晾出脏衣服。我们坦承代码状态,因为它永不完美。我们日渐成为完整的人,配得起神的眷顾,也越来越接近细节中的伟大之处。

在自己的专业领域中,我们亟需能得到的一切帮助。假使干净的地板能减少事故发生,假使归置到位的工具能提升生产力,我也会倾力做到。至于本书,在我看过的有关将精益原则应用于软件的印刷品中,是最具实用性的。那班求索者多年来并肩奋斗,不但是为求一己之进步,更将他们的知识通过和你手上正在做的事一般的工作贡献给这个行业。看过鲍勃大叔寄来的原稿之后,我发现,世界竟略有改善了。

对高瞻远瞩的练习业已结束,我要去清理自己的书桌了。

James O.Coplien于丹麦默尔鲁普


Footnotes

  1. 译注:20世纪中期著名现代建筑大师,秉承“少即是多”的建筑设计哲学,缔造了玻璃幕墙等现代建筑结构。 ↩

  2. 译注:本书主要作者Robert C. Martin绰号Uncle Bob,这里的“鲍勃”及后文的“鲍勃大叔”就是指Robert C. Martin。 ↩

  3. 译注:Test Driven Development,测试驱动开发。 ↩

  4. 译注:这些概念最初出现于日本,5个概念的日文罗马字拼音首字母正好都是S,所以这里也保留了日文罗马字拼音写法。中译本以日文汉字直接译出,读者留意,不可直接对应其中文意思。 ↩

  5. 译注:中文意为“素养、教养”。 ↩