Recent

Support Wikipedia

Calendar

Navigation


On a New Road

Refactoring considered harmful, sometimesFriday February 18, 2011
Refactoring covers a broad swath of techniques to make code cleaner, more reliable, more maintainable, ... But sometimes, these attributes fight against each other. The usual attribute that causes trouble is "more performance". For example, consider factoring out a loop-invarient boolean:
for(....) {
    ...
    if(b) A;
    else B;
    ....
}
when b is loop-invarient, this can become:
if(b)
    for(...) {
        ...
        A;
        ...
    } else
    for(...) {
        ...
        B;
        ...
    }
Depending on a wide variety of factors, this can be faster. Although it might be slower. Careful benchmarking is required :-)

It is certainly less maintainable and less clear. When you see a pice of code that is the result of such a transformation, it's often difficult to tell that the two loops are related. If a bug is found in any of the replicated pieces of code, it has to be fixed in *both* places. Testing gets more complicated because the replicated code paths have to be independently (and somewhat redundantly) tested. To compound the problem, if you have (for example) multiple loop-invarient booleans, the code expansion is exponential (!!) in the number of factored-out booleans. This can get pretty insane pretty fast. I've seen instances where folks have tried to be clean about these transformations by clever use of C macros, but this can get really messy. And the code explosion can be dramatic: I got pulled into this problem years ago when someone checked a new line-drawing routine into the SunOS kernel (that's what Solaris was called before the SVr4 merge) that was bigger than the whole rest of the kernel. But it was fast. I got the job of fixing it :-(

For most people, this class of transformations should be avoided like the plague they are. But for folks like me who all too often need to do intense tuning, they are necessary. Can they be made cleaner? It's a pity that refactoring is viewed purely as something done in an IDE. Sometimes, you can do cool things if the refactoring is expressed in the language. But that's another blog entry.


PS.It's "build season" for the FIRST Robotics Competition. A couple of years ago Sun worked with FIRST to put a JavaVM on the industrial automation controller that they use. Before this, programming the robots was almost impossible. The contest turned into all-mechanical projects, with very little software. With the JVM (and the ability to debug running robots) they've become much easier to program. This year I'm mentoring the team at my younger daughter's school. I'm having a great time helping these kids write control software that works with a pile of motors and sensors. Can't wait to see it all work.
PPS.The RSA conference is in town, which was fun to wander through. It's hard to believe that so many companies making firewalls can succeed. The hard part for me is that I've become something of a magnet for former sun customers and partners to tell their tales of the shenanigans that the Oracle sales force engages in to trap customers. One got caught in a weird shell game where the oracle team was working hard chasing him around town to prevent him from talking to another vendor - physically interposing themselves between the vendor and the customer. As frustrating and pathetic as the stories are, I find them easy to manage by treating them as humor. It is outrageously goofy the stunts that get pulled (although the 5x to 20x price increases often forced on customers are infuriating - talk to anyone "upgrading" from Sun Identity Manager).
Comments:

James, An old friend of mine, from the days when we worked together in industrial automation, has been coaching a FIRST team for a few years. He has been teaching them the programming concepts used in industrial control (very different!), with very good results, despite the lack of Java support. It would be very interesting to marry those concepts with the debugging and robustness goodness of the JVM.

Posted by Ron Ten-Hove on February 18, 2011 at 04:26 PM PST #

James, I had the "pleasure" of being an Oracle "SE" for 5 months after 2/15/2010. {Can you believe a year has past?} It is not about how to help the customer, it is about how to harass the customer. Grant it, Sun could have used some business savviness, but this goes WAY beyond ethical treatment of those you sell to. It saddens me too no end that Solaris, Java, Sparc, et al is in Larry's hands... I did like the this register article about Oracle's glassfish success story!!! http://www.theregister.co.uk/2011/02/15/oracle_glassfish_hudson/

Posted by Jim on February 18, 2011 at 04:37 PM PST #

You ask if these transformations can be made cleaner. I usually do this: if(b) {action = A;} else {action = B;} for(...) { ... action; ... } But I suppose the context of your problem is more complex than what I can imagine. Perhaps you are implicitly forbidding function/subroutine calls.

Posted by 71.202.111.191 on February 19, 2011 at 03:09 AM PST #

I think it's spelled "loop-invariant", with an "a".

Posted by Matt Alexander on February 19, 2011 at 07:31 AM PST #

Some say that most 'if's can be replaced by inheritance... and the JVM will inline all the right calls. Anyway, it is still a variation of a solution from comment by '71.202.111.191'. Closures and MethodHandle-s will go a long way towards making that kind of programming viable.

Posted by tkowalcz on February 19, 2011 at 09:23 AM PST #

If it is an invariant, and it is faster by keeping the condition out of the loop, couldn't the compiler find that out? If clean code must be transformed into something not so clean, most of the time this is a workaround to some other issue in the infrastructure (e.g. missing optimizations in a compiler/execution environment). Of course, the example was simple, and it is no easy task to do this optimization if, e.g. the condition is more complicated - a method call to somewhere else, taking but not using the loop variable for instance.

Posted by Alex on February 20, 2011 at 04:01 AM PST #

I am waiting for that blog entry :)

Posted by Prince on February 20, 2011 at 12:59 PM PST #

Real people, find real solutions. Be real, be sober.

Posted by WSmart on February 20, 2011 at 08:26 PM PST #

Hi, James. I wasn't current with the on-goings of Java recently, so I couldn't post this in your other blogs. I had something to say about Java and what I think could be done about it. Java by far is the best language I have ever developed in. By that I mean the language semantics, design and the set of APIs it includes. I really suggest you to design a new language that targets the LLVM architecture. I was designing something similar and will be releasing it in GNU opensource licence. The language I chose was ofcourse Java-like. I would want your inputs on that. Java has had a major impact in the programming world and will never die. God bless Java and god bless you man. OpenSource will keep Java alive and off from the crutches of Evil-Oracle.

Posted by Aniket on February 20, 2011 at 10:23 PM PST #

That is very valid. Don't just blindly do things. Take care of everything while performing any action. Probably getting suggestions from colleagues brings the best.

Posted by Sandeep on February 21, 2011 at 03:02 AM PST #

Very good advice.

Posted by Gautam on February 21, 2011 at 01:16 PM PST #

Well yes, I think bottom line about refactoring is the same as it is about any other tool / technology / approach you could come up with: It's just as good as the person making use of it, same as the IDE should "just" be a tool to get you rid of boring / time-wasting job of _doing_ routine tasks yet not compensate for lack of _knowing_ how to actually get these done. So, eventually "don't refactor unless you really _know_ why to do it" seems a worthy strategy... ;)

Posted by KR on February 22, 2011 at 01:45 AM PST #

IBM wants to refactor their Sun acquisition strategy.

Posted by Jon on February 22, 2011 at 08:15 AM PST #

Post a Comment:
Comments are closed for this entry.