Weekly Blog: July 28th – Refactoring

I’ve always thought of refactoring as more of an art than a science. But thanks to the works of Martin Fowler and William Opdyke that is probably no longer the case. Looks like I’ll just have to find a new term.

Why do I say this? A program’s I/O is always the same before and after refactoring (ideally), and likewise with optimization. If you black box a program, no one would be any the wiser on exactly how it does what it does. At the same time, there are many refactorings I believe should just be labeled under common sense and others where I don’t see the sense at all. I’ll only focus on one of these to spare all the electrons that will have been inconvenienced from you reading this blog.

The most obvious refactoring technique that I don’t see sense in is method extraction (I personally am not a fan of “Extract Method” – sure it’s short, but we’d probably want to run a “Rename Title” on it so that it flows better). I respect the rights of programmers to choose to have more methods than statements in their program, but I personally think that following a logic five or ten methods down is extremely annoying. Code as text is not designed for that sort of extraction – code is written in a linear format when it really should be represented as a directed network. There is no good way of ordering the methods such that a person could naturally read the methods in the proper order for every use case.

I could go on for pages but here’s the best example I could think of the express what I mean just on this one topic (yes, I must agree I like Martin Fowler’s use of examples, even though I personally don’t like the examples): let’s take a very small excerpt of Python 2’s grammar production, which is basically how a string is comprehended by a Python interpreter:

statements -> simple_statement
simple_statement -> small_statement
small_statement -> expression_statement
expression_statement -> test_list '=' test_list
test_list -> test
test -> or_test
or_test -> and_test
and_test -> not_test
not_test -> 'not' not_test | comparison
comparison -> comp_op
comp_op -> 'is'

I tried to extract the minimum required statements possible (and probably screwed up somewhere along the way) from here, and what could I write from it?

1 is 1

With the above, I can’t even add – to be honest; I don’t think I can even use numbers yet. Now try implementing an if statement. This is how I feel when reading through code where people become trigger happy with functions and methods. Provide your methods with a sense of worth; one way of doing that is by having them do more than one line of code before returning. It’s sort of like that friend you call who know exactly why you called him and knows that you’re just going to ignore him after you do what he wants you to. And are all those levels of indirection really needed (ok, maybe when designing a compiler)? I’m not happy because code written this way is harder to read (at least, in linear files), and the CPU isn’t happy because of all the jump statements. Let’s at least try and keep the CPU happy.

Leave a comment