Symbol Naming Strategy for Flash

Symbol Naming Strategy for Flash

My co-worker, Tony Martin, found a weakness in the mx.core.UIObject symbolName pattern that we have been using. It’s really frustrating because we’re already half-way into the project, and I wished I could of known about it at the beginning so I could formulate a less sweeping refactoring change. How many times have you heard that before?

To give you some background, one of the problems with early Flash Development was the fact that visual elements in Flash can be stored as symbols. These symbols can be reused, much like a class can be reused as instances. Early on, designers started making these symbols do common things, and even started associating code with them, the first components. These MovieClips quickly became problem prone because of the lack of initialization order control, and keeping both linkage name and class name in sync. Linkage names were utilized to name a symbol. That way, when you wanted to attach it visually, you had a name to identify it with. Some people would make both the name of the class and the symbol the same, which was a pretty good convention.

ActionScript 2 came along and introduced packages, much like Java. The early framework thus kept the same scenario where your package name was the same as your symbol name. The occasional issue arose where the 64 character limits on symbol names would cause an unexpected refactoring, but other than that, she worked good.

…till today. I’ve seen the questions in the past on the Flashcoders list of how you associate another Symbol with the same class. There are a couple ways. You can either simply put the class in the AS2 class name in the linkage panel, or associate it at runtime via Object.registerClass.

I never understood the point, though. To me, it didn’t make any sense; why would you create a brand new asset, but re-use the old class that had specific functionality? Why not just do a new class, problem solved? I saw one scenario where the mx framework actually did this, utilizing mx.skins.SkinElement in this way. It was an extremely lightweight class that had like 3 properties, and 3 methods. It acted like a UIObject, but didn’t have all the extra baggage.

Today, we’ve coded a generic List renderer, and our design comps show 2 kinds; one that is thick, and one that has no background and is just text and an arrow. Tony, being prudent, asked if we could just use the same class we already wrote. It was a specific class, inherited a lot of nice functionality from base classes, and the only thing we were changing was artwork and animations. Seemed logical to me.

The problem? The static symbolName property. Typically, when extending UIObject, you implement a symbolName property as a static class member. This typically is the same as your class, only a String. You then copy and paste it into both the linkage ID and AS2 class name fields for the MovieClips. That way, all 4 are in sync. The compiler doesn’t check for a missing symbol name, so if it doesn’t work, you misspelled it; basically ensuring you don’t have a magic string. Secondly, you can utilize the symbolName in the attachMovie and ensure you never misspell it, like:

attachMovie ( MyClass.symbolName, "mc", 0 );

The problem is, “static is the new _global”, and you can’t change static on the fly without affecting all other creations of the components. Even if you made it a class property, you’d have the same problem; anytime a new class would be created, it’d be referencing the new symbolName. Could you change it back? Sure… I guess. I mean, Flash Player is single-threaded, so you could technically time it I guess, but that’s not a risk I want to take.

It gets worse when some of our container classes actually depend on this property, and thus you realize your kind of stuck with it.

We built our lightweight lists around the same way the DataGrid works with cellRenderers; you basically pass in a class you want it to “make”. It works like:

my_list.childClass = Label;

It internally knows that it is dealing with our base component class, so knows to look for the symbolName.

So how’d we get around it? Uber-hack:

var newSymbolForClass:Function = function(){};
newSymbolForClass.symbolName = "AnotherListRenderer";
ourList.childClass = newSymbolForClass;

Voodoo, but it works. All the symbolName really is a String that tells attachMovie what MovieClip to attach; it doesn’t care if it’s an anonymous function or a true class.

This does, however, pose the challenge. Now that I finally understand the use case for allowing multiple MovieClip symbols to utilize the same class, how does one utilize the symbolName strategy to get rid of the magic strings, but be flexible enough to support different symbols for the same class? How does this work in container classes that “know” they are dealing with these types of classes?

For now, I’m thinking we’ll keep the above hack, but in the future, it may be better to make it an instance level property. This, however, makes it harder to pass generic classes to the components who will create them in a factory type fashion. They no longer need only the class, but now need to know which symbol to make. Step backwards, but certainly gives the flexibility that design projects need. Forcing people to create a new class just for new artwork is ridiculous, so maybe this is the best compromise.

This is pointless in ActionScript 3 since everything is a class, and there are no symbol names anymore. You’ll have to basically write a parent class that allows multiple child classes to be drawn into it via Composition.

1 Response

  1. ‘Voodoo, but it works. All the symbolName really is a String that tells attachMovie what MovieClip to attach; it doesn’t care if it’s an anonymous function or a true class.’
    Isn’t it safe to say there are no ‘true classes’ in AS1/AS2? A ‘class’ in a prototype language really IS just a function. In AS1 and JavaScript you build a ‘class’ by creating a function and adding prototype methods if you want, or just add properties to the function as static properties.

    ‘This is pointless in ActionScript 3 since everything is a class, and there are no symbol names anymore. You’ll have to basically write a parent class that allows multiple child classes to be drawn into it via Composition.’
    AS3, booyah!