Code Refactoring

Code Refactoring

Don’t ask me why I’m writing this post. It’s bound to get me into trouble.

Anyways…

What Is Refactoring?

Code refactoring (according to me) is taking a piece of code, code that is already working, and revising it – typically in small steps – to make it more readable, more efficient in execution, or otherwise “better” in one or more ways. Folks expect that such pieces of code will exhibit the same (unchanged) behaviour before and after refactoring.

Aside: This “invariant behaviour” itself seems arguable, as in practice many refactorings leave the code with different “-ilities” (non-functional characteristics – for example, execution efficiency). I suggest claims for such equivalence (of behaviour) are, in general, bogus. “Passes the same tests” is not a great yardstick – how many teams have a suite of tests checking all “-ilities”?

Refactoring is Waste

Given that the piece of code in question is already working, then doing more work on it could be construed as waste (i.e. not adding any value). But hang on. There’s more to it than this.

Firstly, “working” is a relative term. In the Antimatter Principle vernacular, “working” means “meeting some folks’ needs, to some extent”. We can always meet folks’ needs better. So the question then becomes, “when to stop?”. When is any piece of code “good enough”? We can really only answer this question when we have some general understanding of what “good enough” means, for each and every person involved.

Aside: How does your team go about soliciting and sharing information on what “good enough” means?

Why Not Make It Right First Time?

Well, there are some valid reasons. Cognitive load perhaps being the most relevant. Many coders just can’t always get their head around every aspect of the code they’re writing, all at the same time. Many find it necessary, at least sometimes, to defer some considerations – such as performance or readability – until they’re got something roughly “working”.

And then there’s the question of coders’ competence, and intellect, as well as the working environment and coders’ states of mind, from moment to moment.

So, for many coders, right-first-time is just beyond their present capability-in-the-moment.

All this doesn’t change the basic fact that refactoring is waste (muda, in japanese). It does beg the question, though, as to whether it is type I or type II muda:

  • Type I muda: Non-value-added tasks which seem to be nevertheless necessary.
  • Type II muda: Non-value-added tasks which can be eliminated immediately

Why Bother with This? Isn’t it a Storm in a Teacup?

My ha’penn’orth: If we choose to regard refactoring as muda, then we have our eyes open to reducing it, to writing better code on our first attempt, learning and finding other, less wasteful means to meeting folks’ needs, and getting progressively better at our craft. If we choose to see refactoring as part of our regular toolkit of practices, we may be less inclined to search for better ways, and more inclined to just live with it.

And, honestly, the whole “what is waste” question from the Leanheads seems contrived and mostly arbitrary when it comes to drawing a waste/no-waste line. IMO there’s not so much a clean line as a broad and fuzzy overlap between what is and what isn’t value-adding, especially when one considers the needs of all stakeholders, and not just the needs of the “customer”. See also “What is value”.

– Bob

Postscript

[29 March 2015]

What is “good enough”? Generally, when the stakeholders each  say “that’s good enough for me”. And how might we get to such a point? By showing them stuff, allowing them to play with it, work with it, and seeing to what extent what we have given them, to date, meets their needs.

Given we may from time to time give them stuff they’re not so happy with, and choose to try again, I’m minded to ask “how can we minimise the effort and investment in each ‘candidate release’ whilst maximising the relevance of said release?”.

7 comments
  1. dancres said:

    “Passes the same tests” is not a great yardstick – how many teams have a suit[e] of tests checking all “-ilities”?

    A suggested refactoring: suit becomes suite 😉 [Done, thanks – Ed)

    Nice write-up.

  2. Interesting. When we’re practising TDD with katas, a common practise when following the Red, Green Refactor, is at the green stage. We ask ourselves, how can we get to green with the simplest, least effort change. Maybe a line or so. If it’s too big a change it means we need to comment out that test and refactor ourselves into a position where it’s easy to make that change and get our new test to pass.

    Following this logic, our refactoring becomes more focussed, almost using triangulation as our motivation. We also have an end goal in sight or “when to stop”.

    Very thought provoking article. Thanks.

  3. johnicholas said:

    One perspective on refactoring is that refactoring is what programmers call algebraic manipulation, just like “line” means “a rope on a boat”.

    Algebraic manipulation is a form of thinking explictly. Thinking explicitly means using an external memory, like a piece of paper, as a cognitive aid; it’s very valuable for dealing with ideas that are too big to fit in your working memory. Sometimes this is chewing them (from external memory into chunks in long-term memory) until you can deal with them.

    Algebraic manipulation also consists of bouncing back and forth between pure formal manipulations (such as an application of distributive law) and informal, domain-specific interpretations. For example, a physicist might explain centrifugal force by writing down equations without centrifugal force, doing some manipulations, and then interpreting the result as describing a world with centrifugal force. The physicist translated informal language to formal language, performed domain-independent refactorings on it, then translated the formal language back to informal.

    Analogously, a programmer skilled in a particular idiom may be able to come to a particular problem domain, understand it partially, translate their partial understanding into formal code, manipulate the formal code using problem-domain-independent refactorings, and then interpret the resulting code as suggesting a different understanding of the original domain.

Leave a comment