Sponsored Link •
A refactoring exercise tickles an old memory and triggers a new connection
I discovered something very interesting today. I was writing some new code that I intended to have re-use some existing code, but some refactoring was necessary first. The existing code was a method that did three things:
Previously there was only one method that was a client for this code. Now there would be two, and the code would have to be generalized accordingly.
The new client of this code already had an isolated text block, and just needed the block parsed. I first moved the parsing code to the new method, without the text block isolating code. I figured I'd move step 3 (running the associated function) up to the calling method while I was at it, since it seemed to be an independent step.
When I was done, the new method needed to be passed just about every parameter there was, and had to return a bunch as well. I had to add some code to handle all these parameters. Although the new method was now separated from its former neighboring code, the parameters and return values kept it all too tightly coupled together. That smelled bad.
After taking a break, I returned to the task. I found that the parsing code really needed to know the results of isolating the text block, but the exception handling needed higher-level details that the parsing code really didn't care about. By moving the exception handling back into the original method, and the text block isolating code into the new parsing method, I was able to reduce the number of parameters required (and values returned) by the new method to reasonable levels. In the end, the original client code was restored to its initial state, the original method and the exception handling was drastically simplified, the new method became nicely generic, and all the extra code disappeared.
Sometimes, code seems to have a natural optimum arrangement where parameters are minimized and elegance is maximized.
The completion of this small task tickled an old memory. This refactoring felt just like working out symbolic algebra problems in high school math class, such as multiplying polynomials: first expand all the factors, then combine like terms and simplify. When refactoring this code, it grew in size and complexity before it could shrink and become simpler. And just like in algebra, the intermediate steps are just as important as the end result -- you've got to show your work to get full marks.
Meanwhile, the unit tests proved their worth yet again. But that's material for another day...
|David Goodger has been using Python since 1998, and began working on reStructuredText and Docutils in 2000. A proud Canadian, he lived in Japan for 7 years, where a stint at a document processing company in Tokyo began his love/hate relationship with structured markup. David is a Python Enhancement Proposal (PEP) Editor and a member of the Python Software Foundation. He currently lives outside of Montreal, Quebec, with his Japanese wife and their two children.|