More on this book
Community
Kindle Notes & Highlights
Started reading
February 18, 2020
At the moment, most people under-prioritize refactoring—but there still is a balance.
The best time to refactor is just before I need to add a new feature to the code base.
Certainly you have to refactor when you run into ugly code, but excellent code needs plenty of refactoring too.
Each team should experiment to find what works for them; just remember that separating refactoring commits is not a self-evident principle—it’s only worthwhile if it makes life easier.
To change from one library to another, start by introducing a new abstraction that can act as an interface to either library.
While it does happen that teams do too much refactoring, it’s much rarer than teams not doing enough.
A schedule-driven manager wants me to do things the fastest way I can; how I do it is my responsibility.
The decision to refactor or rewrite requires good judgment and experience, and I can’t really boil it down into a piece of simple advice.
You may have trouble telling the difference in productivity between a healthy and a sickly code base because you haven’t had enough experience of a healthy code base—of the power that comes from easily combining existing parts into new configurations to quickly enable complicated new features.
So, when renaming a field, my first commit would add the new database field but not use it. I may then set up the updates so they update both old and new fields at once. I can then gradually move the readers over to the new field. Only once they have all moved to the new field, and I’ve given a little time for any bugs to show themselves, would I remove the now-unused old field.
They realized that refactoring was important in improving their productivity and, ever since, have been working with refactoring, applying it to serious software projects and refining it.
One downside of this popularity has been people using “refactoring” loosely, to mean any kind of restructuring.
It’s now pretty common to find some kind of refactoring support in editors and tools, although the actual capabilities vary a fair bit. Some of this variation is due to the tool, some is caused by the limitations of what you can do with automated refactoring in different languages.
To do refactoring properly, the tool has to operate on the syntax tree of the code, not on the text.
This is why at the moment, most refactoring capabilities are part of powerful IDEs—they use the syntax tree not just for refactoring but also for code navigation, linting, and the like.
even with mostly safe refactorings, it’s wise to run the test suite every so often to ensure nothing has gone pear-shaped.
A technology that’s currently gaining momentum is Language Servers [langserver]: software that will form a syntax tree and present an API to text editors. Such language servers can support many text editors and provide commands to do sophisticated code analysis and refactoring operations.
If you have code that’s similar, but not quite identical, see if you can use Slide Statements (223) to arrange the code so the similar items are all together for easy extraction.
The key here is not function length but the semantic distance between what the method does and how it does it.
Long lists of parameters can be slimmed down with Introduce Parameter Object (140) and Preserve Whole Object (319).
because the alternative was global data, and global data quickly becomes evil.
this doesn’t mean we should ignore the advantages of immutability—there are still many things we can do to limit the risks on unrestricted data updates.
It’s not just a rich source of confusion, bugs, and missed dinners at home—it’s also unnecessary.
We structure our software to make change easier; after all, software is meant to be soft.

