0

In this case, the site is an internal website that is only able to be viewed on IE6. The goal is get it viewable in IE9. There are several IE only propriety scripting such as using xml data islands, accessing document elements by dot notation, i.e., resulttable.style.display = "block";, etc... The aforemention is probably a bit superfluous to the problem at hand, but it could provide some insight.

Throughout the website, there is a huge number of JavaScript methods which are quite large and are hard to debug. To give you an idea, there are upwards of 100 JS files averaging around 1000 lines each.

The following is an actual method with all of the names/logic omitted. All of the return values are dependent on previous logic:

function someMethod() {
if (stuff) {
    // operations
    if (stuff) {
        // operations
        for (loop) {
            // operations
            if (stuff) {
                // operations
                if (stuff) {
                    // operations
                    for (loop) {
                        if (stuff) {
                            // operations
                        }
                    }
                    // operations
                }
                else {
                    // operations
                    if (stuff) {
                        // operations
                    } else {
                        // operations
                    }
                }
                // operations
            }
        }

        // operations

        if (stuff) {
            // operations
            if (stuff) {
                // operations
                if (stuff) {
                    // operations
                    for (stuff) {
                        // operations
                        if (stuff) {
                            // operations
                        } else {
                            // operations
                        }
                    }
                    if (stuff) {
                        // operations
                        if (stuff) {
                            // operations
                            for (loop) {
                                // operations
                            }
                            // operations
                            for (loop) {
                                if (stuff) {
                                // operations
                                }
                            }
                        }
                        // operations
                        if (stuff) {
                            // operations
                        }
                        return something;
                    }
                    else {
                        // operations
                        return something;
                    }
                }
                else {
                    // operations
                    if (stuff) {
                        // operations
                        return something;
                    }
                    else {
                        // operations
                        if (stuff) {
                            // operations
                        }
                        // operations
                        return something;
                    }
                }
            }
        }
        return something;
    }
    else {
        // operations
        return something;
    }
}
return something;
}

When dealing with a legacy website, what advice would you have breaking down JavaScript methods into more manageable pieces?

Disclaimer: My JS skillset is on the average side of things. And we'd like to steer clear of JQuery for now.

Metro Smurf
  • 37,266
  • 20
  • 108
  • 140
  • jQuery will do these lots of ifs for you (I'm assuming that these ifs are related to each browser peculiarities as you said), so I think that should be very good to learn it and put it in use to refactor your code. – davidbuzatto Jul 18 '12 at 03:27
  • I suggest you use a tool. See my [question](http://stackoverflow.com/questions/11364605/procedure-or-tool-to-refactor-section-of-javascript-to-function) and the answers provided – OnesimusUnbound Jul 18 '12 at 03:29
  • @davidbuzatto - these are large logic flow statements; nothing to do with browser peculiarities. Maybe the post didn't convey that, but the current site was designed for IE6, no other browsers. – Metro Smurf Jul 18 '12 at 05:00
  • I don't really think this is specific to javascript. If a method is too large, split it into several logical methods to make it more readable. – Evan Trimboli Jul 18 '12 at 05:03
  • @OnesimusUnbound - PHPStorm/WebStorm are good editors. I'm looking for good ways of dealing with large logic flow statements in JS. There really isn't a "refactor this big statement" in these editors. So, editors aside, the question is more about how to fundamentally deal with large JS methods. – Metro Smurf Jul 18 '12 at 05:03
  • @EvanTrimboli - I do believe this is JS specific. If this were C#, Java, etc.., it'd be much easier to break down into classes. As I mentioned, my JS skills are intermediate at best; so good pointers for dealing this in JS would be great. – Metro Smurf Jul 18 '12 at 05:05
  • I don't think so. You can write classes in JS, you can extract portions of code into logical methods. The principles are exactly the same. – Evan Trimboli Jul 18 '12 at 05:08
  • 1
    First of all, I would start creating namespaces for each js file and filling these namespaces with only the functions of that file. Something like: var MyNamespace = {}; MyNamespace.myFunction1 = function() {}; And so on. With this, I would start to refactor each function, extracting blocks that are common for the entire system and inserting them in a Utils namespace for example and blocks that are specific to the namespace that I'm working. After the extraction, I would start to refactor every function, using no proprietary capabilities. To finish, I would modularize more the result. – davidbuzatto Jul 18 '12 at 05:09
  • Of course, you can create classes, etc. You can use ExtJS (www.sencha.com) to help you with it (and the namespaces too). As your application is a commercial one, you will need to buy a licence of the framework, but I think it worth the money. – davidbuzatto Jul 18 '12 at 05:11

1 Answers1

1

You could simply break someMethod() into individual functions where the logic can be repeated.

Also without looking into the specific logic you have and finding the patterns that best fit the logic some general patterns that may help are

The Module pattern e.g.

var MyModule = function() {
    function privateFn() {
    }
    function publicFn() {
    }
    function doWork(args) {
    }

    return {
        publicFn: publicFn,
        doWork: doWork,
    };
}();
MyModule.doWork({ param1: 'test', param2: true});

Prototypal inheritance can be used similar to classes in c#/Java e.g.

var MyClass = function(args) {
    this.prop1 = 'test'
    this.prop2 = args.param1;
};
MyClass.prototype.doWork = function(args) {
};
var myInstance = new MyClass({ param1: 'test' });
myInstance.doWork({ param1: true });

You can organise these using namespaces e.g.

if (window.MyNamespace === undefined) window.MyNamespace = {};
MyNamespace.MyModule = function () { ... };
MyNamespace.MyClass = function () { ... };
MyNameSpace.MyModule.doWork();

Additional patterns that may help can be found here http://shichuan.github.com/javascript-patterns/

Chris Herring
  • 3,675
  • 3
  • 33
  • 50
  • These are good approaches; I wasn't entirely aware of using JS in a class based structure. In your first example of the `Module Pattern`, you've included `privateFn`; is that a truly private method that is only accessible within `MyModule`? I'm not sure I see how it's any different than `publicFn`. How are they accessed differently? – Metro Smurf Jul 18 '12 at 13:26
  • Great link to the js-patterns, btw! – Metro Smurf Jul 18 '12 at 13:27
  • The module pattern creates functions that are scoped within the wrapping function. The return from this method includes only the functions you want to expose therefore the other functions are not available from the MyModule object. See http://jsfiddle.net/chrish/Wvh2H/ for example – Chris Herring Jul 18 '12 at 23:30