Another blog post on the "Revisited" series.
This time it's Clean Code written by Robert C. Martin. I highly recommend this book because as an experienced programmer, it describes exactly what I have in mind when I write software or when I read code. Martin expresses clearly what I generally admit and sometimes difficult to explain what is clean code (interestingly, I wrote "good code" as a first intention. But here we talk about clean code. Craftsmanship. Not just "good enough"). He gives a lot of arguments for each of his points.
There is also a comprehensive list of what the author thinks what bad code is ("smells"). These "smells" are the same thing as code rule checkers (PMD, Checkstyle, Findbugs, ...) that are run automatically within a continuous integration system.
You will find a word on the author, a synopsis of the book and the tips that are the most important to me.
About the Author
Robert Cecil Martin (colloquially known as Uncle Bob) is an American software engineer and author. He is a co-author of the Agile Manifesto. He now runs a consulting firm called Uncle Bob Consulting LLC and Clean Coders which hosts videos based on his experiences and books.
Even bad code can function. But if code isn’t clean, it can bring a development organization to its knees. Every year, countless hours and significant resources are lost because of poorly written code. But it doesn’t have to be that way. Noted software expert Robert C. Martin presents a revolutionary paradigm with Clean Code: A Handbook of Agile Software Craftsmanship . Martin has teamed up with his colleagues from Object Mentor to distill their best agile practice of cleaning code “on the fly” into a book that will instill within you the values of a software craftsman and make you a better programmer—but only if you work at it. What kind of work will you be doing? You’ll be reading code—lots of code. And you will be challenged to think about what’s right about that code, and what’s wrong with it. More importantly, you will be challenged to reassess your professional values and your commitment to your craft. Clean Code is divided into three parts. The first describes the principles, patterns, and practices of writing clean code. The second part consists of several case studies of increasing complexity. Each case study is an exercise in cleaning up code—of transforming a code base that has some problems into one that is sound and efficient. The third part is the payoff: a single chapter containing a list of heuristics and “smells” gathered while creating the case studies. The result is a knowledge base that describes the way we think when we write, read, and clean code. Readers will come away from this book understanding How to tell the difference between good and bad code How to write good code and how to transform bad code into good code How to create good names, good functions, good objects, and good classes How to format code for maximum readability How to implement complete error handling without obscuring code logic How to unit test and practice test-driven development This book is a must for any developer, software engineer, project manager, team lead, or systems analyst with an interest in producing better code.
Data Abstraction and Objects 1 (Objects and Data Structures)
"The beautiful thing about [...] is that there is no way you can tell wether the implementation is in rectangular or polar coordinates."
"There is a reason that we keep our variables private. We don't want anyone else to depend on them. We want to keep the freedom to change their type or implementation on a whim or an impulse."
"Hiding implementation is not just a matter of putting a leayer of functions between the variables. Hiding implementation is about abstractions! [...] Rather it exposes abstract interfaces that allow its users to manipulate the *essence* of the data, without having to know its implementation."
Data Abstraction and Objects 2 (Objects and Data Structures)
"Objects expose behavior and hide data. This makes it easy to add new kinds of objects without changing existing behaviors."
"Data structures expose data and have no significant behavior."
Use Unchecked Exceptions
"The debate is over."
"However, it is clear now that [unchecked exceptions] aren't necessary for the production of robust software."
C#, C++. Python, Ruby don't have checked exceptions and yet it is possible to write robust software in all of these languages.
"The price of checked exceptions is an Open/Closed Principle violation."
Don't Return Null (Error Handling)
"When we return null, we are essentially creating work for ourselves and foisting problems upon our callers. All it takes is one missing null check to send an application spinning out of control."
Don't Pass Null (Error Handling)
"In most programming languages there is no good way to deal with a *null* that is passed by a caller accidentally. Because this is the case, the rational approach is to forbid passing *null* by default. When you do, you can code with the knowledge that a *null* in an argument list is an indication of a problem, and end up with far fewer careless mistakes."
"Clean code is readble, but it must also be robust" (Error Handling)
Exploring and Learning Boundaries (Boundaries)
"Third-party code helps us get more functionality delivered in less time."
"Learning the third-party code is hard. Integrating the third-party code is hard too,. Doing both at the same time is doubly hard. What if we took a different approach? Instead of experimenting and trying out the new stuff in our production code, we could write some tests to explore our understanding of the third-party code. Jim Newkirk calls such tests *learning tests*."
Keeping Tests Clean (Unit Tests)
"From release to release, the cost of maintaining my team's test suite rose. Eventually, it became the single biggest complaint among the developers. When managers asked why their estimaes were getting so large, the developers blamed the tests. In the end they were forced to discard the test suite entirely."
"But, without a test suite, they lost the ability to make sure that changes to their code worked as expected."
"Test code is just as important as production code."
Clean tests follow F.I.R.S.T. (Unit Tests)
- Fast: Tests should be fast.
- Independent: Tests should not depend on each other.
- Repeatable: Tests should be repeatable in any environment.
- Self-Validating: The tests shoukd have a boolean output.
- Timely: The tests need to be written in a timely fashion.
Clean Systems (Systems)
"An optimal system architecture consists of modularized domains of concern, each of which is implemented with Plan Old Java (or other) Objects. The different domains are integrated together with minimally invasive Aspects or Aspects-like tools. This architecture can be test-driven, just like the code."
Optmize Decision Making (Systems)
"We often forget that it is also best to postpone decisions until the last possible moment. This isn't lazy or irresponsible; it lets us make informed choices with the best possible information. A premature decision is a decision made with suboptimal knowledge."
Systems Need Domain-Specific Languages (Systems)
"Building construction, like most domains, has developed a rich language with a vocabulary, idioms, and patterns that convey essentiel information clearly and concisely. In software, There has been renew interest recently in creating Domain-Specific Languages (DSLs), which are separate, small scripting languages or APIs in standard languages that permi code to be written so that it reads like a structured form of prose that a domain expert might write."
Getting Clean via Emergent Design (Emergence)
"What if there were four simple rules that you could follow that would help you create good designs as your worked?"
- Runs all the tests
- Contains no duplication
- Expresses the intent of the programmer
- Minimizes the number of classes and methods
The rules are given in order of importance.
Myths and Misconceptions (Concurrency)
- "Concurrency always improves performance."
- "Design does not change when writing concurrent programs."
- "Understanding concurrency issues is not important when working with a container such as a Web or EJB container."
- Concurrency incurs some overhead
- Correct concurrency is complex
- Concurrency bugs aren't usually repeatable
- Concurrent often requires a funddamental change in design strategy
Concurrency Defense Principles (Concurrency)
- Single Responsibility Principle
- Limit the Scope of Data
- Use Copies of Data
- Threads Should Be as Independent as Possible
History of JUnit (JUnit Internals)
"JUnit has had many authors, but it began with Kent Beck and Eric Gamma together on a plane to Atlanta. Kent wanted to learn Java, and Eric wanted to learn about Kent's Smalltalk testing framework. "What could be more natural to a couple of geeks in cramped quarters than to pull out our laptops and start coding?" After three hours of high-altitude work, they had written the basics of JUnit."