描述
开 本: 16开纸 张: 胶版纸包 装: 平装-胶订是否套装: 否国际标准书号ISBN: 9787121384356
√ 屹立 20 年影响力大作,成功案例数以千万计,凌驾于任何语言|框架|方法之上。
√ 面向未来重写全部内容,从程序员责任与职业发展,到灵活|易适配|可重用架构。
√ 53个核心话题|99个高能提示,阐明软件开发走向卓越之路及途中各种典型陷阱。
√ 编程界传奇人物云风操刀翻译,至理|奥义|案例|技巧之原著精微,无不掘至毫巅。
◎与“软件腐烂”做斗争
◎持续学习
◎避免知识重复的陷阱
◎写出有弹性、动态、适配性强的代码
◎驾驭基本工具的力量
◎避免依赖巧合编程
◎学习真正的需求
◎解决并发代码的底层问题
◎防范安全漏洞
◎建立务实程序员构成的团队
◎对你的工作和事业负责
◎无情而有效地做测试,包括基于特性的测试
◎组建务实的入门套件
◎取悦你的用户
《程序员修炼之道》之所以在全球范围内广泛传播,被一代代开发者奉为圭臬,盖因它可以创造出真正的价值:或编写出更好的软件,或探究出编程的本质,而所有收获均不依赖于特定语言、框架和方法。时隔20年的新版,经过全面的重新选材、组织和编写,覆盖哲学、方法、工具、设计、解耦、并发、重构、需求、团队等务实话题的*实践及重大陷阱,以及易于改造、复用的架构技术。本书极具洞察力与趣味性,适合从初学者到架构师的各阶层读者潜心研读或增广见闻。
序 XVII
新版前言 XXI
第一版前言 XV
提示1:关注你的技艺 XVII
如果你不关心怎么做好,为什么还要花时间去开发软件呢?
提示2:思考!思考你的工作 XVII
关掉辅助驾驶,由自己掌控,持续不断地评估所做的工作。
第1章 务实的哲学 1
1 人生是你的 2
提示3:你有权选择 3
人生是自己的。把握住人生,让它如你所愿。
2 我的源码被猫吃了 3
提示4:提供选择,别找借口 5
提供选择而不是去找理由。不要只说做不到;解释一下都能做些什么。
3 软件的熵 6
提示5:不要放任破窗 7
只要看到不好的设计、错误的决策、糟糕的代码,就赶紧去纠正。
4 石头做的汤和煮熟的青蛙 9
提示6:做推动变革的催化剂 10
你无法强迫人们去改变,但可以展示美好未来,并帮助他们参与创造。
提示7:牢记全景 10
不要过度沉浸于细枝末节,以免察觉不到周围正在发生的事情。
5 够好即可的软件 11
提示8:将质量要求视为需求问题 12
让用户参与对项目真实质量需求的确定。
6 知识组合 14
提示9:对知识组合做定期投资 16
养成学习的习惯。
提示10:批判性地分析你读到和听到的东西 18
不要受供应商、媒体炒作或教条的影响,根据自身和项目的实际情况来
分析信息。
7 交流! 20
提示11:英语就是另一门编程语言 20
将英语视作一门编程语言。写文档和编程一样要遵循 DRY 原则、ETC、
自动化等。
提示12:说什么和怎么说同样重要 23
如果无法有效交流,任何伟大的想法都是没有意义的。
提示13:把文档嵌进去,而不要栓在表面 24
与代码隔离的文档,很难保持正确并及时更新。
第2章 务实的方法 27
8 优秀设计的精髓 28
提示14:优秀的设计比糟糕的设计更容易变更 28
适合使用者的事物,都已经过良好设计。对代码来说,这意味着必须适应
变化。
9 DRY——邪恶的重复 30
提示15:DRY——不要重复自己 31
系统中的每一条知识,都必须有单一且无歧义的权威陈述。
提示16:让复用变得更容易 39
只要复用方便,人们就会去做。创建一个支持复用的环境。
10 正交性 40
提示17:消除不相关事物之间的影响 41
设计的组件,需要自成一体、独立自主,有单一的清晰定义的意图。
11 可逆性 48
提示18:不设最终决定 50
不要把决定刻在石头上,而要将其视为写在沙滩上的东西,时刻准备
应变。
提示19:放弃追逐时尚 50
尼尔·福特说过:“昨日之最佳实践,即明日之反模式。”要基于基本
原则去选择架构,而不应盲从于流行。
12 曳光弹 51
提示20:使用曳光弹找到目标 53
通过不断尝试并看清着弹点,曳光弹可确保你最终击中目标。
13 原型与便签 57
提示21:用原型学习 58
制作原型旨在学习经验,其价值不在于过程中产生的代码,而在于
得到的教训。
14 领域语言 60
提示22:靠近问题域编程 61
用问题领域的语言来做设计和编程。
15 估算 67
提示23:通过估算来避免意外 67
开始之前做估算,能提前发现潜在问题。
提示24:根据代码不断迭代进度表 72
利用实施过程中获得的经验来精细化项目的时间尺度。
第3章 基础工具 74
16 纯文本的威力 75
提示25:将知识用纯文本保存 76
纯文本不会过时。它能够让你的工作事半功倍,并能简化调试和测试
工作。
17 Shell游戏 79
提示26:发挥 Shell 命令的威力 80
当图形化界面无法胜任时,使用 Shell。
18 加强编辑能力 82
提示27:游刃有余地使用编辑器 82
既然编辑器是至关重要的工具,不妨了解一下如何用它更快更准确地
实现需求。
19 版本控制 85
提示28:永远使用版本控制 87
版本控制为你的工作创造了一个时间机器,可以用它重返过去。
20 调试 90
提示29:去解决问题,而不是责备 91
Bug 到底来自你的失误还是别人的失误真的不重要——它终究是你的
问题,需要你来修复。
提示30:不要恐慌 91
不管是对银河系搭车客,还是对开发者来说,都应这样。
提示31:修代码前先让代码在测试中失败 93
在你修 Bug 前,先创建一个聚焦于该 Bug 的测试。
提示32:读一下那些该死的出错信息 93
大多数异常都能告诉失败之物与失败之处。如果足够幸运,你甚至能
得到具体的参数值。
提示33:“select”没出问题 97
在操作系统或编译器中发现 Bug 非常罕见,甚至在第三方产品或库中
也是如此。Bug 大多出现在应用程序中。
提示34:不要假设,要证明 97
在真实环境中证实你的假设——要依赖真实的数据及边界条件。
21 文本处理 99
提示35:学习一门文本处理语言 99
既然每天都要花大量的时间与文本打交道,何不让计算机帮你分担一二?
22 工程日记 101
第4章 务实的偏执 103
提示36:你无法写出完美的软件 103
软件不可能是完美的。对于在所难免的错误,要保护代码和用户免受其
影响。
23 契约式设计 104
提示37:通过契约进行设计 107
代码是否不多不少刚好完成它宣称要做的事情,可以使用契约加以校验
和文档化。
24 死掉的程序不会说谎 113
提示38:尽早崩溃 114
彻底死掉的程序通常比有缺陷的程序造成的损害要小。
25 断言式编程 115
提示39:使用断言去预防不可能的事情 115
如果一件事情不可能发生,那么就用断言来确保其的确不会发生。断言
在校验你的假设,要使用断言在不确定的世界中将你的代码保护起来。
26 如何保持资源的平衡 119
提示40:有始有终 119
只要有可能,对资源进行分配的函数或对象就有责任去释放该资源。
提示41:在局部行动 122
将易变的变量维持在一个范围内,打开资源的过程要短暂且明显可见。
27 不要冲出前灯范围 127
提示42:小步前进——由始至终 127
永远小步前进,不断检查反馈,并且在推进前先做调整。
提示43:避免占卜 129
只在你能看到的范围内做计划。
第5章 宁弯不折 130
28 解耦 131
提示44:解耦代码让改变更容易 132
耦合使事物紧紧绑定在一起,以至于很难只改变其中之一。
提示45:只管命令不要询问 133
不要从对象中取出值,在加以变换后再塞回去,让对象自己来完成这些
工作。
提示46:不要链式调用方法 135
当访问某事物时,使用的点号不要超过一个。
提示47:避免全局数据 137
最好给每个方法增加一个额外的参数。
提示48:如果全局唯一非常重要,那么将它包装到API 中 137
……但是,仅限于你真的非常希望它是全局的。
29 在现实世界中抛球杂耍 139
30 变换式编程 149
提示49:编程讲的是代码,而程序谈的是数据 151
所有的程序都在变换数据——将输入转换为输出。开始用变换式方法来
设计吧!
提示50:不要囤积状态,传递下去 156
不要把数据保持在函数或模块的内部,拿出来传递下去。
31 继承税 162
提示51:不要付继承税 165
考虑一下能更好满足需求的替代方案,比如接口、委托或mixin。
提示52:尽量用接口来表达多态 167
无需继承引入的耦合,接口就能明确描述多态性。
提示53:用委托提供服务:“有一个”胜过“是一个” 167
不要从服务中继承,应该包含服务。
提示54:利用 mixin 共享功能 169
mixin 不必承担继承税就可以给类添加功能,而与接口结合可以让
多态不再令人痛苦。
32 配置 170
提示55:使用外部配置参数化应用程序 170
如果代码对一些在应用程序发布后还有可能改变的值有所依赖,那么
就在应用外部维护这些值。
第6章 并发 174
33 打破时域耦合 175
提示56:通过分析工作流来提高并发性 176
利用用户工作流中的并发性。
34 共享状态是不正确的状态 179
提示57:共享状态是不正确的状态 180
共享状态会带来无穷的麻烦,而且往往只有重启才能解决。
提示58:随机故障通常是并发问题 186
或许时间和上下文的变化能暴露并发Bug,但并发Bug无法始终保持
一致,也很难重现。
35 角色与进程 187
提示59:用角色实现并发性时不必共享状态 188
使用角色来管理并发状态,可以避免显式的同步。
36 黑板 193
提示60:使用黑板来协调工作流 195
使用黑板来协调不相关的事实和代理人,能同时保持参与者之间的
独立性和孤立性。
第7章 当你编码时 198
37 听从蜥蜴脑 199
提示61:倾听你内心的蜥蜴 201
当编程举步维艰时,其实是潜意识在告诉你有什么地方不对劲。
38 巧合式编程 204
提示62:不要依赖巧合编程 207
只能依赖可靠的事物。注意偶然事件的复杂性,不要混淆快乐的巧合
与有目的的计划。
39 算法速度 210
提示63:评估算法的级别 214
在开始编程前,对这件事情大概会花多长时间要有概念。
提示64:对估算做测试 214
针对算法的数学分析无法说明所有问题,尝试在目标环境中测试一下
执行代码的耗时。
40 重构 216
提示65:尽早重构,经常重构 219
像除草和翻整花园那样,只要有需要就对代码进行重新编写、修订
和架构,以便找到问题的根源并加以修复。
41 为编码测试 220
提示66:测试与找 Bug 无关 221
测试是观察代码的一个视角,可以从中得到针对设计、接口和耦合度的
反馈。
提示67:测试是代码的第一个用户 222
用测试的反馈来引导工作。
提示68:既非自上而下,也不自下而上,基于端对端构建 225
创建一小块端到端的功能,从中获悉问题之所在。
提示69:为测试做设计 228
写下代码之前先从测试角度思考。
提示70:要对软件做4
序
我还记得 Dave 和 Andy 第一次在推特上谈论这本书的新版的那一刻——这可是一条大新闻。在编程社区,所见之处都是对这条大新闻兴奋的回应,人们的期待塞满了我的信息流。二十年过去了,《程序员修炼之道》这本书的地位不逊于当年。
承载这样一段历史的一本书,能引起这样的反响,本身就说明了很多问题。为了写这篇序,我有幸在尚未出版前阅读了本书,读后我就明白了它为什么会引起这么大的轰动。本来,一本书被冠以技术图书之名,给人的印象应该是不太好的。因为技术图书常常令人生畏——充斥着深奥的词汇、晦涩的术语和令人费解的例子,不经意间就会让你觉得自己很愚蠢。而且,作者越有经验,就越容易忘记初学者在学习新概念时的感觉。
Dave 和 Andy 的作品,却能透出那种只有刚刚学到这些课程的人才会有的兴奋感,尽管他们已有几十年的编程经验,却战胜了写出这种感觉的挑战。他们不会居高临下地指指点点,不会假定你是个专家,甚至不认为你已读过本书第一版,仅仅把你当成想要变得更好的程序员而已。他们不惜用整本书的篇幅来帮助你达到目标,一步一个脚印。
公平地说,在这方面,他们在过往已经成绩斐然。最初的本书第一版,包含了许多具体的例子、新想法和实用的技巧,可以帮助你修炼编程所需的“肌肉”和“大脑”,这些东西到今天仍然适用。但是,这次在新版图书中,又有了两项改进。
第一项显而易见:删除了一些较老的引用内容和过时的例子,增补了大量新鲜、现代的内容。循环不变式或构建机这样的例子已经看不到了。Dave 和 Andy 保留了第一版书中的重要内容,以确保相应的课程依然有效,而且读者也不必受旧示例的干扰。对于像 DRY(不要重复自己)这样的旧思想,上面的灰尘已被掸去,并且涂上了一层新油漆——这样做真的让其熠熠生辉。
而第二项,才是这次新版图书发布真正令人兴奋的地方。在写完本书第一版后,他们有机会思考自己想要说什么,想让读者获得什么,以及读者是如何接受这些信息的。他们得到了这些课程的反馈,也看到了读者在哪里被卡住、有什么需要改进,以及哪些内容被误解。在这本书通过全世界程序员的双手和心灵传播的二十年间,Dave 和 Andy 研究了这些回应,并且形成了新的想法和理念。
他们认识到自主权的重要性,并且意识到,相比大多数其他专业人员,开发者或许更能为自己做主。他们以简单而深刻的启示开始这本书:“人生是你的。”这唤起了我们自己的力量,它就蕴含在我们的代码库、工作和职业生涯中。这也为本书的其他内容定下了基调——它不仅仅是又一本充满代码示例的技术图书。
这本书必定会在摆满各种技术图书的书架上脱颖而出,因为它理解身为一名程序员到底意味着什么。编程关涉诸事——尽量减少未来的痛苦,让队友更轻松,做错事情后能够重新振作起来,养成良好的习惯,以及理解工具集。编程只是程序员世界的一部分,而这本书探索了整个世界。
我在思考编码之旅上花了很多时间。我不是从小就开始接触编程的,大学里也没学过编程课。可以说,我的青少年时光并没有花在“摆弄”科技上,直到二十来岁的时候才进入了编程的世界,因而亟须想明白一件事情:成为一名程序员意味着什么。编程社区与我曾经身处的其他社区非常不同。其独特之处在于,人们无不醉心于学习和实践,这既令人生畏,又让人耳目一新。
这对我来说,真像进入一个全新的世界。就算去到一个新城镇,也有必要了解邻居、挑选杂货店、找到最好的咖啡店。我花了一段时间来了解地形,找到了最有效的路线,避开了交通最繁忙的街道,并且知道了什么时候交通可能会出问题。等到天气变化,我又要去置办应季的新衣。
来到一个新城镇的头几周,甚至是头几个月,可能会很害怕。如果有一个已经在这里住了一段时间的邻居,而且他知识渊博又友好,那不是再好不过的事情吗?谁能带你四处参观,谁能领你去那些咖啡店?当然是一个在当地待了足够长时间的,了解当地文化、当地脉搏的人。这样你不仅有家的感觉,还能成为一个同样有贡献的成员。Dave 和 Andy 就是这样的邻居。
一个准新人,更容易对成为程序员的过程,而不是对编程的行为不知所措。因此,必须对整个心态做一次切换——改变习惯、行为和期望。仅仅知道如何编程,并不会让你成为一名更好的程序员,在这个过程中必须经历有意识和深思熟虑的实践。好在现在有了这本书,可以有效地指导你成为更好的程序员。
但不要搞错了——这本书不会告诉你编程应该是怎样的,它并没有使用那种哲学或审判的方式,它只是简单、明了地告诉你,什么是务实的程序员——他们如何操作、如何处理代码。作者让你自己决定是否想成为其中的一员。如果你觉得不适合,也没有人会怪罪你。但如果你决定成为其中的一员,作者就是你的友好邻居,会陪伴左右、为你指路。
Saron Yitbarek
CodeNewbie 创始人及 CEO
Command Line Heroes 主办者
新版前言
在20世纪90年代,我们在与一些项目存在问题的公司合作时,发现总是在对每个人说同样的话:也许你应该在发布之前先测试一下。为什么代码只能在 Mary 的机器上构建?为什么没有人问一下用户呢?
为了节省与新客户打交道的时间,我们开始做笔记。这些笔记最终变成了《程序员修炼之道》这本书。令人惊讶的是,这本书似乎引起了大家的共鸣,在过去的二十年间,这本书一直很受欢迎。
但是二十年对于软件领域来说已经过了好几代。如果一个开发者从 1999 年直接穿越到今天的团队中,面对这个陌生的新世界一定会备感挣扎。但20世纪90年代的世界对今天的开发者来说同样陌生。书中所引用的 CORBA、CASE 工具,以及索引、循环这些东西,放在今天,充其量不过略显古雅有趣,而更多的会给人带来困扰。
与此同时,二十年对常识没有丝毫影响。技术可能改变了,但人没有。实践和方法中的闪光点,在今天看来光芒依旧。在这些方面,本书保鲜如初。
所以,当我们要出版这本二十周年纪念版的时候,必须做出抉择——是回顾和更新前一版中引用的技术后就大功告成,还是充分借鉴这平添的二十年丰富经验,重新审视前一版所推崇的实践背后的种种假设。
最终,我们两者都做了。
因此,这本书有点像忒修斯之船 。书中大约三分之一的主题是全新的,而其余的大部分都被部分或全部重写了。我们的目的是,让内容变得更清晰、更贴切,并在某种程度上不受时间的影响。
我们做了一些艰难的决定。删除了参考资料附录,这样做既因为它无法持续更新,也因为当你有此需要时很容易就能搜索获得。我们重新组织了与并发有关的主题,这是因为考虑到当前有着大量的并行硬件,却缺乏处理并行的好方法。我们还添加了一些内容来反映不断变化的认知和环境,从我们帮助发起的敏捷运动,到对函数式编程语境的日益接受,再到对隐私和安全性方面日益增长的需求。
然而有趣的是,我们之间关于版本内容的争论比写第一个版本时要少得多。重要的东西更容易辨别,这已是我们的共识。
无论如何,这本书最后就是这个样子了,请享用吧。你也许可以从中吸取一些新的做法,也许会觉得我们建议的某些东西是错的,不妨把它们都带到你的工作中去,然后给我们反馈。
但是,最重要的是,记住过程要开心。
【这本书是如何组织的】
这本书是许多短小主题的合集。每一个主题都针对特定的话题而独立成章。你会发现大量的交叉引用,这有助于把各个主题连贯起来。你可以以任意次序随意阅读这些主题——这不是一本需要从头到尾阅读的书。
偶尔你会看到一个写有提示n的框起来的标签块(比如位于第XVII页的提示1:关注你的技艺)。这些提示不仅是文中的重点,在我们眼里也是一条条生命——我们每天都赖以为生。
我们已尽可能适时地在书中加入了练习和挑战。练习通常有相对简单的答案,而挑战则更加开放。为了让你理解我们的思维方式,在附录里我们列出了这些练习的答案,但是拥有唯一正确答案的问题并不多。挑战或许能用于高级编程课程中的小组讨论,或许能作为论文写作的基础。
本书还有一个简短的参考文献,列出了我们明确引用的图书和文章。
【名字有什么含义】
“我用一个词,”矮胖子相当傲慢地说,“总是同我想要说的恰如其分的,既不重,也不轻。”
—— 路易斯·卡罗《爱丽丝镜中奇遇》
在整本书中,你会发现各种各样的行话——要么原本是完好的英语单词,却被曲解为技术词,要么是一些可怕的合成词,由那些对语言充满怨恨的计算机科学家赋予其意义。当我们第一次使用这些行话时,会尝试定义它们,或者至少对其含义给出解释。当然,肯定还有漏网之鱼,而且像对象和关系型数据库这种已被广泛使用的,再下一次定义就有点画蛇添足了。如果你遇到一个以前没见过的术语,请不要跳过它,不妨花点时间去查一下,可以在网上查,也可以在计算机科学的课本上查。如果有机会还可以给我们发邮件投诉,这样我们就可以在本书下一版中增加一个定义。
既然话已至此,我们决定报复一下计算机科学家。有时候,明明有一些非常好的术语,对某个概念表达得很好,但我们却决定不使用这些术语。为什么?因为现有的术语通常局限于特定的问题领域,或者特定的开发阶段。而本书的基本哲学之一就是,我们推荐的大多数技术都是通用的:例如模块化,它就能同时适用于代码、设计、文档和团队组织。当某个传统术语被拿来在更广泛的场景下使用时,却会造成困惑——我们似乎无法摆脱该术语从最初就开始背负的历史包袱。当这种情况发生时,我们只好发明自己的术语,助纣为虐地让语言继续堕落。
【第二版鸣谢】
在过去的二十年里,有成千上万关于编程的有趣对话曾让我们开心不已,其中不乏在会议、课程,甚至是飞机上与人们的偶遇。每一次经历,都会加深我们对开发过程的理解,并为此版本的更新添砖加瓦。感谢所有人(而且,当我们犯错误的时候,请继续提醒)。
感谢本书 Beta 测试过程的参与者,是你们的问题和评论,帮助我们把事情解释得更清楚。
在进行 Beta 测试之前,我们曾与一些人分享过本书。感谢 VM (Vicky) Brasseur、 Jeff Langr、 Kim Shrier 给予的详细评论,感谢 José
这样的赞美一直不绝于耳:通过撰写一本书来推动整个行业,是 Andy 和 Dave 用《程序员修炼之道:从小工到专家》完成的一大壮举,无人可以超越。然而,有时两次闪电的确会击中同一个地方,这部名著的再版即为明证。其令人震撼的内容更新,足以确保自身在未来二十年里继续雄踞“精选软件开发图书”榜单之首,此可谓实至名归。
—— VM (Vicky) Brasseur
瞻博网络开源战略总监
如果想让自己的软件既领先于时代又易于维护,就在手边摆放一本《程序员修炼之道:通向务实的*境界(第2版)》。本书充满实用建议,有技术方面的,也有专业方面的,无不能让你和你的项目受益多年。
—— Andrea Goulet
Corgibytes 公司 CEO
LegacyCode.Rocks 创始人
可以说,《程序员修炼之道》完全改变了我的职业轨迹,为我指明了软件领域的成功方向。正是这本书,开阔了我的视野,让我意识到自己不仅仅是庞大机器上的一枚齿轮,有朝一日也能藉由修炼成为匠师。它是我生命中*重要的一本书。
—— Obie Fernandez
《Rails 之道》作者
初读此书的读者,在见识到那个软件开发实践的新世界时,立刻充满期待。而*版图书,对塑造这样一个迷人的现代世界,的确厥功至伟。现在,*版的读者将有机会在新版中重温旧梦,再次接受洞察力和实践智慧的洗礼,而《程序员修炼之道》当初正因此被奉为圭臬。更重要的是,经由两位专家亲手组织与更新的再版图书,业已因富含新知而重焕青春。
—— David A. Black
《Ruby程序员修炼之道》作者
旧版的《程序员修炼之道》一直驻留在我的书架上。从很久以前它改变我作为一个程序员的工作方式那一刻起,我读了又读。在这个全新的版本中,一切似乎都已改变,而一切又仿佛还在那里。虽然我们现在换用 iPad 阅读新版,其代码示例也改由现代编程语言实现——但是蕴藏其中的概念、思想和态度,亘古不变且通行宇宙。二十年过去,这本书的价值从未折损。现在乃至将来的开发人员,都有机会从 Andy 和 Dave 的深刻洞见中获益,正如当年的我一样,这让人备感欣慰。
—— Sandy Mamoli
敏捷教练
How Self-Selection Lets People Excel 作者
二十年前,《程序员修炼之道》的*版彻底颠覆了我的技术生涯。这次的新版,也将对你有此影响。
—— Mike Cohn
《Scrum敏捷软件开发》
《敏捷估计与规划》
《用户故事与敏捷方法》作者
评论
还没有评论。