"Refactoring is the process of changing a software system in such a way that it does not alter the external behaviour of the code yet improves its internal structure." What does that exactly mean? I mean, we're not changing how it behaves, so the code's going to work the same way, but we're going to change the inner workings of it a little bit.
- We refactor to reduce the complexity to add new features into the code.
- Easy readability
- Easy to enhance and add new features to the code
- Reduce the time it takes to debug an issue
- To improve the understandability of the code for non-authors like new programmers, delivery team or support team.
- To reduce technical debts (a piece of code written in a limited time thinking to redesign it in future)
When to stop refactoring:
- Taking too much time to refactor which is blocking other dependent applications and priority tasks
- There is limited to no ROI (Return On Investment), which is very addictive for developers.
- Refactoring is not same as redesigning the code. It is easier to start the coding from scratch than to refactor your own or somebody else's code.
Importance of test cases
- Unit test cases
- Behavioural/Acceptance cases
- IDE refactoring
- IDE reformatting
- Paired programming
Always take a backup before starting the refactoring
- Sometimes the new design may look worse than current
- More time and energy requirement
- Redesigning of the code needed
Refactor keeping the future you in mind
- Use PEP8 style
- Use Pylint and use .pylintrc to configure it as per the project
- Similarly, you can use the optional static type checker mypy with mypy.ini for configuration
- Always write unit test cases pytest with pytest.ini for its configurations
- The code should be highly testable
- Use a good IDE, PyCharm recommended
- Use a code health checker deepsource, sonarlint, etc. are few which helps in finding complexities and many other things around the code
- Use an automatic code formatter like black, autopep8, sort imports, etc.
- Working in small steps and committing the code
- Working in pair or group (pair programming or mob programming)
- Test cases should be readable.
- Write Explicit Tests (WET)
- Cover the boundary conditions
- Write End to end test cases.
- Start with broader tests and work towards unit testing.
- Test large class or method can by pulling small portions out of it.
- Test every possible decision tree path, i.e. conditional statements
- Different types of tests are there:
Recognizing issues in the code
- Meaningless comments
- Comments repeating the same thing as the function/class/statement
- Confusing comments
- Comments used as section label
- Outdated comments
- Comments to help in organize
- Business and Developer using different nomenclature
Too many conditional statements
Names of variables, functions or classes
- Write less character-based words, usually by removing the vowels like ctr, cty.
- Using meaningless names like x, y, I, j, process, function, class, processes_data_and_many_other_stuffs
- Giving selfish names: my_cls, our_cntry_func
- Using the built-in keyword as a variable name like id, type
Large code bases
- In method/function
- In class
- In a module
- Checking conditional statements for negative cases and the positive condition is on the else part.
Passing too many parameters on a method/function definition
Too many returns on a large function
- Commented code
- Unused/Uncalled code
- Unexecuted code
Deliberate attempt to write complex codes
- Skill show off
- Attempt to confuse.
Remove clutter, complexity and cleverness.
Common refactoring techniques
- Better code sharing
- Break parts into logical pieces
- Improve format and names
- Moving the right piece of code to the right place
- Replacing constant digits and strings with a constant variable
- Deduplicating duplicate piece of codes
- Reducing code lines for readability and simplicity
- Improve formatting
- Change signature
- Replace nested conditional with a guard clause
- Push members down
- Replace magic number with symbolic constant
- Apply experience and logic
- Prepare the software for change
- Improve the software
- Clean up the software