Posted on Tuesday 3 May 2005
I have been busy the past few days cleaning up and debugging a movie a client sent me that I can only describe as horrible. In-line code everywhere, inconsistent naming, _root references galore, three frame loading schemes of the quasi-ifFrameLoaded variety, everything you could possibly do wrong is there. This isn't a small movie either; we're talking about a complete FlashCom app with about 2000 lines of code. Here was part of the main timeline (look at all the little a's, it's scary):

This is the second time I've attempted to clean up a movie of this size, the first being one of my one movies back when I was a script kiddie. The first advice I want to give is DON'T THROW AWAY THE CODE. Don't start over. It's a bad idea. The idea is if the movie is working at least partially, then there's probably a lot of workable code in there. In the particular movie I was debugging, a typical FlashCom Breeze-like app for video conferencing, for example, there is a whiteboard feature. It's relatively trivial to create a whiteboard in FlashComm but as it turned out the methods used in this case were quite interesting; the data transfer was optimized and the drawing code would have been beautiful, if only it wasn't in a five frame movieclip as inline with no naming scheme. It would have taken me a lot more time reimplementing the functionality than it did repackaging. As a side note, keep a copy of all the original files for reference.
The second advice I want to give you is DO IT STEP BY STEP. The last time I attempted a serious repackaging I took all of the code out of the movie and wrote this on frame 1 of the main timeline:
ctrl = new MovieController(this);
Well, switching from 100% bad AS1 code to 100% good patterns-based AS2 code in a single step turned out to be a complete nightmare; for 20 hours the movie did not even compile. This is even though I wrote the original code myself and I knew it in and out.
The other thing is that if you're going to make it better, you're probably going to break it several times while you're working at it. So trace like you've never traced before, and consider getting help from two LocalConnection-based marvels: the NetConnection debugger and John Grden's AdminTool. NetDebug.trace will save your marriage in particular.
Some steps you will want to take (not exactly in the order shown, but you will get the general feel):
- #include everything and paste the scripts in a .as file. Eventually you will want to make your code all class-based, but for the time being make yourself a favour and break out of the Flash IDE. Open up the files in SE|PY or Eclipse or whatever your favorite actionscript editor is.
- Do a quick case sensitivity check. This is done simply in SE|PY with Tools > Case sensitive check.
- Create a Settings class and store all of the hard-coded values in the old code, like strings and coordinates in static variables in that class.
- Identify problematic components and use that as an excuse to redo the work correctly. For example, the client says: when my user rolls over a button in the whiteboard area, the tools should stop drawing. You respond: let me make a tool class, a whiteboard class, and a bunch of subclasses for the different tools, and then I'll attack that problem. It sounds dumb but well organized code is several orders of magnitudes easier to debug.
- Regarding the last example, a sane workflow would be to isolate the whiteboard code and then put it into its class. When that works, you will want to move the tool code to separate classes. At that point it may become obvious that all of these tools use the same kind of functionality, and you create a parent class that includes a basic framework. When that works, you will want to move all of the code you left in the original class where it belongs, for examples SharedObjects or data specific in the tool classes. Test between each step.
- If you have issues with a multiple-frame movie layout like above, put the code in each of the frames in different functions and chain them. Then when the least plausible number of frames is achieved, delete the unnecessary frames.
- Use mx.utils.Delegate everywhere you see direct assignments to event handlers
- Remove as much direct references to _root as is possible. Store the reference to _root in one class, either the Settings class or a controller class. Using mx.utils.Delegate should help you free the need for references to _root. This way when your client comes back to you and says "I need to load it in another movie", you won't start crying.
- Transform loadVariables to LoadVars. Start by switching to LoadVars for just the callback mechanism and then stupidly reinject the variables in _root. When that code becomes part of a class then create private vars for the data.
- Compartmentalize where logical into classes.
- Prepare yourself for patterns but don't implement them yet. A favourite of mine is extending EventDispatcher in Model-like and View-like classes.
- When there is less than around 250-500 lines of code left in the main timeline, it's time to put that in a controller class. At that point you may realize that some of that code should be in another class. Do that. Create an instance of the controller on frame 1 of the main timeline. Enjoy a moment of deep inner peace.
- Only then is it advisable to start thinking about patterns or frameworks and whatnot. Since you have already plugged in some hooks for that purpose it shouldn't be overly difficult to clean up the code in obvious ways.
- When your movie is beautifully laid out, then you can start thinking about optimizing it for speed, but it better work perfectly before you do that.
- Optimize for filesize by deleting unused components in the library setting compression settings for jpgs accordingly, or loading stuff externally where logical.
After having done that, which in my experience takes about an hour for anywhere between 50 and 200 lines of code, depending on damage, Earth's karma should have improved significantly. Look at yourself in the mirror and smile, then cry. Then sleep. Then think about working on AMFPHP eventually (okay, maybe that last part was just for me then).


