Best practices for continual code refactoring sessions.
**!!! WORK IN PROGRESS !!!**
See [Clean Code](Clean%20Code.md) for code writing and design best practices.
Meanwhile, the [Code Review Pyramid](Code%20Review%20Pyramid.md) contains a hierarchy of questions to ask yourself in code reviews.
Once you have written some code, this document explains how to keep it in shape.
1. Tidy Guard Clauses
- Reduce `if` condition blocks in functions to `if ...: pass & return`
- Extract more complex condition blocks into separate functions.
- Extract complex conditionals into well-named functions to make them more readable.
1. Tidy variable declaration and initialization
- Initialization and declaration should not be separated.
- Variable names should explain intent.
1. Tidy improper use of constants and literals
- Refactor literals used like constants into actual constants with an intent-revealing name (`one := 1` is not revealing intent).
- The same constant value might have different intent in different locations, which means they should be treated as two separate constants.
1. Make your parameters explicit
- Avoid pulling in environment variables deep inside your code.
- Avoid using associative arrays (maps) to receive parameters.
- At least extract the function body into a helper that uses explicit parameters, thereby avoiding (implicit) modification of the container while making missing parameters explicit.
1. Break down large or coupled expressions
- Extract them into functions or...
- Break them down into steps with named variables.
- Combine function calls that have temporal coupling (`a()` always needs to be before `b()`) into a single functions `ab()`.
- Extract lines in a function you need to change into a helper function.
1. Delete Dead Code
- YAGNI and trust your version control system to hold a memory of the past.
2. Normalize Accidental Asymmetries
- If one variable or functionality is implemented in many different ways, tidy those asymmetries (one tidying at a time).
3. Beware of Flag Arguments
- Boolean flags in arguments are strong code smells that indicate you should break up your function.
4. Review Returning Functions for Side Effects
- A function with a return value *should* not call a function that causes a side effect (only has a `void` return type).
- If you *must* invoke a side effect (e.g., creating a `new` object), make that side effect explicit in the function name (in this example: constructor name).
1. Use adhesion to pile spaghetti code before refactoring into cohesive units
- Spaghetti code is hard to read due to long and repeated argument lists, repeated code and especially conditionals, unclear helper routines, or shared mutable data structures.
- Move all that spaghetti together in stepwise changes to one large adhesive pile, which will help you understand it better.
- Refactor the pile into cohesive, decoupled units once you understand it.
1. Refactor from the Target State Backwards
- When a new interface would be better, create it but let it use the old implementation. Then, iterate towards the new implementation while delivering working production code at every iteration.
- When refactoring a function, start with the last line and pretend you had the intermediate results needed.
- Start with a [failing test first](Canon%20TDD.md).
2. Order Source Code in Files by Reading Order
- Often, the most critical details end up being written last; Fix that when it happens.
- Reorder functions and objects to make them easy for a reader to comprehend when reading the file from top to bottom.
- Resist the temptation to do another refactoring while fixing and testing the new reading order.
- The correct reading order is context-dependent: primitives typically come before compositions, API before implementation, etc. But use your best judgment to determine what should go first in each case.
3. Co-locate Coupled Code
- Put code blocks and files that are coupled next to each other.
- If you must change multiple locations when making a behavior change, collocate those pieces first.
- Consider decoupling the code if that cost is lower than the cost of the existing coupling.
4. Review Comments
- Code that "needs" comments to be "clear" or "readable" is a smell.
- Refactor comments that are incorrect, unclear, or where the connection to the code or its intent isn't obvious.
- Remove comments that are redundant or obvious from reading the code, including overly excessive use of "banners."
- Replace comments with intention-revealing variable names where possible.
- Replace comments by extracting functions and variables with proper names.
- Remove attribution and commented-out code - that is the job of version control.
- Don't add public documentation to private or protected code.
Source: [Tidy First?](https://www.goodreads.com/book/show/171691901-tidy-first) by Kent Beck (and some Clean Code aspects from Uncle Bob)