Home > Blogs > Applying Refactoring Techniques, Part 1

Applying Refactoring Techniques, Part 1

By  Oct 21, 2008

Topics: Programming

It would not be honest for me to say that I Refactoring introduced me to refactoring techniques. Like most programmers, I have been refactoring code almost for as long as I have been writing code. It is much like GoF’s Design Patterns. You read the patterns and you recognize all of the times that you have been using that pattern, even if you had not known it by name.

Now there are definitely times where the explanation of the refactoring technique (or pattern) provides greater insight. Maybe you realize that there were side effects that you had not dealt with in a systematic approach in the past, but now you will. And of course there may be techniques that you had never needed to use. Those techniques are more rare, and probably less useful. After reading Refactoring, you definitely tend to take a more structured approach, and that is a good. thing. So I thought I would take some very recent cases where I needed to refactor code and at the very least perform some categorization of what I did, based on Fowler’s book.
    All of the example that I am going to give are in ActionScript. That is mostly because it is what I have been using. It is also because of tooling. Let me explain that part. I work a lot in Java, not as much as I used to, but I would still call it my “primary” programming language. If I had to write some code that my life depended on, I would do it in Java. I use Eclipse a lot, and Eclipse has a lot of refactoring techniques built in. I think IntelliJ first started this trend, Eclipse picked it up and ran with it. The current version of Eclipse (Ganymede) has 21 refactoring techniques built in. Many of these are straight out of Fowler’s bok: Extract Method, Extract Local Variable, Introduce Parameter Object, Push Down, Pull Up, etc.
    For ActionScript, I use Adobe’s Flex Builder. It is based on Eclipse. ActionScript 3 has many of the same language features as Java, like static typing, inheritance, etc. So it should be possible to automate many of the same refactoring techniques that Eclipse automates for Java, but so far that’s not the case. I am sure the folks at Adobe are working on this, maybe in Flex Builder 4... Anyways, refactoring is manual in ActionScript, but one day it will probably be automatic.
    The first example is an open source application I created called JsonViewer. It takes a JSON string and displays it as a tree. I built this to help me debug applications that used JSON, as it can be hard to drill deep into a complex JSON structure. Here is a screen shot of the application.

As you can see from the screenshot, the user can copy in some JSON text in to the text box, and then the JsonViewer turns that into a tree structure that can be traversed and examined. As I said earlier, I built this application just to help me do my job, but others found it useful. So I released it. Sure enough people started downloading it, and I got feedback. I mostly got complaints that were caused by AIR versioning, but I also got a feature request recently. They wanted a URL bar where they could put in the URL of a JSON object, and the app could download it and display it. This seemed like a great idea, and one that should be easy to do. However, it turned out to require some refactoring.
    The code that caused the tree to be displayed was an event handler that was triggered by clicking on a button. Here is the original code.

private function showJson():void
{
    valueBox.text = null;
    try{
        var jsonObj:Object = JSON.decode(jsonInput.text);
        var jsonModel:Object = makeModel(jsonObj, "ROOT");
        jsonTree.dataProvider = jsonModel;
    } catch (e:Error) {
        Alert.show("Error parsing JSON: " + e.message);
    }   
}
The jsonInput object is a TextBox. This is where the user inputs the JSON string. This gets parsed into an ActionScript object using Adobe’s corelib. There is a makeModel function that tweaks this object so that is suitable for binding to the Tree control (the jsonTree object in the above code.) The code here is tied to the event handler, so it can be reused as is. It needs to be refactored.
    This is really a pretty simple refactoring. The code to populate the tree needs to be extracted into its own method. This is the classic Extract Method. Here is the refactored code:

private function showJson():void
{
    valueBox.text = null;
    displayTree(jsonInput.text);   
}
private function displayTree(json:String):void
{
    jsonInput.text = json;
    try{
        var jsonObj:Object = JSON.decode(json);
        var jsonModel:Object = makeModel(jsonObj, "ROOT");
        jsonTree.dataProvider = jsonModel;
    } catch (e:Error) {
        Alert.show("Error parsing JSON: " + e.message);
    }   
}
All of the tree code was extracted into the displayTree method. The old showJson method now delegates to displayTree. Now it is easy to re-use displayTree, as shown below.

private function loadUrl():void
{
    var loader:URLLoader = new URLLoader(new URLRequest(urlInput.text));
    loader.addEventListener(Event.COMPLETE, function(e:Event):void{ displayTree(loader.data); });
    loader.addEventListener(IOErrorEvent.IO_ERROR, function(e:Event):void{ Alert.show("Error retrieving URL: " + urlInput.text); });
}
Notice the second command. It creates an anonymous event handler for when the URL entered by the user loads. This anonymous function then calls displayTree. The refactoring worked!

Become an InformIT Member

Take advantage of special member promotions, everyday discounts, quick access to saved content, and more! Join Today.

Other Things You Might Like

Xamarin Unleashed

Xamarin Unleashed