标题：程序员修炼之道:从小工到专家
图书信息
书名：程序员修炼之道：从小工到专家  作者：[美]Andrew Hunt   David Thomas  著  马维达 译
ISBN：978-7-121-12336-8
出版日期：2011年1月 
定价：55.00元
宣传语
传承大师智慧  领悟技术本真
经典名著  翻译良品  典藏不二之选
本书直接从编程的战壕出发，穿过现代软件开发日渐增多的专门化和技术问题，去考察核心的过程——按照需求，编写能工作、可维护、能让用户满意的代码。
作 者 简 介
Andy Hunt 是一位热切的木匠和音乐家，但奇怪的是，人们更需要作为顾问的他。他的工作领域包括电信、银行、金融服务、公共服务，以及一些更奇特的领域，比如医学成像、图形艺术、Internet服务。Andy的专长是把经过验证的技术与先进的技术混合在一起，创建各种新颖的——但也是实用的——解决方案。Andy在北卡罗莱纳州的罗利市拥有自己的顾问公司。     Dave Thomas 喜欢驾驶单引擎飞机飞行，并通过这样的方式为他的习惯付账：为各种难题寻找优雅的解决方案，提供诸多领域里的咨询服务——航空、银行、金融服务、电信、交通运输及Internet。在于1994年移居美国前，Dave在英国创立了一家通过ISO9001认证的软件公司，为世界各地的客户开发成熟、定制的软件项目。Dave现在是一位独立顾问，居住在德克萨斯州的达拉斯。
以The Pragmatic Programmer，L.L.C的名义，Dave与Andy正在协同工作，把合起来超过四十年的专业经验带给美国各地的客户。 译 者 简 介
马维达，《C++网络编程（卷2）》与《ACE自适配通信环境技术文档》的译者。技术兴趣为C++网络编程（ACE）与分布式对象计算（Internet Communications Engine）
内 容 简 介
《程序员修炼之道》由一系列独立的部分组成，涵盖的主题从个人责任、职业发展，直到用于使代码保持灵活、并且易于改编和复用的各种架构技术，利用许多富有娱乐性的奇闻轶事、有思想性的例子及有趣的类比，全面阐释了软件开发的许多不同方面的最佳实践和重大陷阱。无论你是初学者，是有经验的程序员，还是软件项目经理，本书都适合你阅读。
领悟程序员的哲学
在大学的时候，编程是我的兴趣，也是当时我给自己定位的职业方向。
当我在图书馆看到这本《程序员修炼之道》的时候，直觉告诉我应该看看这本书，或许对我的成长有帮助。读完之后更加肯定了自己的直觉是对的。当时我虽然没有实际项目的开发经验，不能一时领悟其意，但我明白，这本书中总结的原则和方法对我来说是极为宝贵的，于是买了一本放在床头。
参加工作后，随着编程经验的积累，我越来越能体会到这本书中的观点。每次重读书中的章节，我都会有新的收获；再结合自己的每次经历，都能与之共鸣——这是对我影响最深的一本书，也是我向朋友和同事推荐次数最多的一本书。有趣的是，书前Kevin Ruland的评论说：这是我唯一不会出借的一本书。究竟是一本什么样的书会让大师如此爱不释手？
这本书所涉及的内容很广，涵盖了程序员成长过程中和软件开发过程中要注意的地方。从程序员的个体哲学到编码过程中的各个环节，再到团队的项目管理；从程序员要如何扩充知识，如何思考问题，如何利用有效的工具打造个人的工作环境，到项目启动之前如何建立一些基本准则，如何分析、设计、编写、测试、重构，如何实现自动化，甚至是项目团队中提高实效的原则。书中的内容全都来自经验的总结，倡导编程中正确的观念和良好的习惯，而这正是优秀的程序员必须拥有的良好素质。
书中讲述的原则源于实践，高于实践，它们蕴涵着前辈们的智慧。随着知识的扩展、编程体验的增加，对这本书中的内容的理解也会愈加深刻。反过来，对前辈菁华的吸收，有助于我们提高编程水平，开发出更好的产品。
我深信这不是一本只要读一遍的书。这些原则看似简单，但细细品味一番，却是大哲大道，环环相扣，要理解透彻并不容易。例如，提示44告诉我们“不要靠巧合编程”，这道理看起来好像很简单，但我发现实际工作中还是很容易就犯这个错的。细想一下Bug列表中的问题，其中大多数问题不正是由于作了不正确的假设，或者是想当然造成的吗？要是一开始就有了深思熟虑，经过了合理的设计，完整有效地进行了测试，应该大部分都可以避免吧。而思考、设计、测试又紧扣书中其他章节。
曾经和朋友讨论关于员工培训的事。如果给程序员做培训，我首选的材料就是这本《程序员修炼之道》。
LAMP程序员 赵钟秋（belltoy）再次阅读，感受颇多
记得四年前刚开始工作时从公司拿到的第一本书，就是这本《程序员修炼之道》（英文版），作为新入职员工study group的学习材料，当时在senior engineer带领下和其他同事一起学习了这本书。虽然之前就听说这是一本好书，当时看的时候也只是觉得讲的都有道理，但这些是很自然的啊，干嘛花这么大的篇幅说来说去？所以只是囫囵吞枣地翻过也就扔在一边了。
之后也看过很多类似的书籍，《程序员修炼之道》也一直是公司新人的必备学习材料，而我却一直没再重拾这本书仔细读一遍，直到最近周筠老师发给我中文电子版，才又从书架上翻出当年的英文版，对照着中文电子版仔细读了一遍。
此次重读，感受颇多，也颇能理解为何公司一直选用此书作为新人教材。
这本书里虽只包含了很多看似粗浅朴素的道理，实则是若干经验的心血总结。比如谁都知道不要对自己家的破窗户置之不理，可实际中听到太多的妥协：这个代码已经这样了，只能继续在上面贴上丑陋的workaround，这其实是一种对责任的推卸和对未来的不负责。当然现实是不完美的，有时救火队员也不得不放下破窗户而迁就其他，但作为一个pragmatic程序员，保持追求完美的心态还是很有必要的，正因为这个心态，我们才会去追求代码的优美、设计、实现的正交、DRY（Don't Repeat Yourself）原则……
关于DRY，我想说，不但don't repeat yourself，也don't repeat others，我们看到太多重复造轮子的故事，正如书中提到“鞋匠的孩子没鞋穿”，作为一个pragmatic程序员，合理地使用工具、库，以及自己积累的开发的轮子，会让自己的productivity不断提升。这让我想起公司里一个让人崇拜的“牛人”，大家一直想把产品进程内cache做成多进程共享，正在大家讨论该怎么做的时候，“牛人”用短短几天时间已经完成了，众人再次对他又崇拜了一把。“牛人”其实是备有很多现成代码的，完成这个功能只是把之前积累的封装良好的模块重用就可以了。
书中推崇的另外一个方法：曳光弹。自己之前用prototype，一直犹豫于代码是否需要重用。其实原则上prototype的代码应该是抛弃型的，但有时候前期做的一些工作是为了确定方案、构建框架，而这些也是作为后期工作的基础。事实上，在项目前期值得仔细考虑的究竟是采用prototype还是曳光弹，取决于它们的适用场景（对于产品开发，曳光弹的应用场景可能相对会更多一些）。
当然，对于书中提到的对知识资产的管理（知识投资）、沟通和交流的重要性等，我想这就不单单对于程序员适用了，任何一个要想有所作为的人，这些方面的重要性都毋庸多说了。而对于自动化和文本处理等方面的经验，也是很多书中都提到的经验之谈（《UNIX编程艺术》、《卓有成效的程序员》等）。
最后，说一下这本书的译者马维达，我最早是在学校时读过他翻译的ACE文档及相关资料，收益颇多，ACE可谓网络编程技术的集大成者，而这本《程序员修炼之道》则可谓编程的集大成者，从项目管理、软件架构和设计、代码编写和测试，各方面在此书中都有精到的阐述。此书的翻译质量应该说比较准确，基本真实地表达了原书的意思，但正因直译，有些语句可能在理解上会有一些难度，比如P146,“只要对于那些被耦合在一起的模块而言，这是众所周知的和可以接受的，你的设计就没有问题。”不过细读这本书，这些有所晦涩的内容还是能理解的。当然，译者还是可以适当加些“译注”，让读者更容易理解，内容更顺畅的，比如书中直接用古鲁来翻译Guru，如果加上解释可能会更好；又比如Law of Demeter，原书没有解释得太清楚，如果多加些解释可能会更便于理解。
感谢周筠老师让我有机会重温这本优秀的书籍，为了完成作业，也为了让自己的认识提升。
趋势科技 stuff engineer 邹飞
一切阅读都是误读
一切阅读都是误读
—— 安伯托•艾柯
上次读这本书已经是五年前的事了，中文版刚出版我就买了一本。那时候，我的工作相对比较清闲，有大量的时间阅读。恰巧我在负责公司的校园招聘及新员工培训，非常需要一些不错的教材，更早的时候听说过这本书的英文版，但是没能一读，中文版自是不能放过。另外，那年我在写书，记录一些程序员生涯中的心得，对经验的总结都颇有兴趣。
爱不释手，是我第一次读完后的心境。完整经历了人生中第一个成功的大的软件项目后，我有许多感慨。知道了不少东西怎样做对，怎样做不对，但是要一条条写下来，却不知道怎么总结。这本书说出了许多我想说的，但却不知道该怎么说的道理。
接下来的日子，我在公司做过好几次技术培训，课题都是以这本书中的某个或某几个观点，再结合自己的经历展开的。对于信任我的同学，我总是将它作为第一本列在给他们开的书单中。
后来，国内又引进了几本类似的好书。比如《代码大全》、《UNIX编程艺术》。古人云，读书有三上，马上、枕上、厕上。我还真把书买了好几本，分别置于床头、办公桌上，方便睡前、如厕时阅读；手机里放入电子版，上下班路上，偶尔翻阅。这些书的确是值得逐章挑选出来，反复精读的。《程序员修炼之道》却于几年前推荐给新入职的同事，从我的视野里消失了。
这几天，同事把书还了我，加上周筠老师发给我电子版，我又重读了一遍。原以为那些嚼烂了的东西，不会再有新味道，但是我错了。
不同的人从不同的角度用不同的方式，阐述相同的道理。其中细微的差异，是需要读者有了许多许多的经历后，才能体会的。比如，在《程序员修炼之道》中花了六页分析DRY - Don't Repeat Yourself原则；而在《UNIX编程艺术》中把它称作SPOT - Single Point of Truth，大约用了一页半的篇幅。他们真是想表达完全一致的理念吗？我看未必。所以，作为读者，同样会有许许多多的想法。随着编程经历越来越多，思考次数的增加，重新和这些前辈的思想相印证，也是一件乐事。
我们以为理解了作者，其实是误解。但我们将再一次理解编程。
网易互动娱乐有限公司 杭州研究中心总监 云风
程序员升级必备
学过高中物理的人，应该会记得，原子中的电子获得能量之后，会发生能级跃迁，到达更高的能量状态。其实任何工种都是一样的，要跳出自己的水平，到达更高的级别，不是件容易的事。这个跳跃过程总需要一些东西的辅助。诚然，如果要成为一个好人，那么只要做好在幼儿园中学到的一切就足够。如果要成为一个好程序员，其实所需要的道理也多不了多少，只不过，当水平不够的时候，永远不能认识到那些朴素道理的重要。而当水平达到的时候，这些道理自然会明白。所以一本帮助程序员进阶的书，很容易落到低手觉得是废话，高手也觉得是废话的悲惨境地。
好几年前，有人向我推荐过这本《程序员修炼之道》，甚至专门买了一本送到我家。而当年的我，不知道是由于无知、自负、浮躁，或是其他，只草草翻了一下，就下了个“烂书”的定义，扔在书架一角。后来有朋友在我书架上发现，如获至宝，说已经买不到了。我当然乐得送了人情。在我心目中，最好的入门书永远是《代码大全》，那也是对我影响最深的一部书。
几年后，再来谈这本书，发现很多人的评价比我高得多，自知不妙，赶紧找来重读，才知道错过了什么。在一个滥俗的译名之下，在一个看起来不知所云的目录之后，在一些读起来拗口的句子之中，隐藏的竟然是相当伟大的思想——朴素而真挚，简单而有效。这时候我突然明白，这是一本不逊于《代码大全》的伟大著作，后者一直被我誉为“新手圣经”。
经验这个东西，往往并不能告诉我们什么一定对，但是可以告诉我们什么一定不对。这本书完全是经验凝成，没有大道理，没有新观念。这些朴素的道理就是创造一个合格软件和作一个好程序员所必须了解的。比如“提示44不要靠巧合编程”，这句话表达的意思是“不要预设立场”。听起来简单，但是只要随手翻翻你最新写过的一段程序，通常都会发现代码中做了大量的“假设”。书中用一道习题，假设了用户使用命令行环境，假设用户懂英语……都可能导致问题。怕了吧？幸好还有“提示30你不可能写出完美的软件”，这可不是帮你开脱责任，而是在讲如何控制需求，这正是能顺利完成一个项目的根本前提，可惜事实上往往到了项目失败的时候，人们才想起来需求出了问题。
这本书涉猎的范围相当广，如何设计架构，如何思考问题，如何测试，如何编码，如何处理文档……如果细心琢磨，构建软件的所有主干和细微枝节都有所涉及。和很多人的看法不同，我不认为这是一本可以轻松读完的书。一方面，这本书涉及的内容太多，虽然已经尽量讲述，但所有话题都可以继续引申出无限的内容；如果用心，还可以配合附录中所提到的各种论文和资源继续学习。习题也要仔细思考。这绝不是一本小说。另一方面，作者用了大量的隐喻，导致读起来有一定难度。开始我认为是翻译质量有问题，不过慢慢发现美国的读者读起来也未必容易。原因还是涉及的范围过大。我特意模仿这种风格写了本文的第一段，虽然是中文，可读起来也不容易。
可能以上的两点会阻挡一部分人阅读这本书，因我也是曾经受阻的人之一。不过，好书并不会随着时间的推移和平台的变化而消亡，好书只会成为经典。无论是《人月神话》，还是《代码大全》，都在时间的长河中沉淀下来，传颂至今。这本书，虽然也只有10年历史，不过现在再来翻看，不仅毫不落伍，甚至感觉穿透了时间，看到了这些年中不少自己犯过的错误，我相信这也是一本能经得起时间沉淀的书，只不过需要多点耐心。因此，我郑重地写下这篇书评，希望能读到这本书的人再多一点耐心，越过语言的障碍，直入本质，直至跃向更高级别。这个希望，不仅是对新手所说，其实也包括我自己。如本书开头所说：注重实效的程序员应该不断学习。我们都应该不断地学习下去。
银杏科技创始人 霍炬
程序员心底的小声音
编程大约有三个境界，新手、高手和高不成低不就的中手。这三个境界，大致和王国维先生划定的做学问的三个境界一一对应。一般来说，如果不经过几十万行的代码的锤炼（衣带渐宽终不悔，为伊消得人憔悴），或者长期在一个高手团队里面打磨切磋，那么无论怎么样的理论熟悉，打字熟练，考试全A，编程起来，都应该算是中手。一个中手如果机缘很好，得到高人亲自指点，则能很快成长为高手；如果没有这样的机缘，那就要在“众里寻她千百度”这个层次苦苦地求索锤炼很久，才能“蓦然回首”。
读书是一种很好弥补没有高手在场的方法，因为书是最好的老师。可现实是，高手写给中手的书很少。在任何行业，适合新手入门的书很多，适合中手的书就很少。原因有两个，一来高手极少愿意耐心指点成长秘诀，即使写了，也是蜻蜓点水，因为这些经验啊结论啊，都被他们本身提炼成了珠玑，他们觉得最重要的也就是那么寥寥几句，也没有太多的废话好写。而读者如果没有类似的经历，看到这些珠玑，也只是觉得把玩颇为有趣而已，极少能有同感。鲜有高手，能把技术书写成散文集，如Brooks一样，在《人月神话》中把经验教训和经历背景等一一道来，并且从这些经历中抽出一般性的知识。因此，高手的风格一般是浮光掠影地概括自己领会的几个原则和教训。这些寥寥数语的珠玑，对其他高手来说一看就懂，但是对于中手来说就很难理解了。所以很多高手写出来的给中手看的书就曲高和寡。二来，中手其实水平差异巨大，偏好也各不一样，有的或许根本认识不到自己应该走的成长轨迹，有的认为这些书籍是片面知识，所以把不喜欢的书都扔给到垃圾堆了，光捡自己喜欢的书看；有的未必看得上高手的经验，认为高手说的那些自己也早已领悟到。因此，也不喜欢购买这些书籍。由于这两个原因，造成了高手提携中手的书在市场上很少见到。
不过这样的书倒不是没有，比方说在编程领域，我至少可以推荐这四本书——《Pragmatic Programmer》、《The Art of UNIX Programming》、《Elements of Programming Style》和《The Productive Programmer》，它们都是高手所写，属于高手指导中手的典范。第二本和第三本我以前介绍过，第四本余晟同学的书评也比我写的好几百倍，所以我就以《Pragmatic Programmer》为例说说这个问题吧。
我们前面说了，对于中手，特别是在“寻她千百度”这个层次的中手来说，或许本身已经捡到了一些珠玑，或许对于像《Pragmatic Programmer》里面说的那些Tip，有的是深有同感的。比如DRY（Don’t Repeat Yourself不要重复你自己），基本上大家都知道，可是在实际中（至少我自己）还是不停地一次一次地犯错误，做事情也不符合DRY原则（一次一次犯错误本身也是一个DRY错误，因为DRY原则要求你对每种错误只能犯一次）。我们读的时候深有同感，可写代码的时候却忘到Java国去了，这还真不是个案，是非常普遍的现象。
能不能让正确的原则指导正确的行动本身，其实就是区分是否是高手的一个显著标志。试想，两个都了解KISS原则的程序员在一起写代码，高手的代码必然会自然流露出KISS的优雅，而中手或许需要旁人的提醒和多次重构，才能达到理想的状态。出现这个问题的原因很明显——中手没有完全内化KISS原则，因此尚且不能“运用自如”。内化是一个非常复杂的认知过程，本身涉及大脑中mind set和paradigm的切换，所以必然不是一个简单的隔夜就能完成的过程，这也就是为啥能够“消得人憔悴”，但是切换一旦完成，实践中就会自然流露出这种新的认识，也就是到了一个新的境界，发现灯火阑珊处。
那么原则和知识的内化这个过程如何加速呢？也就是说，怎么才能较快地到达高手境界呢？可以肯定地说，光靠对自己说我“下次一定按照这个原则这样做”是不行的。认知科学认为，频繁的高强度的外部刺激和自主的有意识的反复提醒是加速内化的两个重要方法。第一个方法需要外部环境的支撑。试想，如果一个程序员不是天天和复杂的文本处理打交道，他必然没有足够的外部刺激来熟悉和内化正则表达式；如果一个程序员不是天天和极度复杂的大项目打交道，即使用全自动编译环境和自动单元测试，也显得无甚必要。因此，除非你正好掉进了一个天天有高强度训练的环境，否则全靠第一点是不可能的。尤其是自学一门语言和一门技术的程序员，往往在没有高强度训练之前就拿着这些技能投入工作了，因此想成为某方面的高手，只能采取第二条路，就是有意识地强化实践和反复提醒。
《圣经》里有一个故事，说一个人在沙漠里，信心丧失的时候，突然听到“A Still Small Voice”（平静的小声音），即上帝的启示。这个平静的小声音把他从绝望中拉了回来。其实对这个人来说，他本身的实践能力在“平静的小声音”出现前后并没有多大的改变，唯一的不同就是他知道该怎么做了。
内化一个人知识或认识的时候所循的路径也是一样的。我们常常会“忘了”应该怎么正确地做一件事情（这个地方的“忘了”，指我们之前从书中或其他渠道读到看到了正确的原则或方法，但是在那一刻脑子里根本没考虑这个原则或方法，因为这个原则或方法根本没有亲自实践过，所以根本不是自己的一部分，不属于自己）。在这个时候，如果突然有一个平静的小声音跳出来，说，“嘿，你是不是该遵循这个原则，用这个方法？”无须说，我们对问题的思考就能顿时全面起来，也会更加深刻理解原先读到看到的不属于自己的原则和方法。当然，我们更加感兴趣的是，如何能够在身边没有高手和上帝发出这样的平静的小声音的时候，自己发出这样的小声音？
怎么靠自己呢，记得鲁迅小朋友破坏公物在课桌上刻的“早”么？是的，我们须要抽象出一些简单的词句和规则，靠记忆和不断地提醒，小规模地内化这些小声音，让这些简单的小声音能够时刻从大脑里跳到耳边，提醒自己。具体来说，在阅读上面几本书，尤其是阅读《Pragmatic Programmer》的时候，如果仅仅以普通的浏览的方式阅读，就会很简单地陷入“啊，这个我知道了，啊，那个我了解了，嗯，这个以后要注意”的套路中。这样的阅读方式，只会强化原有的自己已经知道的部分，而不大可能把“以后要注意”这部分全部内化。所以，自负的读者读完之后必然觉得“哈哈，高手不过如此，大部分我也知道嘛”，而不是“是的，我还有不少要注意”。这两种态度，就把高手和易于满足的中手永恒地隔开了。我觉得，想要内化这些小声音，还是要靠实践，如果不实践，即使你把这些小声音写在100块钱的高档笔记本上也没有用。我个人觉得，理想的阅读状态应该是先大致理解和记住里面的Tip，然后每周争取实践2~3个Tip。其实这样做完一圈也就是半年，在这一圈后就会记住所有的Tip的内容，这时候，小声音就成了自己的一部分了。然后在剩下的几年里，只要时时有这些小声音跳出来，告诉你，“要自动频繁地测试”，或者“别手动做繁琐的工作”，你会很快被强迫转换到高效而优雅的工作状态中来。到了那个时候，这些小声音就再也不会跳出来了，因为你早就自然地遵守这些小声音的要求了。
《Pragmatic Programmer》和《The Elements of Programming Style》书里面的Tip都不是来自上帝的话语，但都是值得随身带着的小声音。其实只要处理过实际问题，编过几万行程序，大多程序员都会有或深刻或浅显的对各个Tip的感悟，而且我相信或许有程序员对有些Tip的认识能比原书的作者还要深刻，这是很正常的。事实上，每一个Tip只是一句话而已，对这一句话的理解层次，则完全不是这一句话能够覆盖的。比如说，一天写了两个Hello Word的程序员能领悟到DRY，一位刚刚重构扔掉几千行重复代码的程序员也能领悟到DRY，而这两个DRY所在的认识层面，必然是不一样的。再好比说我在“编程珠玑番外篇”这个系列里面写的有些文字，看上去很有道理，但笔者本人对这些文字的认识可能比我的读者要浅。即使有些牛人觉得上面这几本书的作者在某些原则上的认识不够深刻，或者觉得作者只是在罗列一些小碎片，但只要读这些书，特别是《Pragmatic Programmer》这本书的那些小Tip，依然是有益的，因为他或许能触发你高于作者的思考，然后在你的脑中形成更加圆润的珠玑。而对于像我这样属于中手下游平时又没有大项目训练的人，《Pragmatic Programmer》这本书，和其他几本书一起，实在是很好的“小声音汇编”。
Washington University Ph.D. candidate 徐宥
专业人士对《程序员修炼之道》的赞誉
“关于这本书，最棒的是它能使编程过程保持新鲜。（本书）能帮助你持续成长，而且显然，它出自到过那里的人之手。”
——Kent Beck，Extreme Programming Explained: Embrace Change的作者
“我发现这本书出色地混合了坚实的建议和美妙的类比！”
——Martin Fowler，Refactoring与UML Distilled的作者
“我会买上一本，读上两遍，然后让我的所有同事都冲出去买一本。这是一本我决不会出借的书，因为我担心丢失。”
——Kevin Ruland，Management Science，MSG-Logistics
“作者的才智和实践经验显而易见。讨论的话题既切身又有益……迄今为止，对我而言它最大的力量在于那些出色的类比——曳光弹、破窗户，还有以直升机为基础、对为何需要正交性所做的惊人解释——特别是在紧急情况下。我几乎毫不怀疑：无论是编程“小工”，是专家级的顾问，还是其他专业人员，这本书最终都将成为有用信息的极好来源。”
——John Lakos，Large-Scale C++ Software Design
“这是那种我会在其出版时买上一打、送给我的客户的书。”
——Eric Vought，软件工程师
“现在的大多数关于软件开发的书都没能说清一个杰出的软件开发者究竟应该具备哪些能力，而是把时间花在介绍语法和技术上——在现实生活中，拥有有才华的、真正精通其技艺的开发者，对任何软件团队而言都是其可能具有的最大优势。一本出色的书。”
——Pete McBreen，独立顾问
“自从读了这本书以后，我实施了书中提出的许多实用建议和提示。所有这些建议和提示都为我的公司节省了时间和金钱，同时还帮助我更快地完成了我的工作！每一个以编码为生的人，都应该在桌面上放一本做参考。”
——Jared Richardson，高级软件开发员，iRenaissance, Inc.
“我想看到这本书被发给我的公司的每一个新员工……”
——Chris Cleeland，高级软件工程师，Object Computing, Inc.
软件开发的变化并不大
写完《程序员修炼之道》至今已有十年。在这十年中，软件产业发生了翻天覆地的变化。很多人逐渐放弃随意的开发方式，转而学习采用更能保证开发结果的方法论，这其中有许多方法论是以敏捷技术为基础的。编程语言的发展出现了一种趋势，静态语言（如Java和C++）的应用率在逐步降低，而更动态的语言（比如Python和Ruby）的普及率在上升。
在体系结构方面，早期的应用集中在数据中心，后来快速过渡到桌面电脑，现在又以同样的速度向云端迁移。开发者现在不得不学习新的体系结构原则、新的网络通信技巧和新的应用部署方式。同时，应用正在向并行化的方向发展。
从表面上看，软件世界似乎陷入了疯狂的状态。
但如果你深入繁杂表象的背后，会发现变化其实并不大。1999年的那些通用开发原则，在2009年同样有效（很可能到2019年还会有效）。我们认为其中的许多原则都包含在这本书里了。
假设我们今天才写这本书，会有什么不同吗？表面上会有些不同。我们可能会采用不同的编程语言和技术给出不同的案例。我们可能不会用太多笔墨强调测试的重要性，因为今天大家已经认识到测试的作用。我们可能会更多地介绍Web、社交和协作方面的技术。
但这本书的本质不会变。因为软件是人写的，优秀的程序员都会采用务实和实践的方法。他们知道变化越多，掌握事物的基本原则就越重要。
祝阅读愉快。别忘了从编程中获得乐趣！
Dave Thomas & Andy Hunt, The Pragmatic Programmers
2009年8月
译  序
本书原名“The Pragmatic Programmer”，也就是“注重实效的程序员”。正如书名所示，本书将围绕“注重实效”讲述关于编程的各种话题：个人责任、曳光弹开发、调试策略、元程序设计、按合约设计（Design By Contract）、重构、无情的测试，等等。看到本书的目录，你也许会奇怪，300多页的篇幅，怎么能涵盖如此多内容？但本书的两位作者Andy Hunt和Dave Thomas的确做到了，他们知道抵达编程的各种维度的途径，并找到了一种言简意赅的方式讲述这些途径；与此同时，在书中还提供了大量资源，可以帮助你找到各种更深入讨论这些话题的读物。本书的各个小节既独立又相关，你可以从头开始阅读，也可以随手翻开任何一页开始阅读——Dave Thomas就将本书视为一本“洗手间读物”。如果你是编程初学者，你可以从本书中了解到各种编程技术和方法，根据书中的指引拓展你的编程生涯；如果你是富有经验的程序员，同样可以从本书中获益：如果一本书能够全面、明晰地总结你从实践中获得的各种认识、总结你从其他书里散乱地读到的技术和方法，这本书就一定不是无益的。
除了是程序员，Andy Hunt还是一位木匠和音乐家，而Dave Thomas则喜欢驾驶单引擎飞机。尽管作者未曾明言，在本书的许多地方，你都将看到与这样的背景相关的叙述。我想，对于两位作者而言，编程就和木匠活、和音乐创作、或是驾驶飞机一样，既需要禀赋，更需要坚持不懈的学习和训练——这也正是书中所说的，编程是一种技艺，一种需要用心学习的技艺。也许，只有在长久的学习之后，我们才会开始明白书中提到的“hacker”的真正含义：“Someone who loves to program and enjoys being clever about it”（摘自《自由软件杂志》）。
我仍然要感谢侯捷先生和周筠老师，他们像以前一样，为了行业的发展扶掖后进，竭尽心力。谢谢你们的支持和帮助。倘若我未能始终如一，请你们原宥。感谢本书的编辑方舟先生，他是一个诚恳、好学的年轻人，从不因我的苛刻批评而存有怨言。他的热情、他的年轻，常常让我想起自己那些古怪的、正渐渐没入记忆深处的青春时光。
这是一本“注重实效”的书，其实也可以说，是一本“实用主义”的书。但正因为这样，两位作者在书序的最后给家人的谢辞或许就更加意味深长：
谢谢你们让我们梦想。
马维达于贵阳
前  言
作为评阅者，我得到了提早阅读你拿在手上的这本书的机会。即使当时还只是草稿，它就已是一本很好的书。Dave Thomas和Andy Hunt有话要说，并且知道怎样去说。我见过他们所做的事情，知道他们所说的将是有效的。我请求让我来撰写这篇前言，以便有机会向你解释其中的原因。
简而言之，本书将告诉你怎样以一种你能够遵循的方式去编程。也许你不认为这是一件困难的事情，但事情却并非如此。为什么？原因之一是，并非所有的编程书籍都是由程序员撰写的。其中有许多是由语言设计者、或是与他们有合作关系的报刊记者编撰而成，意在推销他们的作品。那些书告诉你怎样通过某种编程语言进行表达——这当然很重要，但却只是程序员所做的事情的一小部分。
除了通过编程语言进行表达，程序员还要做些什么？嗯，这是一个更深入的问题。大多数程序员在解释他们所做的事情这个问题上都会有困难。编程是一项充满了各种细节的工作，追踪这些细节需要专注。时间流逝、代码出现，你查看它们，那里全是些语句。如果你不仔细思考，你也许会以为编程不过就是敲入某种编程语言的语句。你当然错了，但找遍书店的编程专柜，你却还是讲不出所以然。
在《程序员修炼之道》一书中，Dave和Andy将告诉我们怎样以一种我们能够遵循的方式编程。他们何以能这样聪明？他们不也是和其他程序员一样，专注于各种细节而已吗？答案是他们在做某件事情时，会把注意力投注在他们在做的事情上——然后他们会试着把它做得更好。
设想你在参加一个会议。或许你在想，这个会议没完没了，你还不如去写程序。而Dave和Andy会想，他们为什么在开会，他们想知道是否可以通过另外的方式取代会议，并决定是否可使某样事情自动化，以使开会的工作推后。然后他们就会这样去做。
这就是Dave和Andy思考的方式。开会并非是某种使他们远离编程的事情。开会就是编程，并且是能够加以改善的编程。我之所以知道他们以这样的方式思考，是因为这是书中的第二条提示：思考你的工作。
那么再设想一下，他们这样思考了几年。很快他们就会拥有一堆解决方案。现在设想他们在工作中使用这些解决方案，又是几年；他们还放弃了其中太过困难、或者不能总是产生结果的解决方案。噢，这样的途径几乎定义了“pragmatic”（注重实效）的含义。现在设想他们又用了一两年来写下他们的解决方案。你也许会想，这些信息可真是金矿。你想对了。
两位作者告诉我们他们是怎样编程的，并且是以一种我们能够遵循的方式来告诉我们的。但这一陈述的后半部分的含义也许要多于你所想到的。让我来解释一下。
作者一直在小心避免提出软件开发理论。这是一件幸运的事情，因为如果他们那样做了，他们就不得不为了捍卫他们的理论而对各章进行“调整”。这样的“调整”是，比如说，物理科学中的传统，在这些学科中，理论不是最终成为定律，就是被静静地丢弃。而另一方面，编程所具有的法则（如果有）却非常少。所以围绕想要成为法则的东西形成的编程建议在纸面上也许显得很好，而在实践中却无法让人满意。这也是那么多方法学书籍误入歧途之处。
我研究这一问题已有十多年，并发现一种叫做模式语言（pattern language）的方法最有前途。简而言之，模式就是解决方案，而模式语言就是相互支援的若干解决方案的系统。围绕着对这些系统的探求，已经形成了一整个社群。
本书不只是一堆提示。它是一种“披着羊皮”的模式语言。我这样说，是因为每一条提示都汲取自经验、作为具体建议讲授、并与其他提示关联而形成系统。是这些特征使我们能够学习并遵循模式语言。在本书中它们以同样的方式发挥着作用。
你可以遵循本书的建议，因为它们是具体的。你不会发现含混不清的抽象。Dave和Andy直接为你而写，就好像每一条提示都是能给你的编程生涯供给能量的重大策略。他们让提示保持简单，他们讲故事，他们使用轻松的笔触，他们接着还给出了各种问题的解答，这些问题将在你进行尝试时出现。
不仅如此。在你阅读了十或十五条提示之后，你将开始看到工作的另外一个维度。我们有时称之为“QWAN”，也即“quality without a name”（无名的品质）。本书的哲学将渗入你的意识，并与你自己的哲学交融在一起。它不鼓吹，它只是讲述什么可行。但在讲述中却又有更多的东西到临。这正是本书美之所在：它体现它的哲学，以如此谦逊的方式。
这就是它：一本易于阅读——也易于应用——的关于整个编程实践的书。我一直在不断讲述它为何有效，而你关心的也许只是它的确有效。它的确有效，你会看到的。
——Ward Cunningham
序
本书将帮助你成为更好的程序员。
不论你是单独的开发者，是大型项目团队中的一员，还是同时与许多客户共事的顾问，这都没有关系。本书将帮助你，作为一个个体，更好地完成工作。本书不是理论书籍——我们专注于实践性的话题，专注于让你利用你的经验做出更有见识的决策。pragmatic一词来自拉丁语的pragmaticus——“精于事务”——后者又源自希腊语的πραττειυ，意为“to do”。这是一本关于“doing”的书。
编程是一种技艺。用最简单的话表述，编程可归结为让计算机做你（或你的用户）想要它做的事情。作为程序员，你既是倾听者，又是顾问；既是解释者，又是发号施令者。你设法捕捉难以捉摸的需求，并找到表达它们的方式，让一台纯粹的机器能够合理地处理它们。你设法为你的工作建立文档，以使他人能够理解它；你还设法使你的工作工程化，以使他人能够以它为基础进行构建。还有，你设法在项目时钟无休止的“嘀嗒”声的催迫下完成所有这些工作。你每天都在创造小小的奇迹。
编程是艰难的工作。
有许多人声称要给你帮助。工具供应商吹嘘它们的产品所展现出的奇迹。方法学古鲁（guru）允诺说他们的技术保证有效。每个人都声称他们的编程语言是最好的，而每一种操作系统都是对所有可以想象得到的问题的解答。
当然，所有这些都不是真的。并不存在容易的答案。也不存在最佳解决方案这样一种东西，无论它是工具，是语言，还是操作系统。能够存在的只是在某些特定情形下更为适宜的系统。
这正是注重实效（pragmatism）登场的地方。你不应该局限于任何特定的技术，而是应该拥有足够广博的背景和经验基础，以让你能在特定情况下选择好的解决方案。你的背景源自对计算机科学的基本原理的理解，而你的经验来自广泛的实际项目。理论与实践的结合使你强大起来。
你调整你的方法，以适应当前情形与环境。你判断对项目有影响的所有因素的相对重要性，并利用你的经验制定适宜的解决方案。你随着工作的进展持续不断地进行这样的活动。注重实效的程序员不仅要完成工作，而且要完成得漂亮。
谁应该阅读本书
本书的目标读者是想要变得更为有效、更多产的程序员。或许你觉得灰心，因为你好像没有在实现自己的潜能。或许你看见同事似乎在使用一些工具，使他们自己比你更多产。也许你现在的工作使用的是较老的技术，而你却想要知道怎样把较新的思想应用于你正在做的工作。
我们不会假装自己拥有所有的（或者即使是大部分）答案，我们的思想也并非适用于所有情况。我们所能说的只是，如果你遵循我们的方法，你将迅速地获取经验，你的生产力将会提高，并且你还将更好地理解整个开发过程。你将能编写更好的软件。
注重实效的程序员有哪些特征
每一个开发者都是独特的，有着个人的力量和弱点、偏好和嫌恶。随着时间的过去，每一个开发者都会营造出他或她自己的个人环境。这个环境会有力地反映这个程序员的个性，就像他或她的业余爱好、衣着或是发型一样。但是，如果你是一个注重实效的程序员，你就会具有下列特征中的许多特征：
早期的采纳者/快速的改编者。你具有技术和技巧上的直觉，你喜爱试验各种事物。给你一样新东西，你很快就能把握它，并把它与你的知识的其余部分结合在一起。你的自信出自经验。
好奇。你喜欢提问。那很漂亮——你是怎么做的？你用那个库时有问题吗？我听说的这个BeOS是什么？符号链接是怎样实现的？你是收集小知识的林鼠（pack rat），每一条小知识都可能会影响今后几年里的某项决策。
批判的思考者。你不会不首先抓住事实而照搬别人的说法。当同事说“因为就该那么做”或者供应商允诺为你的全部问题提供解决方案时，你就会嗅到挑战的气息。
有现实感。你会设法理解你面临的每个问题的内在本质。这样的现实主义给了你良好的感知能力：事情有多困难，需要多长时间？让你自己了解某个过程会有困难，或是要用一点时间才能完成，能够给予你坚持不懈的毅力。
多才多艺。你尽力熟悉广泛的技术和环境，并且努力工作，以与各种新发展并肩前行。尽管你现在的工作也许只要求你成为某方面的专才，你却总是能够转向新的领域和新的挑战。
我们把最基本的特征留到了最后。所有注重实效的程序员都具有这些特征。它们基本得足以用提示的方式来陈述：提示1
Care About Your Craft
关心你的技艺
我们觉得，除非你在乎能否漂亮地开发出软件，否则其他事情都是没有意义的。
提示2
Think! About Your Work
思考！你的工作
为了让你成为注重实效的程序员，我们向你发出挑战：在你做某件事情的时候思考你在做什么。这不是对当前实践的一次性审计——它是对你每一天、在每一次开发上所做出的每一项决策的批判评估。不要依靠自动驾驶仪。不间断地思考，实时地批判你的工作。老IBM公司的箴言，THINK!，是注重实效的程序员的曼特罗（mantra，印度教或佛教的颂歌、咒语——译注）。
如果这在你听来是困难的工作，那么你就正在展现出有现实感的特征。这将占据你的一些宝贵时间——很可能是已经处在极大压力之下的时间。酬劳则是更为活跃地参与你喜爱的工作、感觉到自己在掌握范围日增的各种主题，以及因感受到持续的进步而欢愉。从长远来说，你在时间上的投入将会随着你和你的团队变得更为高效、编写出更易于维护的代码，以及开会时间的减少而得到回报。
注重实效的个体，大型的团队
有人觉得在大型团队或复杂项目中没有个性的位置。“软件构造是工程学科。”他们说：“如果个别的团队成员自行其是，团队就会崩溃。”
我们不同意这种看法。
软件的构造应该是工程学科。但是，这并不排斥个人的技艺。想一想中世纪在欧洲建造的大教堂，每一座都需要数千人年的努力，跨越许多个十年。学到的教训被传递给下一批建造者，后者又通过他们的造诣去提高结构工程的水平。但木匠、石匠、雕刻工和玻璃工都是手艺人，他们解释各种工程需求，以制造超越了建筑的纯粹机械方面的一个整体。他们相信，他们个人的贡献支撑了整个项目：
我们，采集的只是石头，却必须时刻展望未来的大教堂。
——采石工人的信条
在一个项目的总体结构中，总有个性和技艺的位置。就软件工程目前的状态而言，事情就更是如此。一百年之后，我们的工程看起来或许已很古老，就像是中世纪的大教堂建造者所使用的技术在今天的土木工程师看来很古老一样，但我们的技艺却仍将受到尊重。
它是一个持续的过程
一位参观英格兰伊顿公学的游客问那里的园丁，他是怎样让草坪变得如此完美的。“那很容易，”园丁回答说，“你只要每天早晨拂去露水，每隔一天刈一次草，每个星期碾压一次就行了。”
“就是这些吗？”游客问。
“就是这些，”园丁回答说，“这样做上500年，你也将拥有一片漂亮的草坪。”
了不起的草坪需要每天给予一点关心，了不起的程序员也是这样。管理顾问们喜欢在谈话中扔出“kaizen”这个词。“kaizen”是一个日语术语（译注：kaizen，日文“改善(かいぜん)”），表达的是持续地做出许多小改进的概念。它被认为是日本制造业在生产率与质量方面取得长足进步的主要原因之一，并且在世界各地得到了广泛的效仿。kaizen也适用于个人。每天为提炼你所拥有的技能而工作，为把新的工具增加到你的技能列表中而工作。与伊顿的草坪不同，你在几天之中就将开始看到结果。几年之后，你将会惊奇你的经验得到了怎样的发展，你的技能得到了怎样的提升。
本书的组织方式
本书由一系列小节组成。每一节都是独立的，并且讨论一个特定的话题。你会发现大量交叉引用，帮助把各个话题置入相关语境（context）中。请随意以任何次序阅读各节——这不是一本需要你从头到尾顺次阅读的书。
有时你会遇到标有提示nn（比如第xxix页上的提示1：“关心你的技艺”）的。除了强调文本中的要点以外，我们还觉得提示有其自身的生命——我们每天都和它们生活在一起。在本书末尾你可以找到全部提示的一览表。
附录A包含了一组资源：本书的参考文献、Web资源的URL列表及我们推荐的期刊、书籍和专业组织的列表。贯穿全书你将会发现对参考文献和URL列表（比如[KP99]和[URL18]）的分别引用。
我们还在适当的地方包括了一些练习和挑战。练习通常有相对直接的答案，而挑战则更为开放。为了让你对我们的想法有所了解，我们还在附录B中包括了我们对练习的解答，但这些练习很少只有一个正确的解决方案。挑战可以用做小组讨论的基础，或是高级编程课程中的论文作业。
名称的内涵
“我使用词语时，”Humpty Dumpty用一种轻蔑的语调说，“我要它是什么意思它就是什么意思——不多也不少。”
——Lewis Carroll, Through the Looking-Glass
在全书的各个地方，你会遇到各种各样的行话（jargon）——它们或者是非常纯正的英语，被故意误用来表示某些技术事物；或者是人为捏造的可怕词语，由对语言怀有嫉妒之心的计算机科学家赋予了各种含义。我们第一次使用某个这样的行话词语时，会试着定义它，或至少是给出关于其含义的提示。但是，我们确信某些行话已经掉进了故纸堆，而另一些，比如对象和关系数据库，十分常用，加上定义反而让人厌烦。如果你确实遇到了一个你未曾见过的术语，请不要轻易跳过它。花点时间查一查，或是在网上，或是在某本计算机科学课本中。而且，如果有机会，就给我们发个邮件，抱怨一下，让我们在下一版中加上定义。
说过所有这些之后，我们决定报复一下计算机科学家们。有时候，有一些行话词语能够完好地表达各种概念，我们却决定忽略它们。为什么？因为已有的行话通常都被限定在特定的问题领域中，或是特定的开发阶段。而这本书的基本哲学之一就是我们推荐的大多数技术都是普遍适用的：例如，模块性适用于代码、设计、文档及团队组织。当我们想要在更宽泛的语境中使用传统的行话词语时，它就会造成混淆——我们似乎无法克服原来的术语所附带的包袱。在发生这样的事情时，我们就会发明我们自己的术语，并以此为语言的衰败做出贡献。
源码与其他资源
书中所示的大部分代码都摘录自可从我们的网站上下载的可编译源文件
你也能在那里找到我们认为有用的资源链接，以及本书的更新及关于其他注重实效的程序员的开发活动的新闻。
给我们发送反馈
我们将重视你的来信。意见、建议、文本中的错误，或是例子中的问题都很欢迎。
致谢
当我们开始撰写本书时，我们并不知道它最终会成为这样一个协作的成果。
Addison-Wesley一直都很卓越，从选题到待印制的拷贝，他们领着一对幼稚的黑客走过了整个书籍制作过程。十分感谢John Wait和Meera Ravindiran最初的支持；感谢Mike Hendrickson，我们热心的编辑（和小气的封面设计者！）、还有Lorraine Ferrier以及John Fuller在制作上提供的帮助；感谢不屈不挠的Julie Debaggis把我们大家团结在一起。
然后是评阅者：Greg Andress、Mark Cheers、Chris Cleeland、Alistair Cockburn、Ward Cunningham，Martin Fowler、Thanh T. Giang、Robert L. Glass、Scott Henninger、Michael Hunter、Brian Kirby、John Lakos、Pete McBreen、Carey P. Morris、Jared Richardson、Kevin Ruland、Eric Starr、Eric Vought和Chris Van Wyk。没有他们细心的评阅和宝贵的洞见，这本书不会像现在这样易读、准确，并且会加长一倍。谢谢你们大家的时间和智慧。
几年来，我们与许多锐意进取的客户工作在一起，取得并提炼了我们在此写下的经验。最近，我们有幸与Peter Gehrke一道参与了若干大型项目的开发。非常感谢他对我们的技术的支持和热情。
本书通过Linux下的Bash和zsh shell，使用LaTex、pic、Perl、dvips、ghostview、ispell、GNU make、CVS、Emacs、XEmacs、EGCS、GCC、Java、iContract和SmallEiffel制作。令人惊讶的是，所有这些奇妙的软件都可以自由获取。我们应该向世界各地的注重实效的程序员大声说：“谢谢你们”，他们为我们大家奉献了上述的以及其他的作品。我们尤其要感谢Reto Kramer在iContract方面给我们的帮助。
最后，但绝非最不重要的是，我们对我们的家人亏欠甚多。她们不仅要忍受深夜的键盘敲击声、巨额的电话账单以及我们长期心不在焉的状态，她们还一次又一次很有风度地阅读了我们所写下的东西。谢谢你们让我们梦想。
Andy Hunt
Dave Thomas
目  录
前言 xxix
序 xxxi
第1章  注重实效的哲学 1
1  我的源码让猫给吃了 2
2  软件的熵 3
3  石头汤与煮青蛙 5
4  足够好的软件 8
5  你的知识资产 10
6  交流 14
第2章  注重实效的途径 19
7  重复的危害 20
8  正交性 25
9  可撤消性 33
10  曳光弹 36
11  原型与便笺 40
12  领域语言 43
13  估算 48
第3章  基本工具 55
14  纯文本的威力 56
15  shell游戏 60
16  强力编辑 63
17  源码控制 67
18  调试 69
19  文本操纵 77
20  代码生成器 80
第4章  注重实效的偏执 85
21  按合约设计 86
22  死程序不说谎 95
23  断言式编程 97
24  何时使用异常 100
25  怎样配平资源 103
第5章  弯曲，或折断 111
26  解耦与得墨忒耳法则 112
27  元程序设计 117
28  时间耦合 121
29  它只是视图 127
30  黑板 134
第6章  当你编码时 139
31  靠巧合编程 140
32  算法速率 144
33  重构 149
34  易于测试的代码 153
35  邪恶的向导 160
第7章  在项目开始之前 163
36  需求之坑 163
37  解开不可能解开的谜题 172
38  等你准备好 174
39  规范陷阱 176
40  圆圈与箭头 178
第8章  注重实效的项目 181
41  注重实效的团队 181
42  无处不在的自动化 186
43  无情的测试 191
44  全都是写 200
45  极大的期望 205
46  傲慢与偏见 208
附录A  资源 209
专业协会 209
建设藏书库 210
Internet资源 212
参考文献 221
附录B  练习解答 225
索引 249
注重实效的程序员之快速参考指南 263