全部博文(465)
分类: Delphi
2012-11-16 15:33:13
Clean Code(评注版)
[美]Robert C. Martin(罗伯特.马丁) 著
韩磊 评注
ISBN 978-7-121-15505-5
2012年2月出版
定价:79.00元
16开
496页
内 容 简 介
软件质量,不但依赖架构及项目管理,而且与代码质量紧密相关。这一点,无论是敏捷开发流派还是传统开发流派,都不得不承认。本书提出一种观念:代码质量与其整洁度成正比。干净的代码,既在质量上较为可靠,也为后期维护、升级奠定了良好的基础。本书作者给出了一系列行之有效的整洁代码操作实践。这些实践在本书中体现为一条条规则(或称“启示”),并辅以来自现实项目的正、反两方面的范例。只要遵循这些规则,就能写出干净的代码,从而有效提升代码的质量
本书适合致力于改善代码质量的程序员及技术经理阅读。本书介绍的规则均来自作者多年的实践经验,涵盖从命名到重构的多个方面,虽为一“家”之言,然诚有借鉴意义。
本书是Clean Code一书的评注版,力邀国内资深专家执笔,在英文原著的基础上增加了中文点评和注释,旨在融合二者之长,既保留经典的原创文字与味道,又以先行者的学研心得与实践感悟,对读者的阅读和学习加以点拨,指明捷径。
作者简介
Robert C. Martin
软件工程领域的大师级人物,设计模式和敏捷开发运动的主要倡导者之一,曾经担任C++ Report杂志主编多年。他的Agile Software Development: Principles, Patterns, and Practices一书曾荣获Jolt大奖。
评注者简介
韩磊
技术管理者和作译者,互联网专家。2001年创办CoDelphi.com中文开发在线网站;2003年加入CSDN,历任网络总监、副总经理、CSDN网站和《程序员》杂志总编辑等职;2010年加入21世纪传媒,现任21世纪新媒体副总经理、CTO。拥有美国Borland公司“Delphi产品专家”及“微软最有价值专家”称号。译有《C#编程风格》(Elements of C# Style)、《梦断代码》(Dreaming in Code)、《代码整洁之道》(Clean Code),合著有《网络媒体教程》,合译有《Beginning C# Objects:对象到代码》。
评注者序
代码猴子与童子军军规
年3月,我在SD West 2007技术大会上聆听了Robert C. Martin(鲍勃大叔)的主题演讲Craftsmanship and the Problem of Productivity: Secrets for Going Fast without Making a Mess。一身休闲打扮的鲍勃大叔,以一曲嘲笑低水平编码者的Code Monkey(代码猴子)开场。
是的,我们就是一群代码猴子,上蹿下跳,自以为领略了编程的真谛。可惜,当我们抓着几个酸桃子,得意洋洋坐到树枝上时,却对自己造成的混乱熟视无睹。那堆“可以运行”的乱麻程序,就在我们的眼皮底下慢慢腐坏。
从听到那场以TDD为主题的演讲之后,我就一直关注鲍勃大叔,还有他在TDD和整洁代码方面的言论。
这本书名为Clean Code,乃Object Mentor(鲍勃大叔开办的技术咨询和培训公司)一干大牛在编程方面的经验累积。按鲍勃大叔的话来说,就是“Object Mentor整洁代码派”的说明。
正如Coplien在序中所言,宏大建筑中最细小的部分,如关不紧的门、有点儿没铺平的地板,甚至是凌乱的桌面,都会将整个大局的魅力毁灭殆尽——这就是整洁代码之所系。Coplien列举了许多谚语以证明整洁的价值,中国也有“修身、齐家、治国、平天下”之语。整洁代码的重要性毋庸置疑,问题是如何写出真正整洁的代码。
本书既是整洁代码的定义,亦是如何写出整洁代码的指南。鲍勃大叔认为,“写整洁的代码,需要遵循大量的小技巧,贯彻刻苦习得的‘整洁感’。这种‘代码感’就是关键所在……它不仅让我们看到代码的优劣,还予我们以借戒规之力化劣为优的攻略。”作者阐述了在命名、函数、注释、代码格式、对象和数据结构、错误处理、边界问题、单元测试、类、系统、并发编程等方面如何做到整洁的经验与最佳实践。长期遵照这些经验编写代码,所谓“代码感”也就自然而然滋生出来。更有价值的部分是鲍勃大叔本人对3个Java项目的剖析与改进过程的实操记录。通过多达3章的重构记录,鲍勃大叔充分地证明了童子军军规在编程领域同样适用:离开时要比发现时更整洁。为了向读者呈现代码的原始状态,我对这部分代码及本书其他部分的绝大多数代码注释都不做评注。如果读者有任何疑问,可通过邮件与我沟通(cleancode.cn@gmail. com)。
接触开发技术10多年以来,特别是从事IT技术媒体工作6年以来,我见过许多对于代码整洁性缺乏足够重视的开发者。不过分地说,这是职业素养与基本功的双重缺陷。为本书做评注,实在也是因为希望在这方面看到开发者的重视度和实际应用能力的提升。
在本书的结束语中,鲍勃大叔提到别人给他的一条腕带,上面的字样是“Test Obsessed”(沉迷测试)。鲍勃大叔“发现自己无法取下腕带。不仅是因为腕带很紧,而且那也是条精神上的紧箍咒……它一直提醒我,我做了写出整洁代码的承诺。”有了这条腕带,代码猴子成了模范童子军。我想,每位开发者都需要这样一条腕带吧!
韩磊
目 录
Chapter 1: Clean Code(新增评注47条) 1
There Will Be Code 2
Bad Code 3
The Total Cost of Owning a Mess 5
The Grand Redesign in the Sky 6
Attitude 6
The Primal Conundrum 7
The Art of Clean Code? 8
What Is Clean Code? 9
Schools of Thought 15
We Are Authors 17
The Boy Scout Rule 18
Prequel and Principles 18
Conclusion 18
Bibliography 19
Chapter 2: Meaningful Names(新增评注19条) 21
Introduction 21
Use Intention-Revealing Names 22
Avoid Disinformation 24
Make Meaningful Distinctions 25
Use Pronounceable Names 26
Use Searchable Names 27
Avoid Encodings 28
Hungarian Notation 28
Member Prefixes 29
Interfaces and Implementations 29
Avoid Mental Mapping 30
Class Names 30
Method Names 30
Don’t Be Cute 31
Pick One Word per Concept 32
Don’t Pun 32
Use Solution Domain Names 33
Use Problem Domain Names 33
Add Meaningful Context 33
Don’t Add Gratuitous Context 35
Final Words 36
Chapter 3: Functions(新增评注25条) 39
Small! 42
Blocks and Indenting 43
Do One Thing 44
Sections within Functions 45
One Level of Abstraction per Function 45
Reading Code from Top to Bottom:The Stepdown Rule 46
Switch Statements 46
Use Descriptive Names 48
Function Arguments 49
Common Monadic Forms 50
Flag Arguments 50
Dyadic Functions 51
Triads 52
Argument Objects 52
Argument Lists 52
Verbs and Keywords 53
Have No Side Effects 53
Output Arguments 54
Command Query Separation 55
Prefer Exceptions to Returning Error Codes 56
Extract Try/Catch Blocks 57
Error Handling Is One Thing 57
The Error.java Dependency Magnet 57
Don’t Repeat Yourself 58
Structured Programming 59
How Do You Write Functions Like This? 59
Conclusion 60
SetupTeardownIncluder 60
Bibliography 62
Chapter 4: Comments(新增评注18条) 65
Comments Do Not Make Up for Bad Code 67
Explain Yourself in Code 68
Good Comments 68
Legal Comments 68
Informative Comments 69
Explanation of Intent 69
Clarification 70
Warning of Consequences 71
TODO Comments 71
Amplification 72
Javadocs in Public APIs 72
Bad Comments 72
Mumbling 73
Redundant Comments 73
Misleading Comments 76
Mandated Comments 76
Journal Comments 77
Noise Comments 78
Scary Noise 80
Don’t Use a Comment When You Can Use a Function or
a Variable 80
Position Markers 80
Closing Brace Comments 81
Attributions and Bylines 82
Commented-Out Code 82
HTML Comments 83
Nonlocal Information 83
Too Much Information 84
Inobvious Connection 84
Function Headers 84
Javadocs in Nonpublic Code 85
Example 85
Bibliography 88
Chapter 5: Formatting(新增评注13条) 89
The Purpose of Formatting 90
Vertical Formatting 90
The Newspaper Metaphor 91
Vertical Openness Between Concepts 92
Vertical Density 93
Vertical Distance 94
Vertical Ordering 99
Horizontal Formatting 99
Horizontal Openness and Density 100
Horizontal Alignment 101
Indentation 103
Dummy Scopes 104
Team Rules 105
Uncle Bob’s Formatting Rules 106
Chapter 6: Objects and Data Structures(新增评注12条) 109
Data Abstraction 110
Data/Object Anti-Symmetry 111
The Law of Demeter 114
Train Wrecks 115
Hybrids 116
Hiding Structure 116
Data Transfer Objects 117
Active Record 118
Conclusion 118
Bibliography 119
Chapter 7: Error Handling(新增评注7条) 121
Use Exceptions Rather Than Return Codes 122
Write Your Try-Catch-Finally Statement First 123
Use Unchecked Exceptions 125
Provide Context with Exceptions 126
Define Exception Classes in Terms of a Caller’s Needs 126
Define the Normal Flow 128
Don’t Return Null 129
Don’t Pass Null 130
Conclusion 131
Bibliography 131
Chapter 8: Boundaries(新增评注6条) 133
Using Third-Party Code 134
Exploring and Learning Boundaries 136
Learning log4j 137
Learning Tests Are Better Than Free 138
Using Code That Does Not Yet Exist 139
Clean Boundaries 140
Bibliography 141
Chapter 9: Unit Tests(新增评注13条) 143
The Three Laws of TDD 144
Keeping Tests Clean 145
Tests Enable the -ilities 146
Clean Tests 147
Domain-Specific Testing Language 150
A Dual Standard 150
One Assert per Test 153
Single Concept per Test 154
F.I.R.S.T. 155
Conclusion 156
Bibliography 156
Chapter 10: Classes(新增评注12条) 157
Class Organization 158
Encapsulation 158
Classes Should Be Small! 158
The Single Responsibility Principle 161
Cohesion 162
Maintaining Cohesion Results in Many Small Classes 163
Organizing for Change 169
Isolating from Change 172
Bibliography 174
Chapter 11: Systems(新增评注10条) 175
How Would You Build a City? 176
Separate Constructing a System from Using It 176
Separation of Main 178
Factories 178
Dependency Injection 179
Scaling Up 180
Cross-Cutting Concerns 183
Java Proxies 184
Pure Java AOP Frameworks 186
AspectJ Aspects 189
Test Drive the System Architecture 190
Optimize Decision Making 191
Use Standards Wisely, When They Add Demonstrable Value 191
Systems Need Domain-Specific Languages 191
Conclusion 192
Bibliography 192
Chapter 12: Emergence(新增评注5条) 195
Getting Clean via Emergent Design 195
Simple Design Rule 1: Runs All the Tests 196
Simple Design Rules 2–4: Refactoring 196
No Duplication 197
Expressive 199
Minimal Classes and Methods 200
Conclusion 201
Bibliography 201
Chapter 13: Concurrency(新增评注15条) 203
Why Concurrency? 204
Myths and Misconceptions 205
Challenges 206
Concurrency Defense Principles 207
Single Responsibility Principle 207
Corollary: Limit the Scope of Data 207
Corollary: Use Copies of Data 208
Corollary: Threads Should Be as Independent as Possible 208
Know Your Library 209
Thread-Safe Collections 209
Know Your Execution Models 210
Producer-Consumer 210
Readers-Writers 211
Dining Philosophers 211
Beware Dependencies Between Synchronized Methods 212
Keep Synchronized Sections Small 212
Writing Correct Shut-Down Code Is Hard 212
Testing Threaded Code 213
Treat Spurious Failures as Candidate Threading Issues 214
Get Your Nonthreaded Code Working First 214
Make Your Threaded Code Pluggable 214
Make Your Threaded Code Tunable 215
Run with More Threads Than Processors 215
Run on Different Platforms 215
Instrument Your Code to Try and Force Failures 215
Hand-Coded 216
Automated 217
Conclusion 218
Bibliography 219
Chapter 14: Successive Refinement(新增评注18条) 221
Args Implementation 223
How Did I Do This? 228
Args: The Rough Draft 229
So I Stopped 240
On Incrementalism 241
String Arguments 243
Conclusion 280
关于第15章、第16章和第17章 281
Chapter 15: JUnit Internals 283
The JUnit Framework 284
Conclusion 297
Chapter 16: Refactoring SerialDate 299
First, Make It Work 300
Then Make It Right 302
Conclusion 316
Bibliography 316
Chapter 17: Smells and Heuristics 317
Comments 318
C1: Inappropriate Information 318
C2: Obsolete Comment 318
C3: Redundant Comment 318
C4: Poorly Written Comment 319
C5: Commented-Out Code 319
Environment 319
E1: Build Requires More Than One Step 319
E2: Tests Require More Than One Step 319
Functions 320
F1: Too Many Arguments 320
F2: Output Arguments 320
F3: Flag Arguments 320
F4: Dead Function 320
General 320
G1: Multiple Languages in One Source File 320
G2: Obvious Behavior Is Unimplemented 320
G3: Incorrect Behavior at the Boundaries 321
G4: Overridden Safeties 321
G5: Duplication 321
G6: Code at Wrong Level of Abstraction 322
G7: Base Classes Depending on Their Derivatives 323
G8: Too Much Information 324
G9: Dead Code 324
G10: Vertical Separation 324
G11: Inconsistency 324
G12: Clutter 325
G13: Artificial Coupling 325
G14: Feature Envy 325
G15: Selector Arguments 326
G16: Obscured Intent 327
G17: Misplaced Responsibility 328
G18: Inappropriate Static 328
G19: Use Explanatory Variables 329
G20: Function Names Should Say What They Do 329
G21: Understand the Algorithm 330
G22: Make Logical Dependencies Physical 330
G23: Prefer Polymorphism to If/Else or Switch/Case 331
G24: Follow Standard Conventions 332
G25: Replace Magic Numbers with Named Constants 332
G26: Be Precise 333
G27: Structure over Convention 333
G28: Encapsulate Conditionals 334
G29: Avoid Negative Conditionals 334
G30: Functions Should Do One Thing 334
G31: Hidden Temporal Couplings 335
G32: Don’t Be Arbitrary 336
G33: Encapsulate Boundary Conditions 336
G34: Functions Should Descend Only One Level of Abstraction 337
G35: Keep Configurable Data at High Levels 338
G36: Avoid Transitive Navigation 339
Java 339
J1: Avoid Long Import Lists by Using Wildcards 339
J2: Don’t Inherit Constants 340
J3: Constants versus Enums 341
Names 342
N1: Choose Descriptive Names 342
N2: Choose Names at the Appropriate Level of Abstraction 343
N3: Use Standard Nomenclature Where Possible 344
N4: Unambiguous Names 344
N5: Use Long Names for Long Scopes 345
N6: Avoid Encodings 345
N7: Names Should Describe Side-Effects 345
Tests 346
T1: Insufficient Tests 346
T2: Use a Coverage Tool 346
T3: Don’t Skip Trivial Tests 346
T4: An Ignored Test Is a Question about an Ambiguity 346
T5: Test Boundary Conditions 346
T6: Exhaustively Test Near Bugs 346
T7: Patterns of Failure Are Revealing 347
T8: Test Coverage Patterns Can Be Revealing 347
T9: Tests Should Be Fast 347
Conclusion 347
Bibliography 347
Appendix A: Concurrency II 349
Client/Server Example 349
The Server 349
Adding Threading 351
Server Observations 351
Conclusion 353
Possible Paths of Execution 353
Number of Paths 354
Digging Deeper 355
Conclusion 358
Knowing Your Library 359
Executor Framework 359
Nonblocking Solutions 359
Nonthread-Safe Classes 361
Dependencies Between Methods Can Break Concurrent Code 362
Tolerate the Failure 363
Client-Based Locking 363
Server-Based Locking 365
Increasing Throughput 366
Single-Thread Calculation of Throughput 367
Multithread Calculation of Throughput 367
Deadlock 368
Mutual Exclusion 369
Lock & Wait 369
No Preemption 369
Circular Wait 370
Breaking Mutual Exclusion 370
Breaking Lock & Wait 370
Breaking Preemption 371
Breaking Circular Wait 371
Testing Multithreaded Code 372
Tool Support for Testing Thread-Based Code 374
Conclusion 375
Tutorial: Full Code Examples 375
Client/Server Nonthreaded 375
Client/Server Using Threads 379
Appendix B: org.jfree.date.SerialDate 381
Appendix C: Cross References of Heuristics 441
Epilogue 445
Index 447