第1章 整洁代码 1
1.1要有代码 2
1.2糟糕的代码 2
1.3混乱的代价 3
1.3.1华丽新设计 4
1.3.2态度 4
1.3.3迷题 5
1.3.4整洁代码的艺术 5
1.3.5什么是整洁代码 6
1.4思想流派 10
1.5我们是作者 11
1.6童子军军规 12
1.7前传与原则 12
1.8小结 12
1.9文献 13
第2章 有意义的命名 15
2.1介绍 15
2.2名副其实 16
2.3避免误导 17
2.4做有意义的区分 18
2.5使用读得出来的名称 19
2.6使用可搜索的名称 20
2.7避免使用编码 21
2.7.1匈牙利语标记法 21
2.7.2成员前缀 21
2.7.3接口和实现 22
2.8避免思维映射 22
2.9类名 23
2.10方法名 23
2.11别扮可爱 23
2.12每个概念对应一个词 24
2.13别用双关语 24
2.14使用解决方案领域名称 25
2.15 使用源自所涉问题领域的名称 25
2.16添加有意义的语境 25
2.17不要添加没用的语境 27
2.18最后的话 27
第3章 函数 29
3.1短小 32
3.2只做一件事 33
3.3每个函数一个抽象层级 34
3.4 switch语句 35
3.5使用描述性的名称 36
3.6函数参数 37
3.6.1一元函数的普遍形式 38
3.6.2标识参数 38
3.6.3二元函数 38
3.6.4三元函数 39
3.6.5参数对象 39
3.6.6参数列表 40
3.6.7动词与关键字 40
3.7无副作用 40
3.8分隔指令与询问 42
3.9使用异常替代返回错误码 42
3.9.1抽离Try/Catch代码块 43
3.9.2错误处理就是一件事 44
3.9.3 Error.java依赖磁铁 44
3.10别重复自己 44
3.11结构化编程 45
3.12如何写出这样的函数 45
3.13小结 45
3.14 SetupTeardownIncluder程序 46
3.15 文献 48
第4章 注释 49
4.1注释不能美化糟糕的代码 50
4.2用代码来阐述 51
4.3好注释 51
4.3.1法律信息 51
4.3.2提供信息的注释 51
4.3.3对意图的解释 52
4.3.4阐释 53
4.3.5警示 53
4.3.6 TODO注释 54
4.3.7放大 54
4.3.8公共API中的Javadoc 55
4.4坏注释 55
4.4.1喃喃自语 55
4.4.2多余的注释 56
4.4.3误导性注释 58
4.4.4循规式注释 58
4.4.5日志式注释 59
4.4.6废话注释 59
4.4.7可怕的废话 61
4.4.8能用函数或变量时就别用注释 62
4.4.9位置标记 62
4.4.10括号后面的注释 62
4.4.11归属与署名 63
4.4.12注释掉的代码 63
4.4.13 HTML注释 64
4.4.14非本地信息 64
4.4.15 信息过多 65
4.4.16不明显的联系 65
4.4.17函数头 66
4.4.18非公共代码中的Javadoc 66
4.4.19范例 66
4.5文献 69
第5章 格式 71
5.1格式的目的 72
5.2垂直格式 72
5.2.1向报纸学习 73
5.2.2概念间垂直方向上的区隔 73
5.2.3垂直方向上的靠近 74
5.2.4垂直距离 75
5.2.5垂直顺序 79
5.3横向格式 79
5.3.1水平方向上的区隔与靠近 80
5.3.2水平对齐 81
5.3.3缩进 82
5.3.4空范围 84
5.4团队规则 84
5.5鲍勃大叔的格式规则 85
第6章 对象和数据结构 87
6.1数据抽象 87
6.2数据、对象的反对称性 89
6.3得墨忒耳律 91
6.3.1火车失事 91
6.3.2 混杂 92
6.3.3隐藏结构 92
6.4数据传送对象 93
6.5小结 94
6.6文献 94
第7章 错误处理 95
7.1使用异常而非返回码 96
7.2先写Try-Catch-Finally语句 97
7.3使用不可控异常 98
7.4给出异常发生的环境说明 99
7.5依调用者需要定义异常类 99
7.6定义常规流程 100
7.7别返回null值 101
7.8别传递null值 102
7.9小结 103
7.10文献 104
第8章 边界 105
8.1使用第三方代码 106
8.2浏览和学习边界 107
8.3学习log4j 108
8.4学习性测试的好处不只是免费 110
8.5使用尚不存在的代码 110
8.6整洁的边界 111
8.7文献 112
第9章 单元测试 113
9.1 TDD三定律 114
9.2保持测试整洁 115
9.3整洁的测试 116
9.3.1面向特定领域的测试语言 118
9.3.2双重标准 119
9.4每个测试一个断言 121
9.5 F.I.R.S.T 122
9.6小结 123
9.7文献 124
第10章类 125
10.1类的组织 126
10.2类应该短小 126
10.2.1单一权责原则 128
10.2.2内聚 129
10.2.3保持内聚性就会得到许多短小的类 130
10.3为了修改而组织 136
10.4文献 139
第11章 系统 141
11.1如何建造一个城市 142
11.2将系统的构造与使用分开 142
11.2.1分解main 143
11.2.2工厂 143
11.2.3依赖注入 144
11.3扩容 145
11.4 Java代理 148
11.5纯Java AOP框架 150
11.6 AspectJ的方面 152
11.7测试驱动系统架构 153
11.8优化决策 154
11.9明智使用添加了可论证价值的标准 154
11.10系统需要领域特定语言 154
11.11小结 155
1112文献 155
第12章 迭进 157
12.1通过迭进设计达到整洁目的 157
12.2简单设计规则1:运行所有测试 158
12.3简单设计规则2~4:重构 158
12.4不可重复 159
12.5表达力 161
12.6尽可能少的类和方法 162
12.7小结 162
12.8文献 162
第13章 并发编程 163
13.1为什么要并发 164
13.2挑战 165
13.3并发防御原则 166
13.3.1单一权责原则 166
13.3.2推论:限制数据作用域 166
13.3.3推论:使用数据复本 167
13.3.4推论:线程应尽可能地独立 167
13.4了解Java库 167
13.5了解执行模型 168
13.5.1生产者-消费者模型 169
13.5.2读者-作者模型 169
13.5.3宴席哲学家 169
13.6警惕同步方法之间的依赖 169
13.7保持同步区域微小 170
13.8很难编写正确的关闭代码 170
13.9测试线程代码 171
13.9.1将伪失败看作可能的线程问题 171
13.9.2先使非线程代码可工作 171
13.9.3编写可插拔的线程代码 172
13.9.4编写可调整的线程代码 172
13.9.5运行多于处理器数量的线程 172
13.9.6在不同平台上运行 172
13.9.7装置试错代码 173
13.9.8硬编码 173
13.9.9自动化 174
13.10小结 175
13.11文献 175
第14章 逐步改进 176
14.1 Args的实现 177
14.2 Args:草稿 183
14.2.1所以我暂停了 195
14.2.2渐进 195
14.3字符串参数 197
14.4小结 234
第15章JUnit内幕 235
15.1 JUnit框架 236
15.2小结 249
第16章 重构SerialDate 251
16.1首先让它能工作 252
16.2让它做对 254
16.3小结 266
16.4文献 267
第17章 味道与启发 269
17.1注释 270
17.2环境 271
17.3函数 271
17.4一般性问题 272
17.5 Java 288
17.6名称 291
17.7测试 294
17.8小结 295
17.9文献 296
附录A并发编程Ⅱ 297
A.1客户端/服务器的例子 297
A.1.1服务器 297
A.1.2添加线程代码 298
A.1.3观察服务器端 299
A.1.4小结 301
A.2执行的可能路径 301
A.2.1路径数量 302
A.2.2深入挖掘 303
A.2.3小结 305
A.3了解类库 305
A.3.1 Executor框架 305
A.3.2非锁定的解决方案 306
A.3.3非线程安全类 307
A.4方法之间的依赖可能破坏并发代码 308
A.4.1容忍错误 309
A.4.2基于客户代码的锁定 309
A.4.3基于服务端的锁定 311
A.5提升吞吐量 312
A.5.1单线程条件下的吞吐量 313
A.5.2多线程条件下的吞吐量 313
A.6死锁 314
A.6.1互斥 315
A.6.2上锁及等待 315
A.6.3无抢先机制 315
A.6.4循环等待 315
A.6.5不互斥 316
A.6.6不上锁及等待 316
A.6.7满足抢先机制 317
A.6.8不做循环等待 317
A.7测试多线程代码 317
A.8测试线程代码的工具支持 320
A.9小结 320
A.10教程:完整代码范例 321
A.10.1客户端/服务器非线程代码 321
A.10.2使用线程的客户端/服务器代码 324
附录B org.jfree.date.SerialDate 327
结束语 389