本文同步发自于个人blog - [Refactoring] Chapter 2 Principles in Refactoring - Book Summary
1. Defining Refactoring
Noun's definition: A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.Verb's definition: To restructure software by applying a series of refactorings without changing its observable behavior.Both definitions have the same objective: don't change the software's behavior.
Like electrical wiring for our life, we plug electrical appliances and the electric current moves through the wiring. The plug-in is like an API. Electrical appliances get the electric current with this API and don't understand what plug-in electrical panel works. If API's internal code structure is like:
Electrical Panel before re-wiring (Source: https://theintegrityexperience.com/rewiring-a-house-and-electrical-panel-upgrade/)
It's ugly but it still works to supply electric current. Someday, the power failure occurs and we should check the electrical panel then open it, OS: "What the hell" and very hard to find the broken wires.....
After refactorings(re-wiring), the new electrical panel is like:
Electrical Panel after re-wiring (Source: https://theintegrityexperience.com/rewiring-a-house-and-electrical-panel-upgrade/)
What a beautiful wiring! It supplies electric current like the last ugly wiring but next time we will find correct wires quickly. This analogy to our coding refactorings is very similar.
The tip at book's page 46 describes:
**_
If someone says their code was broken for a couple of days while they are refactoring, you can be pretty sure they were not refactoring.
_**
This tip is very funny XD. According to chapter 1's tip, refactoring is driven by testings. Every refactoring step is done, then run the testings to validate the observable behavior is not changed.
2. The Two Hats
When we are developing the software, we have 2 hats: one hat for adding functionality and the other one for refactoring. Only wear one of these 2 hats in a period of developing. Do not add functionality and refactor concurrently.
3. Why Should We Refactor?
3.1 Refactoring Improves the Design of Software
If we don't refactor, the code becomes more messyMessy code means maintenance is more difficult.DRY (Don't Repeat Yourself) is a fundamental design principle and reduces the code size3.2 Refactoring Makes Software Easier to Understand
Programmer is the reader of the code and it's the major time costIf the reader spends 1 week understanding the code and modifying it ---- What a terrible codeIf the reader spends 1 hour understanding the code and modifying it ---- What a great codeWe spend a little time refactoring our code and make the code more readable. Next time the reader will spend less time working.If the code function is easily looked up by documentation, programmers don't deliberately remember them.3.3 Refactoring Helps Me Find Bugs
When we are refactoring the code, code structure maybe shows some bugs we have never noticed
3.4 Refactoring Helps Me Program Faster
The previous points result in this pointDoes not the time of refactoring slow the development? No! If the system with poor design, it would add features like putting many "patches" on it.... It's hard to understand what a module works.Design Stamina Hypothesis: Good designs increase the stamina of the software effortRefactoring makes the design better than the lastThe development time with good and poor design (Redraw at book's page 49)
4. When Should We Refactor?
The Rule of Three
The first time you do something, you just do it. The second time you do something similar, you wince at the duplication, but you do the duplicate thing anyway. The third time you do something similar, you refactor.
Or for those who like baseball: Three strikes, then you refactor.
4.1 Preparatory Refactoring - Making It Easier to Add a feature
Parameterize Function skill reduces the duplicated code. Similar codes are centered.Like before I move to a place, I check the map and find a short route to arrive at the place.4.2 Comprehension Refactoring: Making Code Easier to Understand
Read codes to understand "What is the section of the code doing?". Spending much time reading code is a refactoring chance.Refactoring makes the code logics clearer4.3 Litter-Pickup Refactoring
If there is a small trash code (duplicated codes, terrible variable naming...), immediately refactor itIf the trash code is not easy to be refactored with current task, note the trash code, put it aside and continue current task. After finish the task, then refactor the noted trash code.4.4 Planned and Opportunistic Refactoring
Previous 3 refactoring examples are opportunistic. Planned refactoring is not a natural thing. Adding features or fixing bugs are normal with refactoring.The tip at book's page 52 describes:
You have to refactor when you run into ugly code - bug excellent code needs plenty of refactoring too.
Kent Beck also described:
For each desired change, make the change easy (warning: this may be hard), then make the easy change.
The two sections are excellent points.
Author thinks that creating a new branch to refactor codes in control version system is not good because refactoring is closed with adding new features.4.5 Long-Term Refactoring
Like previous Planned Refactoring, it's not recommend by author. Example: If the system wants to replace a existing library, use Branch By Abstraction to make the replacement easy4.6 Refactoring in a Code Review
Better practice: Pair-programming and refactoring/reviewing the code4.7 What Do I Tell My Manager?
If the manager doesn't know what the refactoring is, don't tell him/her why you do refactoring. Manger just wants the task to be finished before the deadline. We just use refactoring this professional skill to smoothly complete the job.4.8 When Should I Not Refactor?
If there is a messy code and it's not required to be modified, don't refactor with it.If some ugly code is hidden under an API, don't refactor.Sometimes rewriting is easier than refactoring but it's hard to decide which method should be executed.5. Problems with Refactoring
5.1 Slowing Down New Features
The tip at book's page 56 describes:
If there are a large-scale refactoring situation and small-scale urgent new feature, finish the urgent new feature and then back to the refactoring.Refactoring's target doesn't equal to the one of "Clean Code" and "Good Engineering Practice". Refactoring focuses on adding features quickly, fixing bugs quickly.The whole purpose of refactoring is to make us program faster, producing more value with less effort.
5.2 Code Ownership
Example: A naming is not good and we use Change Function Declaration skill to rename it. But the renamed function is used by other teams / product API caller, it will result in blocked situation.Use Rename Function skill and the old function is pass-through to the new one. Mark the old function as [deprecated].Team ownership of code is recommended by author, not only restricted to one person.5.3 Branches
Every branch is responsible for specific features, after a period, those branches will be merged into master/trunk. But if the feature branch is isolated for a long time, the integration with master will be hard.Refactoring like renaming for merging branch sometimes is a difficult integrationContinuous Integration (CI) / Trunk-Based Development: Use this practice to require every member to merge branch into master and integrate. This action avoid the large difference between branches.Refactoring very fits CI practice. Small changes are easily integrated when using CI. Kent Beck's Extreme programming uses CI and refactoring5.4 Testing
If we want refactoring, self-testing code is requiredIf no testing can support, we can use automated refactoring. But it only executes safe refactoring methods.Special style of refactoring: only use proved and absolutely safe refactoring methods. Like an example that shows how to safely execute Extract Method skill in C++ provided by Jay Bazuzi.I very recommend that every programmer should read this book to learn unit testing: The Art of Unit Testing: with examples in C# written by Roy Osherove5.5 Legacy Code
Legacy code without testings is very terrible...Adding new testings in current legacy code is not easyWorking Effectively with Legacy Code by Michael Feathers is recommended by author. It teaches how to perform refactoring and testings in legacy codeStep-by-step refactor legacy code instead of changing it widely5.6 Databases
Refactoring Databases: Evolutionary Database Design by Scott Ambler & Pramod Sadalage is recommended by author.Add migration scripts into version control system with code. This makes the database development efficientExample with .NET, Entity Framework has a migration tool to upgrade/downgrade database's structure.The book provides a refactoring skill: parallel change. I think I should buy this book to deeply learn it!6. Refactoring, Architecture, and Yagni
In early period, architecture was first designed. So the later development was restricted with the architecture and the system continued to become decayed.Refactoring is the iterative method to improve current designyou aren't going to need it : Yagni mixes architecture, design and development and depends on refactoringBuilding Evolutionary Architectures: Support Constant Change by Neal Ford, Rebecca Parsons, Patrick Kua is a continuously developing subject and discover what pattern and practice are useful for iterative developement.7. Refactoring and the Wider Software Development Process
Self-testing is the first foundation of refactoringSelf-testing, CI and refactoring are the 3 major practices for a refactoring teamBased on these 3 practices, some products can be published in one dayThese practices are not easy to build up8. Refactoring and Performance
3 methods to write fast software1. Time budgeting: It's a serious method for real time system like heart pacemakers. Every module is restricted with limited resources.
2. Constant attention: Every programmer keeps the system with high performance anytime.
3. Use the optimization statistic analysis to improve the system
9. Where Did Refactoring Come From?
In 1980, Smalltalk project with refactoring skills influenced the development communityFirst one wrote the refactoring book is Martin Fowler10. Automated Refactorings
IntelliJ IDEA provides many automated refactoring tools for popular programming language.IDE analyzes the syntax tree of the code and provides safer refactoring results11. Going Further
Refactoring Workbook by Ross Venables, William Wake, John FullerRefactoring to Patterns by Joshua Kerievsky Refactoring HTML: Improving the Design of Existing Web Applications by Elliotte Rusty HaroldRefactoring: Ruby Edition by Jay Fields, Shane Harvie, Martin Fowler, Kent Beckrefactoring.com12. References
Refactoring: Improving the Design of Existing Code (2nd Edition)