The art of writing readable code
Improvements at the surface level
naming, commenting, and aesthetics--tips that you can use for each line of the code base.
Simplifying loops and logic
Define loops, logic, and variables in your program, making your code easier to understand.
Re-Organize your code
The ability to organize large blocks of code at a higher level, as well as ways to solve problems at the functional level.
Featured Topics
Apply the idea of "easy to understand" to tests and examples of large data structure code.
1th Chapter: Code should be easy to understand
1. The code should be easy to understand.
2. The code should be written to minimize the time required for others to understand it.
The first part: improvement of surface level
the 2nd Chapter: put the information in the name
1. Use a professional word. 2. Avoid vague names. 3. Use specific names to describe things in more detail. 4. Bring important details to the variable name. 5. Use a longer name for the larger name of the scope. 6. Use uppercase and lowercase, underline and so on. For example, after the class member variable, add "_" to differentiate the local variable.
3rd: Names that will not be misunderstood
1. Ask yourself a few more times: "Will this name be interpreted by others as something else?" "Take a closer look at the name.
2. The clearest way to name limits is to add max_ or Min_ to the limits of things.
3. When naming a Boolean value, use words like IS and has to explicitly indicate that it is a Boolean value.
4. Be careful about the user's expectations of a particular word. For example, the user expects get () or size () to be a lightweight method.
The 4th Chapter: Aesthetics
1. Use a consistent layout that allows readers to get used to this style quickly.
2. Make similar code look similar.
3. Group the relevant lines of code into blocks of code.
The 5th chapter: What kind of comments should be written
1. The purpose of the note is to try to help the reader to understand as much as the author.
2. Where no comments are required:
- A fact that can be quickly inferred from the code itself.
- A "cane-style note" used to whitewash a rotten code--the code should be changed well.
3. The ideas you should write down include:
- For the reasons why the code Ctrip does not have such an intrinsic reason ("instructional annotations").
- Bugs in the code, using tags like TODO: or xxx: such.
- The story behind the constant, why is this value.
4. Think in the reader's position:
- What part of the code is expected to make the reader say: "Ah?" "and add notes to them.
- Add comments to the unexpected behavior of ordinary readers.
- Use the "Global View" annotation at the file/class level to annotate how all the parts work together.
- Use annotations to summarize blocks of code so that readers are not lost in detail.
the 6th chapter: Write Concise Notes
1. The note should have a high information/space rate. 2. Describe the behavior of the function as accurately as possible. 3. Note the carefully selected input/output examples in the comments. 4. Declare the high-level intent of the code, not the obvious details. 5. Use embedded annotations (such as function (/*arg =*/...) ) to explain the hard-to-understand function parameters. 6. Use words that are rich in meaning to make annotations concise.
Part II: Simplifying Loops and logic
7th: Make control flow easier to read
1. The more "natural" the change in conditions, cycles, and other team control flows, the better. Use a way to make the reader not stop and reread your code. 2. A better measure than the pursuit of minimizing the number of lines of code is to minimize the time that people need to understand it. 3. When you make changes to the code, look at it from a new perspective and treat it as a whole. 4. Nested blocks of code need to be more focused on understanding.
The 8th chapter: splitting the extra-long expression
1. Split your extra-long expression into smaller pieces that are easier to understand.
2. Be careful with small snippets of "smart"-they tend to be confusing for others to read later.
3. Help readers identify key concepts in the code.
the 9th chapter: variables and readability
1. Reduce variables, that is, those that are hindered.
2. Reduce the scope of each variable, the smaller the better.
3. A variable that writes only once is better. (const, final, constant) makes the code easier to understand.
Part III: Reorganize your code
the 10th chapter: extracting unrelated sub-problems
1. Look at a function or block of code and ask yourself: What is the high-level goal of this code? 2. For each line of code, ask: does it work directly for the purpose? 3. If the number of rows is sufficient to resolve unrelated sub-problems, extract the code into a separate function. separating generic code from proprietary code: It allows programmers to focus on small, well-defined issues that have been disconnected from other parts of the project.
11th: Do only one thing
at a time
1. List all "Tasks" that the code has done.
2. Try to split the task into different functions, or at least a different paragraph in the code.
the 12th chapter: Turning Ideas into code
If you can't explain something to your grandmother, it means you haven't really understood it yet. --Albert Einstein
Write clearer code:
1. Describe what the code does in natural language, just like a colleague.
2. Note the keywords and phrases used in the description.
3. Write the code that matches the description.
Chapter 13th: Write less code
1. Remove unnecessary functionality from the project and do not overdo it.
2. Reconsider the requirements, solve the simplest version of the problem, as long as you can complete the work.
3. Constantly read through the entire API of the standard library to keep them familiar.
Part IV: Featured Topics
the 14th chapter: Testing and Readability
1. The highest level of each test should be as concise as possible. It is best to use one line of code to describe the input/output of each test. 2. If the test fails, the error message it sends should make it easy for you to track and fix the bug. 3. Use the simplest test input that can be used to fully apply the code. 4. Give the test function a fully descriptive name so that each test has a clear sense of what is being measured. For example, a name like:test_<functionname>_<situation>.
Table 1: Code features with poor testability, and design problems it brings
Characteristics |
Testability Issues |
Design issues |
Using Global variables |
Reset all global variables for each test (otherwise, different tests will affect each other) |
It is difficult to understand which functions have any side effects. There is no way to think about each function independently, to consider the whole program to understand that not all the code can work |
Code that has a lot of dependencies on external components |
It is difficult to write any tests for it because there are too many scaffolding to put up first. Writing test monogram is uninteresting, so people will avoid writing tests |
The system is more likely to fail because of a dependency failure. It's hard to know what kind of impact the change will have. It is difficult to refactor classes. The system will have more failure modes and more recovery paths to consider |
The code has an indeterminate behavior |
Testing can be erratic and unreliable. Tests that often fail will eventually be ignored |
This program is more likely to have conditional competition or other bugs that are difficult to reproduce. This procedure is difficult to infer. Bugs in the product are difficult to track and correct |
Table 2: Characteristics of well-testability code, and the excellent design it produces
Characteristics |
The benefits of Testability |
The benefits of Design |
There are few or no internal states in the class |
It's easy to write tests because you want to test a method with fewer settings and have fewer hidden states to check |
Classes with fewer states are simpler and easier to understand |
class/function do only one thing |
Only a few test cases are required to test it |
Fewer/simpler components are more modular, and generally less coupling of the system |
The dependence of each class on other classes is very low; |
Each class can be tested independently (much easier than testing a class) |
The system can be developed in parallel. You can easily modify or delete classes without affecting other parts of the system |
The interface of the function is simple and well defined |
There are definite behaviors that can be tested. Less effort required to test a simple interface |
Interfaces are easier for programmers to learn and more likely to be reused |
Write an art note for readable code