Clean Code. Whew! 1253
I’ve been working on this book for several years now. After a flurry of effort (you might have noticed I’ve been quiet lately) I’m very pleased to say that I’m done with the writing and am preparing the manuscript for production. See The Prentice Hall Listing

Table of Contents
Clean Code 1
There Will Be Code 1
Bad Code 2
The Total Cost of Owning a Mess. 3
Schools of Thought. 11
We are Authors. 12
The Boy Scout Rule 13
Prequel and Principles 14
Conclusion 14
Bibliography 15
Meaningful Names by Tim Ottinger 17
Introduction 17
Use Intention-revealing Names 17
Avoid Disinformation 19
Make Meaningful Distinctions 20
Use Pronounceable Names 21
Use Searchable Names 22
Avoid Encodings 23
Avoid Mental Mapping 24
Class Names 25
Method Names 25
Don't Be Cute 25
Pick One Word Per Concept 26
Don't Pun 26
Use Solution Domain Names 27
Use Problem Domain Names 27
Add Meaningful Context 27
Don't add Gratuitous Context 29
Final Words ... 30
Functions 31
Small! 34
Do one thing. 35
One level of abstraction per function. 36
Switch Statements. 37
Use descriptive names. 39
Function Arguments. 39
Have no side-effects. 43
Command Query Separation 44
Prefer exceptions to returning error codes. 45
Don't Repeat Yourself. 47
Structured Programming 48
How do you write functions like this? 48
Conclusion 49
SetupTeardownIncluder 49
Bibliography 52
Comments 53
Comments do not make up for bad code. 55
Explain yourself in code. 55
Good Comments 55
Bad Comments 59
Example 71
Bibliography 74
Formatting 75
The Purpose of Formatting 76
Vertical Formatting 76
Horizontal Formatting 84
Team Rules 89
Uncle Bob's Formatting Rules. 90
Objects and Data Structures 93
Data Abstraction 93
Data/Object anti-symmetry. 95
The Law of Demeter 97
Data Transfer Objects 99
Conclusion 101
Bibliography 101
Error Handling by Michael Feathers 103
Use Exceptions Rather than Return Codes 103
Write Your Try-Catch-Finally Statement First 105
Use Unchecked Exceptions 106
Provide Context with Exceptions 107
Define Exception Classes In Terms of a Caller's Needs. 107
Define the Normal Flow 109
Don't Return Null 110
Don't Pass Null 111
Conclusion 112
Bibliography 112
Boundaries by James Grenning 113
Bibliography 119
Unit Tests 121
The Three Laws of TDD 122
Keeping Tests Clean 123
Clean Tests 124
One Assert per Test 129
F.I.R.S.T. 132
Conclusion 132
Bibliography 133
Classes 135
Class Organization 135
Classes should be Small! 136
Organizing for Change 146
Bibliography 150
Systems By Dean Wampler 151
How would you build a city? 151
Separate constructing a system from using it 152
Scaling Up 155
Java Proxies 158
Pure Java AOP Frameworks 160
AspectJ Aspects 163
Test-drive the system architecture 164
Optimize decision making 165
Use standards wisely, when they add demonstrable value 165
Systems need Domain-Specific Languages 166
Conclusion 166
Bibliography 167
Emergence By Jeff Langr 169
Getting Clean via Emergent Design 169
Simple Design Rule 1: Runs all the tests 170
Simple Design Rules 2-4: Refactoring 170
No Duplication 170
Expressive 173
Minimal Classes and Methods 174
Conclusion 174
Bibliography 174
Concurrency by Brett Schuchert 175
Why Concurrency? 176
Challenges 177
Concurrency Defense Principles 178
Know Your Library 180
Know Your Execution Models 181
Beware Dependencies between Syncrhonized Methods 182
Keep Synchronized Sections Small 183
Writing Correct Shut-Down Code is Hard 183
Testing Threaded Code 184
Conclusion 188
Bibliography 189
Successive Refinement 191
Args Implementation 192
Args: the rough draft. 198
String Arguments 212
Conclusion 246
JUnit Internals 249
Conclusion 262
Refactoring SerialDate 263
Conclusion 280
Bibliography 281
Smells and Heuristics 283
Comments 283
Environment 284
Functions 285
General 285
Java 304
Names 306
Tests 310
Conclusion 311
Bibliography 312
Concurrency II by Brett Schuchert 313
Client/Server Example 313
Possible Paths of Execution 317
Knowing Your Library 322
Dependencies between methods can break concurrent code 325
Increasing Throughput 329
Deadlock 331
Testing Multi-Threaded Code 335
Tool Support for Testing Thread-Based Code 337
Conclusion 338
Tutorial: Full Code Examples 339
org.jfree.date.SerialDate 345
Cross References of Heuristics 406
Clean Code. Whew! 1253
I’ve been working on this book for several years now. After a flurry of effort (you might have noticed I’ve been quiet lately) I’m very pleased to say that I’m done with the writing and am preparing the manuscript for production. See The Prentice Hall Listing

Table of Contents
Clean Code 1
There Will Be Code 1
Bad Code 2
The Total Cost of Owning a Mess. 3
Schools of Thought. 11
We are Authors. 12
The Boy Scout Rule 13
Prequel and Principles 14
Conclusion 14
Bibliography 15
Meaningful Names by Tim Ottinger 17
Introduction 17
Use Intention-revealing Names 17
Avoid Disinformation 19
Make Meaningful Distinctions 20
Use Pronounceable Names 21
Use Searchable Names 22
Avoid Encodings 23
Avoid Mental Mapping 24
Class Names 25
Method Names 25
Don't Be Cute 25
Pick One Word Per Concept 26
Don't Pun 26
Use Solution Domain Names 27
Use Problem Domain Names 27
Add Meaningful Context 27
Don't add Gratuitous Context 29
Final Words ... 30
Functions 31
Small! 34
Do one thing. 35
One level of abstraction per function. 36
Switch Statements. 37
Use descriptive names. 39
Function Arguments. 39
Have no side-effects. 43
Command Query Separation 44
Prefer exceptions to returning error codes. 45
Don't Repeat Yourself. 47
Structured Programming 48
How do you write functions like this? 48
Conclusion 49
SetupTeardownIncluder 49
Bibliography 52
Comments 53
Comments do not make up for bad code. 55
Explain yourself in code. 55
Good Comments 55
Bad Comments 59
Example 71
Bibliography 74
Formatting 75
The Purpose of Formatting 76
Vertical Formatting 76
Horizontal Formatting 84
Team Rules 89
Uncle Bob's Formatting Rules. 90
Objects and Data Structures 93
Data Abstraction 93
Data/Object anti-symmetry. 95
The Law of Demeter 97
Data Transfer Objects 99
Conclusion 101
Bibliography 101
Error Handling by Michael Feathers 103
Use Exceptions Rather than Return Codes 103
Write Your Try-Catch-Finally Statement First 105
Use Unchecked Exceptions 106
Provide Context with Exceptions 107
Define Exception Classes In Terms of a Caller's Needs. 107
Define the Normal Flow 109
Don't Return Null 110
Don't Pass Null 111
Conclusion 112
Bibliography 112
Boundaries by James Grenning 113
Bibliography 119
Unit Tests 121
The Three Laws of TDD 122
Keeping Tests Clean 123
Clean Tests 124
One Assert per Test 129
F.I.R.S.T. 132
Conclusion 132
Bibliography 133
Classes 135
Class Organization 135
Classes should be Small! 136
Organizing for Change 146
Bibliography 150
Systems By Dean Wampler 151
How would you build a city? 151
Separate constructing a system from using it 152
Scaling Up 155
Java Proxies 158
Pure Java AOP Frameworks 160
AspectJ Aspects 163
Test-drive the system architecture 164
Optimize decision making 165
Use standards wisely, when they add demonstrable value 165
Systems need Domain-Specific Languages 166
Conclusion 166
Bibliography 167
Emergence By Jeff Langr 169
Getting Clean via Emergent Design 169
Simple Design Rule 1: Runs all the tests 170
Simple Design Rules 2-4: Refactoring 170
No Duplication 170
Expressive 173
Minimal Classes and Methods 174
Conclusion 174
Bibliography 174
Concurrency by Brett Schuchert 175
Why Concurrency? 176
Challenges 177
Concurrency Defense Principles 178
Know Your Library 180
Know Your Execution Models 181
Beware Dependencies between Syncrhonized Methods 182
Keep Synchronized Sections Small 183
Writing Correct Shut-Down Code is Hard 183
Testing Threaded Code 184
Conclusion 188
Bibliography 189
Successive Refinement 191
Args Implementation 192
Args: the rough draft. 198
String Arguments 212
Conclusion 246
JUnit Internals 249
Conclusion 262
Refactoring SerialDate 263
Conclusion 280
Bibliography 281
Smells and Heuristics 283
Comments 283
Environment 284
Functions 285
General 285
Java 304
Names 306
Tests 310
Conclusion 311
Bibliography 312
Concurrency II by Brett Schuchert 313
Client/Server Example 313
Possible Paths of Execution 317
Knowing Your Library 322
Dependencies between methods can break concurrent code 325
Increasing Throughput 329
Deadlock 331
Testing Multi-Threaded Code 335
Tool Support for Testing Thread-Based Code 337
Conclusion 338
Tutorial: Full Code Examples 339
org.jfree.date.SerialDate 345
Cross References of Heuristics 406
Business software is Messy and Ugly. 71
I was at a client recently. They are a successful startup who have gone through a huge growth spurt. Their software grew rapidly, through a significant hack-and-slash program. Now they have a mess, and it is slowing them way down. Defects are high. Unintended consequences of change are high. Productivity is low.
I spent two days advising them how to adopt TDD and Clean Code techniques to improve their code-base and their situation. We discussed strategies for gradual clean up, and the notion that big refactoring projects and big redesign projects have a high risk of failure. We talked about ways to clean things up over time, while incrementally insinuating tests into the existing code base.
During the sessions they told me of a software manager who is famed for having said:
“There’s a clean way to do this, and a quick-and-dirty way to do this. I want you to do it the quick-and-dirty way.”
The attitude engendered by this statement has spread throughout the company and has become a significant part of their culture. If hack-and-slash is what management wants, then that’s what they get! I spent a long time with these folks countering that attitude and trying to engender an attitude of craftsmanship and professionalism.
The developers responded to my message with enthusiasm. They want to do a good job (of course!) They just didn’t know they were authorized to do good work. They thought they had to make messes. But I told them that the only way to get things done quickly, and keep getting things done quickly, is to create the cleanest code they can, to work as well as possible, and keep the quality very high. I told them that quick-and-dirty is an oxymoron. Dirty always means slow.
On the last day of my visit the infamous manager (now the CTO) stopped into our conference room. We talked over the issues. He was constantly trying to find a quick way out. He was manipulative and cajoling. “What if we did this?” or “What if we did that?” He’d set up straw man after straw man, trying to convince his folks that there was a time and place for good code, but this was not it.
I wanted to hit him.
Then he made the dumbest, most profoundly irresponsible statement I’ve (all too often) heard come out of a CTOs mouth. He said:
“Business software is messy and ugly.”
No, it’s not! The rules can be complicated, arbitrary, and ad-hoc; but the code does not need to be messy and ugly. Indeed, the more arbitrary, complex, and ad-hoc the business rules are, the cleaner the code needs to be. You cannot manage the mess of the rules if they are contained by another mess! The only way to get a handle on the messy rules is to express them in the cleanest and clearest code you can.
In the end, he backed down. At least while I was there. But I have no doubt he’ll continue his manipulations. I hope the developers have the will to resist.
One of the developers asked the question point blank: “What do you do when your managers tell you to make a mess?” I responded: “You don’t take it. Behave like a doctor who’s hospital administrator has just told him that hand-washing is too expensive, and he should stop doing it.”
Active Record vs Objects 100
Active Record is a well known data persistence pattern. It has been adopted by Rails, Hibernate, and many other ORM tools. It has proven it’s usefulness over and over again. And yet I have a philosophical problem with it.
public class Employee extends ActiveRecord {
private String name;
private String address;
...
}
We should be able to fetch a given employee from the database by using a call like:
Employee bob = Employee.findByName("Bob Martin");
We should also be able to modify that employee and save it as follows:
bob.setName("Robert C. Martin");
bob.save();
In short, every column of the Employee table becomes a field of the Employee class. There are static methods (or some magical reflection) on the ActiveRecord class that allow you to find instances. There are also methods that provide CRUD functions.
Even shorter: There is a 1:1 correspondence between tables and classes, columns and fields. (Or very nearly so).
It is this 1:1 correspondence that bothers me. Indeed, it bothers me about all ORM tools. Why? Because this mapping presumes that tables and objects are isomorphic.
The Difference between Objects and Data Structures
From the beginning of OO we learned that the data in an object should be hidden, and the public interface should be methods. In other words: objects export behavior, not data. An object has hidden data and exposed behavior.
Data structures, on the other hand, have exposed data, and no behavior. In languages like C++ and C# the struct keyword is used to describe a data structure with public fields. If there are any methods, they are typically navigational. They don’t contain business rules.
Thus, data structures and objects are diametrically opposed. They are virtual opposites. One exposes behavior and hides data, the other exposes data and has no behavior. But that’s not the only thing that is opposite about them.
Algorithms that deal with objects have the luxury of not needing to know the kind of object they are dealing with. The old example: shape.draw(); makes the point. The caller has no idea what kind of shape is being drawn. Indeed, if I add new types of shapes, the algorithms that call draw() are not aware of the change, and do not need to be rebuilt, retested, or redeployed. In short, algorithms that employ objects are immune to the addition of new types.
By the same token, if I add new methods to the shape class, then all derivatives of shape must be modified. So objects are not immune to the addition of new functions.
Now consider an algorithm that uses a data structure.
switch(s.type) {
case SQUARE: Shape.drawSquare((Square)s); break;
case CIRCLE: Shape.drawCircle((Circle)s); break;
}We usually sneer at code like this because it is not OO. But that disparagement might be a bit over-confident. Consider what happens if we add a new set of functions, such as Shape.eraseXXX(). None of the existing code is effected. Indeed, it does not need to be recompiled, retested, or redeployed. Algorithms that use data structures are immune to the addition of new functions.
By the same token if I add a new type of shape, I must find every algorithm and add the new shape to the corresponding switch statement. So algorithms that employ data structures are not immune to the addition of new types.
Again, note the almost diametrical opposition. Objects and Data structures convey nearly opposite immunities and vulnerabilities.
Good designers uses this opposition to construct systems that are appropriately immune to the various forces that impinge upon them. Those portions of the system that are likely to be subject to new types, should be oriented around objects. On the other hand, any part of the system that is likely to need new functions ought to be oriented around data structures. Indeed, much of good design is about how to mix and match the different vulnerabilities and immunities of the different styles.
Active Record Confusion
The problem I have with Active Record is that it creates confusion about these two very different styles of programming. A database table is a data structure. It has exposed data and no behavior. But an Active Record appears to be an object. It has “hidden” data, and exposed behavior. I put the word “hidden” in quotes because the data is, in fact, not hidden. Almost all ActiveRecord derivatives export the database columns through accessors and mutators. Indeed, the Active Record is meant to be used like a data structure.
On the other hand, many people put business rule methods in their Active Record classes; which makes them appear to be objects. This leads to a dilemma. On which side of the line does the Active Record really fall? Is it an object? Or is it a data structure?
This dilemma is the basis for the oft-cited impedance mismatch between relational databases and object oriented languages. Tables are data structures, not classes. Objects are encapsulated behavior, not database rows.
At this point you might be saying: “So what Uncle Bob? Active Record works great. So what’s the problem if I mix data structures and objects?” Good question.
Missed Opportunity
The problem is that Active Records are data structures. Putting business rule methods in them doesn’t turn them into true objects. In the end, the algorithms that employ Active Records are vulnerable to changes in schema, and changes in type. They are not immune to changes in type, the way algorithms that use objects are.
You can prove this to yourself by realizing how difficult it is to implement an polymorphic hierarchy in a relational database. It’s not impossible of course, but every trick for doing it is a hack. The end result is that few database schemae, and therefore few uses of Active Record, employ the kind of polymorphism that conveys the immunity of changes to type.
So applications built around ActiveRecord are applications built around data structures. And applications that are built around data structures are procedural—they are not object oriented. The opportunity we miss when we structure our applications around Active Record is the opportunity to use object oriented design.
No, I haven’t gone off the deep end.
I am not recommending against the use of Active Record. As I said in the first part of this blog I think the pattern is very useful. What I am advocating is a separation between the application and Active Record.
Active Record belongs in the layer that separates the database from the application. It makes a very convenient halfway-house between the hard data structures of database tables, and the behavior exposing objects in the application.
Applications should be designed and structured around objects, not data structures. Those objects should expose business behaviors, and hide any vestige of the database. The fact that we have Employee tables in the database, does not mean that we must have Employee classes in the application proper. We may have Active Records that hold Employee rows in the database interface layer, but by the time that information gets to the application, it may be in very different kinds of objects.
Conclusion
So, in the end, I am not against the use of Active Record. I just don’t want Active Record to be the organizing principle of the application. It makes a fine transport mechanism between the database and the application; but I don’t want the application knowing about Active Records. I want the application oriented around objects that expose behavior and hide data. I generally want the application immune to type changes; and I want to structure the application so that new features can be added by adding new types. (See: The Open Closed Principle)
Architecture is a Second Order Effect 61
We often argue that in order to achieve flexibility, maintainability, and reusability, it is important to have a good software architecture. This is certainly true. Without a well ordered architecture, software systems become masses of tangled modules and code. However, the effect of architecture on the ‘ilities is secondary to the effect that a good, fast, suite of tests has.
Why don’t we clean our code? When we see an ugly mass of code that we know is going to cause of problems, our first reaction is “This needs to be cleaned up.” Our second reaction is: “If I touch this code I’ll be spending the next two weeks trying to get it to work again.” We don’t clean code because we are afraid we’ll break it.
In this way bad code hooks itself into our systems and refuses to go away. Nothing stops clean code from going bad, but once it’s bad, we seldom have the time, energy, or nerve to clean it. In that sense, bad code is permanent.
What if you had a button? If you push this button a little light instantly turns red or green. Green means your system works. Red means it’s broken. If you had a button like this, you could make small changes to the system, and prove that they didn’t break anything. If you saw a batch of tangled messy code, you could start to clean it. You’d simply make a tiny improvement and then push the button. If the light was green you’d make the next tiny change, and the next, and the next.
I have a button like that! It’s called a test suite. I can run it any time I like, and within seconds it tells me, with very high certainty, that my system works.
Of course, to be effective, that test suite has to cover all the code in the system. And, indeed, that’s what I have. My code coverage tools tell me that 89% of the 45,000 lines in my system are covered by my test suite. (89% is pretty good number given that my coverage tool counts un-executable lines like interfaces.)
Can I be absolutely sure that the green light means that the system works? Certainly not. But given the coverage of my test suite, I am reasonably sure that the changes I make are not introducing any bugs. And that reasonable surety is enough for me to be fearless about making changes.
This fearlessness is something that needs to be experienced to understand. I feel no reluctance at all about cleaning up the code in my system. I frequently take whole classes and restructure them. I change the names of classes, variables, and functions on a whim. I extract super-classes and derivatives any time I like.
In short, the test suite makes it easy to make changes to my code. It makes my code flexible and easy to maintain.
So does my architecture of course. The design and structure of my system is very easy to deal with, and allows me to make changes without undue impact. The reason my architecture is so friendly, is that I’ve been fearless about changing it. And that’s because I have a test suite that runs in seconds, and that I trust!
So the clean architecture of my system is a result of on-going efforts supported by the test suite. I can keep the architecture clean and relevant because I have tests. I can improve the architecture when I see a better approach because I have tests. It is the tests that enable architectural improvement.
Yes, architecture enables flexibility, maintainability, and reusability; but test suites enable architecture. Architecture is a second order effect.
