[閱讀筆記] Clean Code Chapter 17 — Smells and Heuristics
3 min readFeb 18, 2021
The followings are all the bad things and should be avoided in programming.
Comments
- Inappropriate Information (meta-data such as authors, last-
modified-date, SPR number, and so on) - Obsolete Comment
- Redundant Comment
- Poorly Written Comment
- Commented-Out Code
Environment
- Build Requires More Than One Step
- Tests Require More Than One Step
Functions
- Too Many Arguments (< 3)
- Output Arguments
- Flag Arguments (function does more than one thing)
- Dead Function (not used function)
General
- Avoid Multiple Languages in One Source File
- Avoid Obvious Behavior Is Unimplemented
- Avoid Incorrect Behavior at the Boundaries (Don’t rely on your intuition)
- Avoid Overridden Safeties
- Avoid Duplication (TEMPLATE METHOD, or STRATEGY pattern)
- Avoid Code at Wrong Level of Abstraction
- All the lower-level concepts should be in the derivatives and all the higher-levels in the base class - Avoid Base Classes Depending on Their Derivatives
- Base classes should know nothing about their derivatives
- Exception: the base class has code that selects between the derivatives
- In general, the deployment of derivatives and bases should be separated - Avoid Too Much Information
- The fewer methods/fewer/instance variables a class has, the better
- Hide your data/utility functions/constants/temporaries
- keeping interfaces very tight and very small - Avoid Dead Code
- If/catch try/switch case that never happens
- Dead code is not completely updated when designs change - Avoid Vertical Separation
Local variables should be declared just above their first usage and should have a small vertical scope - Avoid Inconsistency
Do something a certain way, do all similar things in the same way - Avoid Clutter
Unused variables/uncalled functions/no information comments, etc - Avoid Artificial Coupling
- A coupling between two modules that serves no direct purpose
- It is a result of putting a variable, constant, or function in a temporarily
convenient, though inappropriate, location → put them in the right place - Avoid Feature Envy
The methods should be interested in the variables and functions of the class they belong to, and not the variables and functions of other classes - Avoid Selector Arguments (true/false, enums, integers, etc)
- The purpose of a selector argument is difficult to remember and each selector argument combines many functions into one
- have more functions > pass some code into a function to select the behavior - Avoid Obscured Intent (ex. iThsWkd/ iThsRte)
- Avoid Misplaced Responsibility
Code should be placed where a reader would naturally expect it to be - Avoid Inappropriate Static
- nonstatic > static methods, When in doubt → nonstatic
- If you really want a function to be static, make sure that there
is no chance that you’ll want it to behave polymorphically - Use Explanatory Variables
- Function Names Should Say What They Do
- Understand the Algorithm → understand how it works
- Make Logical Dependencies Physical
Dependent module should not make assumptions (logical dependencies) about the module it depends upon → Explicitly ask that module for all the information it depends upon (physical dependencies) - Prefer Polymorphism to If/Else or Switch/Case
- Follow Standard Conventions
- Replace Magic Numbers with Named Constants
- Be Precise
- Structure over Convention (base classes with abstraction > switch/case)
- Encapsulate Conditionals
- Avoid Negative Conditionals
- Functions Should Do One Thing
- Do NOT Hide Temporal Couplings
- Don’t Be Arbitrary
- Encapsulate Boundary Conditions
- Functions Should Descend Only One Level of Abstraction
- Keep Configurable Data at High Levels
ex. public static final String DEFAULT_PATH = “.”; - Avoid Transitive Navigation
Modules know only about their immediate collaborators and do not know the navigation map of the whole system
Names
- Choose Descriptive Names
- Choose Names at the Appropriate Level of Abstraction
- Use Standard Nomenclature Where Possible
- Unambiguous Names
- Use Long Names for Long Scopes
- Avoid Encodings
- Names Should Describe Side-Effects
Tests
- Insufficient Tests
- Use a Coverage Tool!
- Don’t Skip Trivial Tests
- An Ignored Test Is a Question about an Ambiguity
- Test Boundary Conditions
- Exhaustively Test Near Bugs
- Patterns of Failure Are Revealing
- Test Coverage Patterns Can Be Revealing
- Tests Should Be Fast