标题：编程匠艺
编程匠艺——编写卓越的代码

内容简介
如果你可以编写出合格的代码，但是想更进一步、创作出组织良好而且易于理解的代码，并希望成为一名真正的编程专家或提高现有的职业技能，那么《编程匠艺——编写卓越的代码》都会为你给出答案。本书的内容遍及编程的各个要素，如代码风格、变量命名、错误处理和安全性等。此外，本书还对一些更广泛的编程问题进行了探讨，如有效的团队合作、开发过程和文档编写，等等。本书各章的末尾均提供一些思考问题，这些问题回顾了各章中的一些关键概念，可以促使你像专家一样思考，从而使本书成为那些渴望作为团队的一分子，职业并高效地编程的新手们的一本绝佳的参考书。
作者简介
Pete Goodliffe是一位软件开发专家，他在软件“食物链”上从未驻足不前。他在各种各样的项目中使用过许多种语言。他还在教授和指导程序员方面有着丰富的经验，并且常年为ACCU的C Vu杂志（www.accu.org）撰写栏目“编程的职业化”。Pete痴迷于编写出色的、没有错误的代码，这使得他有更多的时间与自己的孩子共度美好时光.
推 荐 序

——打造开发者的核心竞争力
信息产业几乎是开放程度最高的产业，其发展之快，让身处其中的我们既感到兴奋和激动，也时常困惑和惶恐。信息技术的变化太快、太激烈，一切都在迅速革新当中，作为技术人员，我们今天熟悉并且赖以安身立命的东西，很快就会变成故纸堆里的古董。人生总是需要不断积累才能越走越高的，如果找不到一项可以积累提升、而且被市场所承认的核心竞争力，事业的大厦是建不起来的。于是一个严峻的问题就摆在每一个技术人员的面前——什么才是我们的核心竞争力？
二十年前，人们认为软件开发者的核心竞争力应该体现在他的聪明才智和扎实的基本功上，要精通算法、硬件、编译、计算机体系结构，要有天马行空般的想像力和创造力，能够单枪匹马单打独斗。至于什么团队协作、编码规范、单元测试、最佳实践，都是对天才的不必要的羁绊。
大约到了20世纪90年代中期，风水变了。随着软件的规模越来越大，以及当代操作系统、面向对象技术、软件开发工具、程序库和框架的普及，“平台”和“工具”变得越来越重要了。大多数时候，开发者不需要自己从头实现所有功能，他所依赖的平台已经准备好了现成的组件供使用，有的时候甚至应用程序中最繁琐、最复杂的部分已经由框架或程序库实现好了。因此，人们普遍认为，一个开发者的核心竞争力很大程度上表现为对平台与工具的理解和掌握，并依托这种理解创造性地构筑产品，或者更确切地说，一种创造性地组装产品的能力。你还在为刚刚琢磨出来的一个高效算法而得意吗？旁边那位借助程序库里提供的组件，已经快速地完成了整个功能模块；你发明了一个新的视频格式以及对应的codec？很了不起！不过另一个初出茅庐、连快速傅里叶变换算法都写不出来的团队已经基于sourceforge上的开源组件做出产品来，并且播得满互联网都是了。当然，黑客们仍然有着不可取代的价值，总是能找到自己的位置；但是对于那些强调团队作战、快速行动的企业来说，一个熟练掌握MFC、Delphi、J2EE、ASP.NET或者LAMP的开发者可能更实用，能更有效地为企业带来价值。因此，这样的程序员便一时成为企业的宠儿，众人眼中的高手。
然而不到十年下来，问题又出现了。流行的平台和工具如走马灯般你方唱罢我登场：昨天还在为领悟了MFC、Delphi而沾沾自喜，今天就发现应用主流已经是Web了；刚刚啃完艰深的EJB2，抬眼一看却发现它已经被Spring的拥趸们批倒批臭了；上个月还是冲在敏捷Java领域的改革派，这个月就被一群嘴上无毛的RoR粉丝给划到改革的对立面去了；ASP.NET还没学踏实呢，微软又准备好ASP.NET MVC、ASP.NET AJAX、Silverlight等等一大堆新玩意让你啃了。这样下去，什么时候是个头？把自己的核心竞争力建立在这些转瞬即逝的昙花上，难道不是把有限的生命投入到无限的瞎折腾之中吗？难道只有钻到一间舒舒服服的大公司里，到了三十多岁就寻求所谓的“转型”，顺着一条十分确凿的“职场路线”攀或是混，最后在公司没有倒闭或者自己没有被“战略裁员”的幸运之下头顶玻璃天花板光荣退休，才是中国程序员的归宿？什么才是程序员可以长期积累，不断提高，不但足以安身立命，而且能够实现梦想、成就事业的核心竞争力呢？ 回答好这个问题，对于今天的开发者来说，可能比掌握和精通某项具体技术意义重大得多。
在我看来，当代程序员的核心竞争力至少应该体现在这么几点上：有扎实的基本功，活跃的想像力与创造力，快速的学习能力，具备行业和领域知识，以及专业的软件工艺能力。而在这其中，专业软件技能是最基本、也是最重要的一项。
什么是专业软件技能呢？就是正确地开发软件的能力，更具体地说，是通过一系列有组织的、有原则、流程化、可检验、可重复的实践行为，协作式开发高质量程序的能力。对于一个程序员来说，这是你的看家老本，对于一个软件团队来说，这是你们的立足之基。算法不会，可以查资料慢慢掌握；不理解行业，可以边做边学，逐渐深入；缺乏创新，可以站在巨人肩膀上耐心摸索；甚至基本功不足，也可以自我弥补，可是如果没有做软件的专业态度和实践技能，没有制作合格软件的工艺水平，连一段高质量的程序都写不出来，试问你还剩下什么？
经过近三十年的时间，人们最终认识到，在规模化团队协作的情况下，决定软件产品质量的不再是个人的聪明才智，也不是靠什么神仙技术，而是团队的工艺实践。是否在一开始就形成了开发计划？是否对这个计划进行了必要的确认、维护和跟踪？必要的规范文档是否撰写了？是否形成了合理的架构？是否恰当地选择了开发工具和编程语言？是否建构了适于团队渐进协作的良好的工具和工作平台？是否一开始就形成了有力的缺陷核查、控制和跟踪策略并始终严格地执行？是否制定了连续一致的编码标准，并且通过诸如代码走查等加以保证？是否有完整的测试制度？是否具有明确的性能优化和软件安全性保障过程？是否在整个生命周期贯彻了严格的版本管理、配置管理、发布管理和软件维护退役管理措施？这些实实在在的问题，是需要耐心与细心地用具体实践细节来回答的。当一个团队对于这些问题都给出了明确而一致的回答并且用行动来执行的时候，他们就是一个专业的、具有核心竞争力的团队。而当一个个体开发者能够对这些问题具备正确的观念，并且通过施加自己的影响力促进团队向正确的方向前进的时候，他就是一个具有核心竞争力的开发者。一个具有核心竞争力的团队和开发者，是可以不断进步的，是具备把握机遇的能力的；一旦时机合适，他们就完全有可能实现更大的目标。
十多年以前国内外软件界对工艺的问题并不重视。大部分人要么执迷于技术本身，指望某一天一个面向某某的技术能够一劳永逸的解决软件开发中的所有问题，要么就是把问题大而化之为“软件工程”，企图以指令性的方式，在宏观的层面上用管理取代工艺。在这两个方向上，程序员要么被视为可以充分放纵的孤胆英雄，要么被视为伟大编程技术最终出现之前不得不存在的过渡品，或者管理指令的机械的执行体，“人”的维度消失了。这种对于人和工艺细节的忽视也体现在技术著作方面。软件工程、面向对象、编程技巧和产品手册之类的著作汗牛充栋，而认真谈到软件工艺的书屈指可数。
直到20世纪90年代中期，随着一些软件产品的规模越来越大，微软率先认识到工艺问题的重要性，于是出版了诸如《代码大全》、《编写清晰的代码》等一系列探讨这一问题的著作。直到20世纪90年代末期，当整个工业界从面向对象和软件工程的幻影泡沫中走出来之后，才开始认真全面地审视软件工艺的问题，而且通过敏捷运动、把软件工艺的重要性和基本实践提到了一个令人瞩目的位置上。事实上，敏捷运动可以认为是软件工艺的复兴运动。此外，随着《代码大全2》、《软件工艺》、《代码阅读》、《程序员修炼之道》等经典作品的出版，在技术图书领域也陆续出现了一批专门探讨软件工艺的著作。这本《编程匠艺》也是这个领域中的一本佳作。
本书是一部全面讨论软件构造工艺实践的著作，从软件开发的计划到架构设计，从编码风格规范到软件缺陷的检测与管理，从程序员工具箱的配备到团队协作精神的塑造，这本书都给予了翔实、风趣而具有启发性的讨论。这些讨论，既有原则性、理论性一面，也有技术性的具体建议，对于团队领导者、高级开发者和每一个希望快速进步的程序员具有明确的指导意义。如果读者认同软件工艺的重要性，那么可以说这本书是帮助读者建构自己核心竞争力的一本难得的作品。特别值得一提的是，这本书中文版的翻译流畅自然，在很多地方都体现出译者的认真态度和翻译功力。对于一本翻译自英文的技术著作来说，这无疑是一个大大的加分。
当然，一本书的覆盖面和功效毕竟是有限的，核心竞争力的确立和建构归根到底是一个艰苦实践的过程，不同性格的人也一定有着不同的目标和方式。但是我相信，对于有心人来说，只要我们不断地探索和实践，都会获得自己的核心竞争力，做一个有准备的人，争取和等待机会的垂青，最终实现自己的人生目标。
读此书有感而发，借题发挥，是为评论。
译 者 序
作为从事软件开发的程序员，你肯定遇到过这样的情况：自认为完美的代码，在项目快要结束的时候，却总是会发现还有好多内容需要修改。更有甚者，由于人员的变动，那些他们遗留下来的“老代码”，作为时间留给程序员与项目组的最大遗产，却可能会成为项目组的灾难。
除了受制于人类自身的缺陷之外，还有由于组织而带来的问题，如客户需求不断变更、必须在有限的时间和预算之内完成项目，来自内部所谓“项目管理”的种种压力，等等。天哪，这些问题我们绝大部分人都赶上了。
列宁曾在监狱中写下了《怎么办？》，指导了俄国的十月革命。而在软件业，从一代宗师Frederick P. Brooks的《人月神话》开始，就在找“怎么办”这个“银弹”了。然而，“狼来了”在多次被喊出来后，已经很少有人相信了。我们必须承认，这些都是根本层面的问题，目前还不能得到解决。但是，本书的作者Pete Goodliffe认为，至少我们可以采取一些方式，减少一些开发上的痛苦。因为，除了开发，人生还有许多更为美好的事物在等着我们。我们这次也可以高喊“银弹来了”。没有最好，只有更好，谁知道这次不是真的呢？
著名国画大师齐白石在年轻的时候，曾经做过木匠。据说有一次他和师傅去给地主干活，在路上迎面走来另外一对木匠师徒。齐先生的师傅说，赶紧给别人让路。师徒俩站在路边，老师恭敬地目送那两人渐渐走远。齐白石不解，问师傅：同是木匠，你我师徒为什么要给他们让路。老师傅回头说：为什么？别人是做细活的，我们是做粗活的。
Pete Goodliffe在业界的年头快要超过好多人的年龄了，此君曾经涉猎多个领域、不同的编程语言以及多种架构，并且曾经在采用不相同流程的公司里从事开发。在本书中，他把多年压箱底的一些观念想法和技巧告诉了大家，这些都是时间与智慧的结合，相信无论是开发人员、项目经理甚至测试人员，都可以从中发现阿里巴巴开启金库的钥匙。
那么本书有什么特色呢？对于想了解内容的普通读者来说，本书至少有以下特点：
1．贴近实际 《编程匠艺——编写卓越的代码》是本书的书名，但也是作者的用心所在。人生有三个境界，最后一个就是“看山是山，看水是水”。这是废话吗？当然不是，作者对此给出了最好的解答。作为程序员，我们最喜欢争论不同工具、平台、方法之间的优劣。而作者却通过多年经验，力图告诉我们应该如何提高质量，并成为一名优秀的程序员。这些方法就像点石成金的手指，它们是方法论，而不是针对具体的工具或者平台的说教。我们现在所缺的，恰恰是这些能使自己更进一阶的手段，而不是那些特殊的技术细节。
2．内容丰富翔实 很少有一本书能涵盖如此多的领域，并且还如此扎实。作为一名程序员，我们可能永远无法达到完美。而需要处于一种持续不断地提高的状态，总会有更多的东西需要学习。那么下一步应该做什么呢？这里就有答案。
3．可作为“秘要心法” 本书不仅适合入门者，也适合需要提高的开发人员，以及那些想管理好所谓代码猴子的项目经理们。与《项目经理案头手册》一样，这本书也将成为每人的案头手册或者枕边书，可以作为应急或者提升的手段。如果以后碰到了问题，可以随时参阅相关的章节。
4．心态决定一切 这句话对吗？有了良好心态，不一定行，如果没有，肯定不行。我们常常羡慕于老外以四五十岁的年纪仍然能继续从事编程，为什么我们不行呢？可能不同的读者都会找到属于自己的答案！Pete Goodliffe具有宽阔的视野，扎实的基础，广泛的爱好，带有一种程序员应该具有的高雅和恬淡。这正是我们这个浮躁的时代中积极探索的一代程序员所不具备的。
最后禁不住要抱怨一下，作者Pete Goodliffe以他丰富的阅历和爱好，给译者带来了不小的麻烦，比如出于它对于音乐的爱好，所有章节的标题都来自英国的歌曲名称。为了理解上的直观，我们在翻译的过程中采取的是“信达雅”中的“雅”，以保证国内读者能很快切入主题。本书每章开始和行文的过程中，作者都引用了历史上或者现在社会中一些名人的名言，这给翻译增加了不少的难度，但是由于贴切精辟，这些名言也可称之为点睛之笔。尤为值得高兴的是，此君对我中华文化竟然也有一定的造诣，孔夫子和老子的哲理名言竟然多次出现，而且能够贴切地表达出这些圣人的思想对软件开发有哪些启示，这非常不简单，难为了作者，也着实难为了译者。从外国作者的笔下，让我们着实体会到了自己国家的文化源远流长。这从一个侧面也体现出东海西海，千圣一心。
此书给了我们一个快速成功进阶的好范例。我觉得它更像一个程序员的入门或者修行心法。从此入门，我们可以少走很多弯路。同时，我们也要争取像佛经中“般若波罗密”所讲的那样：大智慧到彼岸，最后连佛法也像渡河的筏子一样，成佛后立即丢弃。我更希望的是，看过此书的读者们，最后能够拍案而起，大声说：我可以了。
图书目录

第I篇 代码表面第一部分
第1章 善于防守——健壮代码的防御性编程技巧 3
1.1 向优秀的代码前进 4
1.2 设想：最坏的选择 4
1.3 什么是防御性编程 6
1.4 又大又坏的世界 8
1.5 防御性编程技巧 8
1.5.1 使用好的编码风格和合理的设计 9
1.5.2 不要仓促地编写代码 9
1.5.3 不要相信任何人 10
1.5.4 编码的目标是清晰，而不是简洁 10
1.5.5 不要让任何人做他们不该做的修补工作 11
1.5.6 编译时打开所有警告开关 11
1.5.7 使用静态分析工具 12
1.5.8 使用安全的数据结构 12
1.5.9 检查所有的返回值 13
1.5.10 审慎地处理内存（和其他宝贵的资源） 13
1.5.11 在声明位置初始化所有变量 14
1.5.12 尽可能推迟一些声明变量 14
1.5.13 使用标准语言工具 14
1.5.14 使用好的诊断信息日志工具 15
1.5.15 审慎地进行强制转换 15
1.5.16 细则 15
1.6 约束 16
1.6.1 约束的内容 17
1.6.2 移除约束 18
1.7 总结 20
1.8 另请参见 20
1.9 思考 21
1.9.1 深入思考 21
1.9.2 结合自己 22
第2章 精心布局——源代码的版面和样式 23
2.1 什么是关键 24
2.2 了解你的读者 25
2.3 什么是好的样式 26
2.4 使用括号 26
2.4.1 K&R括号风格 27
2.4.2 悬挂式的括号风格 27
2.4.3 缩进的括号风格 29
2.4.4 其他的括号风格 29
2.5 主宰一切的风格 30
2.6 内部风格（以及在哪里使用它们） 31
2.7 设立标准 33
2.8 正义的战争 35
2.9 总结 35
2.10 另请参见 37
2.11 思考 37
2.11.1 深入思考 37
2.11.2 结合自己 38
第3章 名正言顺——为有意义的事物起有意义的名称 39
3.1 为什么我们应该恰当地命名呢 41
3.2 我们对什么进行命名 41
3.3 名字游戏 42
3.3.1 描述性 42
3.3.2 技术上正确 42
3.3.3 符合语言习惯 43
3.3.4 恰当 43
3.4 具体细节 44
3.4.1 命名变量 44
3.4.2 命名函数 45
3.4.3 命名类型 46
3.4.4 命名名字空间 47
3.4.5 命名宏 48
3.4.6 命名文件 48
3.5 玫瑰不叫玫瑰 49
3.5.1 保持前后一致 50
3.5.2 利用上下文 51
3.5.3 使用对你有利的名称 51
3.6 总结 52
3.7 另请参见 53
3.8 思考 53
3.8.1 深入思考 54
3.8.2 结合自己 55
第4章 不言自明——编写“自文档化”代码的技巧 57
4.1 自文档化的代码 59
4.2 编写自文档化代码的技术 61
4.2.1 使用好的样式编写简单的代码 61
4.2.2 选择有意义的名称 62
4.2.3 分解为原子函数 62
4.2.4 选择描述性的类型 63
4.2.5 命名常量 63
4.2.6 强调重要的代码 64
4.2.7 分组相关信息 64
4.2.8 提供文件头 64
4.2.9 恰当地处理错误 65
4.2.10 编写有意义的注释 65
4.3 实用的自文档化方法 66
4.3.1 文学性编程 66
4.3.2 文档化工具 67
4.4 总结 69
4.5 另请参见 70
4.6 思考 71
4.6.1 深入思考 71
4.6.2 结合自己 72
第5章 随篇注释——如何编写代码注释 73
5.1 什么是代码注释 74
5.2 注释看上去是什么样的 75
5.3 多少注释是恰当的 75
5.4 注释中应该有些什么 76
5.4.1 解释为什么，而不是怎么样 76
5.4.2 不要描述代码 76
5.4.3 不要取代代码 76
5.4.4 确保注释有用 77
5.4.5 避免分心 78
5.5 实践 79
5.6 从审美的角度看注释 80
5.6.1 一致性 80
5.6.2 清晰的块注释 80
5.6.3 缩进的注释 81
5.6.4 行尾注释 81
5.6.5 帮助你阅读代码 81
5.6.6 选择一种维护成本较低的风格 82
5.6.7 分隔板 82
5.6.8 标志 83
5.6.9 文件头注释 83
5.7 使用注释 84
5.7.1 帮助你编写例行程序 84
5.7.2 错误修正通告 85
5.7.3 注释过时 85
5.7.4 维护和空洞无物的注释 86
5.8 总结 86
5.9 另请参见 87
5.10 思考 87
5.10.1 深入思考 88
5.10.2 结合自己 88
第6章 人非圣贤——处理不可避免的情况——代码中的错误情形 89
6.1 从何而来 90
6.2 错误报告机制 91
6.2.1 不报告 91
6.2.2 返回值 92
6.2.3 错误状态变量 93
6.2.4 异常 93
6.2.5 信号 95
6.3 检测错误 95
6.4 处理错误 96
6.4.1 何时处理错误 97
6.4.2 可能的反应 98
6.4.3 代码示例 100
6.5 使地狱浮现 104
6.6 管理错误 105
6.7 总结 106
6.8 另请参见 107
6.9 思考 107
6.9.1 深入思考 107
6.9.2 结合自己 108
第II篇 代码的神秘生命
第7章 欲善其事，先利其器——使用工具构建软件 111
7.1 什么是软件工具 112
7.2 为什么要在意工具 114
7.3 使工具发挥作用 115
7.3.1 了解它能做些什么 115
7.3.2 学习如何驾驭它 116
7.3.3 了解它适合什么任务 116
7.3.4 检查它是否可用 116
7.3.5 找到了解更多信息的途径 117
7.3.6 查明新版本何时出现 117
7.4 哪个工具 117
7.4.1 源代码编辑工具 118
7.4.2 代码构建工具 120
7.4.3 调试和调查工具 123
7.4.4 语言支持工具 124
7.4.5 其他工具 125
7.5 总结 126
7.6 另请参见 127
7.7 思考 128
7.7.1 深入思考 128
7.7.2 结合自己 128
第8章 测试时代——测试代码的魔术 129
8.1 反思现实 131
8.2 谁、是什么、何时以及为什么 132
8.2.1 我们为什么要测试 132
8.2.2 谁来进行测试 133
8.2.3 测试的内容有些什么 133
8.2.4 何时进行测试 134
8.3 测试并不难…… 135
8.4 测试的类型 138
8.5 选择单元测试用例 142
8.6 为测试而设计 144
8.7 看！不要用手！ 144
8.8 面对故障该怎么办 145
8.9 你能管理它吗 146
8.9.1 缺陷跟踪系统 147
8.9.2 bug审查 148
8.10 总结 149
8.11 另请参见 150
8.12 思考 150
8.12.1 深入思考 150
8.12.2 结合自己 151
第9章 寻找缺陷——调试：当事情进展得不顺利时该怎么办 153
9.1 生活的真相 154
9.2 bug的种类 155
9.2.1 从远处看 155
9.2.2 从近处看 156
9.2.3 从更近处看 158
9.3 消灭害虫 160
9.3.1 地下之路 161
9.3.2 地上之路 161
9.4 搜寻bug 162
9.4.1 编译时错误 162
9.4.2 运行时错误 164
9.5 如何修正缺陷 167
9.6 预防 169
9.7 除蜂剂、驱虫剂、捕蝇纸 169
9.7.1 调试器 169
9.7.2 内存访问校验器 170
9.7.3 系统调用跟踪 170
9.7.4 内核转储 170
9.7.5 日志 170
9.8 总结 171
9.9 另请参见 172
9.10 思考 173
9.10.1 深入思考 173
9.10.2 结合自己 173
第10章 代码构建——将源代码转换为可执行代码的过程 175
10.1 语言障碍 176
10.1.1 解释型语言 177
10.1.2 编译型语言 178
10.1.3 字节编译型语言 179
10.2 小题大做 179
10.3 构建软件版本 181
10.4 怎样才算是一个优秀的构建系统 184
10.4.1 简洁 184
10.4.2 一致 184
10.4.3 可重复和可靠 185
10.4.4 原子性 186
10.4.5 能够应付错误 187
10.5 技术细节 187
10.5.1 目标的选择 187
10.5.2 内务处理 189
10.5.3 依赖关系 189
10.5.4 自动构建 190
10.5.5 构建配置 191
10.5.6 递归地使用make 192
10.6 请发布我吧 192
10.7 构建大师是全能的吗 194
10.8 总结 195
10.9 另请参见 195
10.10 思考 196
10.10.1 深入思考 196
10.10.2 结合自己 196
第11章 追求速度——优化程序和编写高效的代码 199
11.1 优化是什么 200
11.2 是什么使代码不尽如人意 201
11.3 为什么不进行优化呢 202
备选方案 204
11.4 为什么要进行优化 205
11.5 优化的具体细节 206
11.5.1 证明你需要进行优化 206
11.5.2 找出运行得最慢的代码 207
11.5.3 测试代码 208
11.5.4 优化代码 209
11.5.5 优化之后 209
11.6 优化的技术 210
11.6.1 设计更改 210
11.6.2 代码更改 213
11.7 编写高效的代码 217
11.8 总结 219
11.9 另请参见 219
11.10 思考 220
11.10.1 深入思考 220
11.10.2 结合自己 221
第12章 不安全感综合症——编写安全的程序 223
12.1 危险 224
12.2 敌人 226
12.3 借口，都是借口 228
12.4 感到很脆弱 229
12.4.1 不安全的设计和体系结构 229
12.4.2 缓冲溢出 229
12.4.3 嵌入的查询字符串 230
12.4.4 竞争状况 231
12.4.5 整数溢出 231
12.5 防范措施 232
12.5.1 系统安装技术 233
12.5.2 软件设计技术 234
12.5.3 代码实现技术 235
12.5.4 规程技术 236
12.6 总结 236
12.7 另请参见 237
12.8 思考 238
12.8.1 深入思考 238
12.8.2 结合自己 238
第III篇 代码的形成过程
第13章 崇尚设计——如何创作出优秀的软件设计 241
13.1 边设计边编程 242
13.2 我们要设计什么 243
13.3 为什么这么忙乱 244
13.4 良好的软件设计 245
13.4.1 简洁 246
13.4.2 优雅 247
13.4.3 模块化 247
13.4.4 良好的接口 248
13.4.5 可扩展性 251
13.4.6 避免重复 251
13.4.7 可移植性 252
13.4.8 符合语言习惯 252
13.4.9 良好地文档化 253
13.5 如何设计代码 253
13.5.1 设计方法和过程 254
13.5.2 设计工具 255
13.6 总结 257
13.7 另请参见 258
13.8 思考 258
13.8.1 深入思考 258
13.8.2 结合自己 259
第14章 软件体系结构——奠定软件设计的基础 261
14.1 什么是软件体系结构 262
14.1.1 软件蓝图 262
14.1.2 视图 263
14.1.3 在何时和何处进行体系结构设计 264
14.1.4 用体系结构来做什么 265
14.1.5 关于组件和连接 266
14.2 什么是良好的体系结构 268
14.3 体系结构风格 269
14.3.1 没有体系结构 269
14.3.2 分层的体系结构 270
14.3.3 管道和过滤器体系结构 271
14.3.4 客户端/服务器体系结构 271
14.3.5 基于组件的体系结构 273
14.3.6 框架 274
14.4 总结 275
14.5 另请参见 276
14.6 思考 276
14.6.1 深入思考 276
14.6.2 结合自己 277
第15章 改良与革命——代码是如何成长的 279
15.1 软件腐烂 281
15.2 警告信号 282
15.3 代码是如何成长的 284
15.4 相信不可能之事 286
15.5 对此我们可以做些什么 287
15.5.1 编写新代码 287
15.5.2 维护现有代码 288
15.6 总结 290
15.7 另请参见 290
15.8 思考 291
15.8.1 深入思考 292
15.8.2 结合自己 292
第IV篇 “一群”程序员第一部分
第16章 代码猴子——培养正确的编程态度和方法 295
16.1 各种各样的猴子 296
16.1.1 卖力工作的程序员 297
16.1.2 代码猴子 298
16.1.3 权威 299
16.1.4 半权威 300
16.1.5 傲慢的天才 300
16.1.6 牛仔 302
16.1.7 规划者 302
16.1.8 老前辈 303
16.1.9 狂热者 304
16.1.10 单线条程序员 305
16.1.11 拖沓者 306
16.1.12 勉强的团队领导 306
16.1.13 你 307
16.2 理想的程序员 308
16.3 那么该怎么办 308
16.4 最愚蠢的人 309
16.5 总结 310
16.6 另请参见 310
16.7 行为表格 311
16.8 思考 312
16.8.1 深入思考 312
16.8.2 结合自己 312
第17章 团结就是力量——团队合作与个人程序员 315
17.1 我们的团队——概览 316
17.2 团队组织 318
17.2.1 管理方法 318
17.2.2 责任划分 318
17.2.3 组织和代码结构 320
17.3 团队合作工具 320
17.4 团队疾病 322
17.4.1 巴别塔 322
17.4.2 独裁制 324
17.4.3 民主制 325
17.4.4 卫星站 327
17.4.5 大峡谷 329
17.4.6 流沙 330
17.4.7 旅鼠 332
17.5 良好团队合作的个人技巧和特点 333
17.5.1 沟通 333
17.5.2 谦虚 334
17.5.3 处理冲突 334
17.5.4 学习和适应能力 335
17.5.5 了解你的不足之处 336
17.6 团队合作原则 336
17.6.1 集体代码所有制 336
17.6.2 尊重别人的代码 337
17.6.3 编码准则 337
17.6.4 定义成功 337
17.6.5 定义责任 338
17.6.6 避免倦怠 338
17.7 团队的生命周期 339
17.7.1 团队的创建 339
17.7.2 团队的成长 341
17.7.3 团队合作 342
17.7.4 团队结束 343
17.8 总结 345
17.9 另请参见 346
17.10 行为表格 347
17.11 思考 348
17.11.1 深入思考 348
17.11.2 结合自己 348
第18章 安全措施——源代码控制与自我控制 349
18.1 我们的责任 350
18.2 源代码控制 351
18.2.1 修订控制 352
18.2.2 访问控制 353
18.2.3 处理代码库 354
18.2.4 在代码树上创建分支 354
18.2.5 源代码控制简史 356
18.3 配置管理 356
18.4 备份 358
18.5 发布源代码 359
18.6 应该将源代码放在哪里 360
18.7 总结 361
18.8 另请参见 362
18.9 思考 363
18.9.1 深入思考 363
18.9.2 结合自己 363
第V篇 开发过程的组成部分第一部分
第19章 注意细节——编写软件规范 367
19.1 规范到底是什么 368
19.2 规范的类型 369
19.2.1 需求规范 371
19.2.2 功能规范 373
19.2.3 系统体系结构规范 373
19.2.4 用户界面规范 374
19.2.5 设计规范 374
19.2.6 测试规范 375
19.3 规范应当包含哪些内容 376
19.4 规范编写过程 379
19.5 我们为什么会不编写规范 381
19.6 总结 383
19.7 另请参见 383
19.8 思考 384
19.8.1 深入思考 384
19.8.2 结合自己 384
第20章 代码审查——执行代码审查 385
20.1 什么是代码审查 386
20.2 何时进行审查 387
20.2.1 是否要进行审查 388
20.2.2 审查哪些代码 389
20.3 执行代码审查 389
20.3.1 代码审查会议 390
20.3.2 集成审查 392
20.4 审查你的态度 393
20.4.1 作者的态度 393
20.4.2 审查人员的态度 394
20.5 完美的代码 395
20.6 代码审查之外 396
20.7 总结 397
20.8 另请参见 397
20.9 清单 398
20.10 思考 399
20.10.1 深入思考 399
20.10.2 结合自己 399
第21章 时间估计——软件时间范围估计的魔术 401
21.1 在黑暗中摸索 402
21.2 为什么估计这么困难？ 403
21.3 压力之下 405
21.4 实用的估计方法 406
21.5 计划游戏 409
21.6 坚持！ 412
21.7 总结 415
21.8 另请参见 415
21.9 思考 416
21.9.1 深入思考 416
21.9.2 结合自己 416
第VI篇 从高处鸟瞰
第22章 程序秘方——代码开发的方法和过程 419
22.1 编程风格 420
22.1.1 结构化编程 421
22.1.2 面向对象的程序设计 422
22.1.3 函数式编程 423
22.1.4 逻辑编程 424
22.2 烹饪方法：做什么与怎样做 424
22.3 开发过程 425
22.3.1 混乱 426
22.3.2 瀑布模型 427
22.2.3 SSADM和PRINCE 429
22.3.4 V模型 430
22.3.5 原型设计 430
22.3.6 迭代和增量开发 432
22.3.7 螺旋模型 432
22.3.8 敏捷的方法 433
22.3.9 其他开发过程 434
22.4 已经够了！ 435
22.5 选择一种过程 436
22.6 总结 437
22.7 另请参见 438
22.8 思考 438
22.8.1 深入思考 438
22.8.2 结合自己 439
第23章 编程领域大观——不同的编程分支 441
23.1 应用程序编程 442
23.1.1 塑装软件 443
23.1.2 定制应用程序 444
23.2 游戏编程 445
23.3 系统编程 446
23.4 嵌入式编程 447
23.5 分布式编程 450
23.6 网络应用程序编程 451
23.7 企业编程 453
23.8 数字编程 454
23.9 那又怎样 455
23.10 总结 456
23.11 另请参见 456
23.12 思考 457
23.12.1 深入思考 457
23.12.2 结合自己 457
第24章 下一步呢——结果好就一切都好 459
但下一步该做什么呢？ 460
答案和讨论 463
参考书目 559
索引 564
图书章节
第7章 欲善其事，先利其器——使用工具构建软件
任何胆敢使用超乎自己力量的装置，都会身陷危险。
——J.R.R.托尔金（J.R.R. Tolkien）
要想成为一位多产的艺人，你需要有一套顺手的工具。水暖工工具箱里的东西可以帮助他完成任何任务，要不然你就不会在下次家里的水龙头漏水时去叨唠他了。
只是拥有这些工具还不够，它们的质量也很重要。差劲的工具会让人对优秀的工匠感到失望。无论你的水暖工有多能干，如果压缩阀不好，也会到处都是水。
当然，是你对这些工具的使用使你成为一名杰出的工匠。工具本身什么也做不成。在电动工具出现之前，木匠们就已经能做出精美的家具了。工具相对而言是基础的，使用工具的技能才是创造精美物品的关键。 
编程也是同样的道理。要把工作做好，你需要得到一套适当工具的支持；这应该是一套让你充满信心的工具，你知道如何使用它们，对你所遇到的工作也非常适用。要创造出非凡的代码，不仅需要有技艺精湛的编程高手，还要有好用的工具和灵活运用这些工具的能力。
这是一个重要的问题。你使用工具的方式可以看出你是否能成为一名真正多产的程序员。在极端的情况下，这些工具可以提供决定你的项目成功与否的简化操作。软件工厂那不懈的前进步伐，要求你紧紧抓住任何可以帮助你编写更好的代码，以及更快和更可靠地编写代码的工具。
其他章节会包含一些涉及某种特定工具的内容。本章我们将把软件工具作为一个整体来讨论。编程是一项没有工具就无法进行的工作。我们日复一日地使用着工具，使用编译器就像使用开罐器一样自然，没有经过太多的思考。如果它运转正常，就没有任何问题，但是当它发生了故障（或者你需要开启一个奇形怪状的罐头）时，不管开罐器有多高档，你都会被卡住。一个简单便宜但是能用的开罐器要好过一个外表华丽构造复杂但是不能用的装置。