Style guide & best practices for ActionScript 3 (AS3)
Published by Nicholas Dunbar on January 24th, 2011
Goals
When you look at a variable, class or function name, the way that the code is written should clearly denote to you what it is, where it is located, how it’s declared and something about what it does. Our goal is to name constructs in such a way that all these things are instantly apparent. We not only are looking at readable code but efficient and secure code.
Avoid Dogma
Folder structure
Classes
Fonts
All fonts should be saved in a fonts directory. Sometimes you will use a font then break apart the text field to turn it into a shape for a shape tween or another reason. It is suggested that when you do this you note the font name that you used in the layer name where the text is first appears, so that if later the text needs to be manipulated you will remember what font was used. This is also useful when recycling content years later when a new developer needs to customize the text for a new project and doesn’t have the font installed on his machine.
Source images
Primary Naming Guidelines
When writting code native ActionScript is our guide. If classes are always capitalized then your classes will always be capitalized, if they use camel case you use camel case (more on camel case below), etc. Most importantly, an application's naming scheme must be consistent and names should be chosen for readability. This means that names should be understandable words or phrases. The primary function or purpose of any entity should be obvious from its name. The name should not imply that it does any more than it actually does.
Since ActionScript is a dynamically typed language (objects, arrays, XML, dynamic classes), the name should also contain a suffix that defines the type of object being referred to by the name. In general, "noun-verb" and "adjective-noun" phrases are the most natural choice for names. For example:
- Class objects (first letter always capitalized) ScrollBar
- Object Contructor actionscript 3.0 (always put classes in folder named classes, this way a declaration will always be obvious to what it is. The first letter of the constructor is always capitalized. You will see this syntax in native flash constructor objects like new Array() ) – var ThingsList = new ExtendedArray();
- Variable names – waterSpeed (notice first letter of a variable name or function name is lower case, then between each word is defined by using an upper case letter, this is called camel case, and is the standard in ActionScript )
- Variable names – soundVolume
- Frame labels – -hello-world (no spaces or underscores. This helps the user know what kind of data we are dealing with in cases where it’s not obvious. Ex: someLoc_str = “-say-hello"; because it starts with a dash we know it’s a frame label right away, or some kind of prefix can be used for example "label-hello-world", "frame-hellow-world", etc.You choose it, just be consistent. I personally like the dash "-" because it is short )
- ActionScript 2.0 coders should notice the difference between classes and data types. int, unint, void, ect… all start with lower case because it’s a single native data type, rather than a native data type the represents some sort of collection like MovieClip, Array and Classes.
- Avoid using reserved words or language constructs as variable names in external data files, because doing so makes reading and debugging your code more difficult, especially when custom functions are highlighted as native to flash in your code editor.
Classes and object constructors, should be capitalized.
Function names and variables should begin with a lower case letter.
Functions should always use verbs, nouns are objects.
When creating handlers or call backs, choose the suffix handler, proxy, or callback and always be at the back of the function name. ex: userDataHandler();
Handlers or callbacks make code very difficult to debug through just reading the code. It is strongly advised that you avoid using callbacks whenever possible except in the cases where the function call is asynchronous.
When creating listeners, the word listener should always be somewhere in the function name. ex: userDataListener ();
- var = “foo";
- MovieClip = “myMovieClip";
- switch = “on";
- case = false;
- abstract = “bar";
- extends = true;
- implements = 5;
- const BASEURL = http://www.foo.com; //constant
- const MAX_COUNT_LIMIT = 10; //constant
Classes
//
package {
internal class TheObject {
private static var identifier:String = “your mom";
public function changeValue(){
TheObject.identifier = “his mom";
}
}
}
//
Object type |
Variable suffix |
Array |
_array |
Button |
_btn |
Camera |
_cam |
Color |
_color |
ContextMenu |
_cm |
ContextMenuItem |
_cmi |
Date |
_date |
Error |
_err |
LoadVars |
_lv |
LocalConnection |
_lc |
Microphone |
_mic |
MovieClip |
_mc |
MovieClipLoader |
_mcl |
PrintJob |
_pj |
NetConnection |
_nc |
NetStream |
_ns |
SharedObject |
_so |
Sound |
_sound |
String |
_str |
TextField |
_txt |
TextFormat |
_fmt |
Video |
_video |
XML |
_xml |
XMLNode |
_xmlnode |
XMLSocket |
_xmlsocket |
For information on using code hints when they appear, see Using code hints.
The following suffix strings are not supported in flash’s code editor but we feel are necessary for consistency since these are commonly used in different publications.
Component Parameter |
_param |
myParameter_param |
Component |
_cmp |
myComponent_cmp |
Object |
_obj |
myObject_obj |
Boolean |
_bl |
isOpen_bl see more for Booleans below |
Helpful suffixes used with the Flex Builder/Flash Builder IDE.
Mc or DisplayListMc: Since using suffixes is really a Flash IDE practice, Movie clips which show up on stage should still always be suffixed with mc. No _mc because when coding in flex camel case is the standard practice. This allows the programmer to clearly spot objects that are assumed to exist on the stage. It is very confusing when you see a MovieClip being accessed but you don't see its decairation anywhere. This practice saves the programmer time by allowing him/her to see that the MovieClip is being declaired on the stage just by looking at it. You can choose the suffix I don't like DisplayListMc because it is verbose and makes for a lot of typing. Feel free to invent your own but make sure that you are in agreement with everyone working on your code. Mc is very common so I suggest just sticking to that standard. Ex: playersCarGraphicMc
Obj: Dynamic objects should have obj some where in there name so that it is easy to find runtime errors. The use of the Object dynamic class creates slow running and hard to debug code. When you can, use a non dynamic class instead. Ex: mysteryBoxObj
Txt: Text that is found on stage should be suffixed with Txt. This is of course in line with the idea with Mc. Ex: scoreTxt
Btn: Buttons that are found on stage should be suffixed with Btn. This is of course in line with the idea with Mc. Ex: playNowBtn
Passing by reference.
It is discouraged to reference members of another class from inside another. Clear APIs should be defined to pass information back and forth, or a clear event architecture should be established. But when you are in a rush there is nothing like passing a reference to an object into another object, and there is nothing that provokes confusion at a later date. To minimize confusion always finish your variables with Ref example: objRef. Make sure that when you pass the reference to the class it should always be done though an obvious and deliberate function. Always use registerMyClass(instanceOfMyClass) register is commonly used and you can easily spot it. Never pass references like this:
myNewClassInstance.objRef = otherClassInstance.
myNewClassInstance.registerOtherClass(otherClassInstance)
//here is what the function declaration looks like on myNewClassInstance
public function registerOtherClass(otherClass:OtherClass):void{
_otherClassRef = otherClass;
The underscore at the front of variable names.
Naming variables starting with an underscore is a practice from ActionScript 2 that copies Macromedia’s usage to denote objects of the nature of _root or _global and properties of classes like _x. In ActionScript 3 these two usages of the front side underscore are out of date. You now only see the front side underscore for denoting private variables in a class. This can be seen commonly in various developers work, like joey lott’s and danny patterson’s book, actionscript 3 with design patterns.
//this is bad, many programmers reserve this for private members of a class
_mc = this.aMovieClip_mc;
_mc.x = 1;
_mc.visible = true;
_mc = this.anotherMovieClip_mc;
_mc.x = 1;
_mc.visible = true;
//this is good
dumMc = this.aMovieClip_mc;
dumMc.x = 1;
dumMc.visible = true;
dumMc = this.anotherMovieClip_mc;
dumMc.x = 1;
Using the 'this', Class Files, and the front side underscore as prefixes.
Naming Boolean Variables
Start Boolean variables with the word "is" when ever you can (because a Boolean value either "is" or "is not" because of its nature). Therefore, you might use the following for whether a baby is a girl or not (which is a Boolean value).
Naming Interfaces
Starting interface names with an uppercase "I" helps you distinguish an interface from a class. The following interface name, IEmployeeRecords, uses an initial uppercase letter and concatenated words with mixed case, as follows:
interface IEmployeeRecords{}
Naming Getters and Setters
public function get isLoggedInGet():Boolean{
return this.isLoggedIn;
}
public function set isLoggedInSet(isLgdIn:Boolean):Void{
this.isLoggedIn = isLgdIn;
public function get isLogIn():Boolean{
return this. isLoggedIn;
}
public function set isLogIn(isLgdIn:Boolean):Void{
isLgdIn = ! isLgdIn;
this. isLoggedIn = isLgdIn;
This is an extreme example where the programmer might be very confused why when he types someClass. isLogIn = true and then he traces someClass.isLogIn traces he gets false. If the functions are suffixed with get and set then the user knows that something may be happening inside the function call and that they are not looking at direct assignment. It is important to note that if you are trying to obfuscate what is happening inside your code than avoiding a naming convention is appropriate. Even in the debugger getters and setters look indistinguishable from variables. Mainly this functionality was developed for obfuscating functionality and for control of read/write access. If you have no need to control read write or to obfuscate your code then just use someClass.setIsLogin(true).
public function set isLogInSet
Variable names that use or are acronyms
Use semicolons at the end of lines of code
if (someObj.someVar) vs. if (someObj.someVar != null)
Declaring Variables
Import statements
Commenting code
All significant blocks of code should contain headers, here is an example of a possible header: (classes, functions, components, …)
//*******************************
// TITLE: a quick 5-10 word description goes here
// DEVELOPER: this is useless if you are using a versioning system
// DESCRIPTION: a more in depth description on how it works, this should be brief, rely on
// comments through out the code for the details of how the code functions.
// FLASH VERSION: this is optional
//*******************************
Always comment code in an application. Comments are the author's opportunity to tell a story about what the code was written to do. Comments should document every decision that was made while building an application. At each point where a choice was made about how to code the application, place a comment describing that choice and why it was made. An important thing to keep in mind is that you do not want to reiterate your code in your comments. In other words don’t explain your syntax! Explain instead what you are trying to do.
When writing code that is a work-around for an issue with the application, be sure to add a comment that will make the issue clear to future developers who may be looking at the code. This will make it easier to address that specific problem the next time someone encounters it.
Here is an example of a simple comment for a variable:
var clicks = 0; // variable for number of button clicks
Block comments are useful when a comment contains a large amount of text:
/*
Initialize the clicks variable that keeps track
of the number of times the button has been clicked. Blah blah balah!!
*/
Some common methods for indicating important comments are:
// :TODO: topic
Example
/*
:TODO: msw 654321 : issues with displaying large set of data from the database. Consider breaking up the data into smaller chunks for each request.
*/
Indicates that there is more to do here.
// :BUG: [bugid] topic
Shows a known issue here. The comment should also explain the issue and optionally give a bug ID from your bug management system like bugzilla or others, if applicable.
// :KLUDGE:
Indicates that the following code is not elegant, a quick temporary fix or does not conform to best practices. This comment alerts others to provide suggestions about how to code it differently next time.
// :TRICKY:
Notifies developers that the subsequent code has a lot of interactions. Also advises developers that they should think twice before trying to modify it.
// :TEST:
Commenting: variable names that are acronyms
Sometimes your variables will be to long and descriptive so you will have to inevitably use elusive variable names. Key variables should always be declared in a centralized place (like the top of a function) with an included comment that describes the variables function. This becomes particularly important when the variable is an acronym liketimeSlbl. Make sure variables like this have the acronym definition in a comment like.
// time since last byte loaded
Break Point Code
Break point code is where the debugger requires you to put in junk code inorder for the break point to catch. Randomly naming your variables creates clutter in your debugger variables window. If you name them consistantly it will be easier to browse variable lists with minimal disruption. Especially if there are a lot of these variables in the current scope, they will all be bunched together making it easy for the eye to dismiss them in one big block.
if (isDebugCondition){
var breakpoint1:uint = 0;
Swf file names
Strict Data Typing
Use strict data typing with your variables whenever possible because it helps you in the following ways:
* Adds code completion functionality, which speeds up coding.
Error checking
Library layout and Asset Management
The goal of standardizing the naming of symbols in the library is that different resources can be quickly located and the nature of the symbol will be apparent to the developer at first sight. Make MovieClip names clear and understandable. When possible relate the stage instant’s name to the library name (library : car, instance : car_mc). In some situations it’s just good to have everything in one large list so that you can jump to them in the library list alphabetically with shift-‘a’ (the first letter of the symbol). However it is advised to use folders in the following situations. Repetitive graphics should be put in folders similar to the names of their associated movie clips. For example I have imported a sequence of images for an animation footballplayer1,jpg – footballplayer200.jpg. these 200 images should be put into a folder called footballplayer jpgs and the movie that holds the animation should be called football player. Don’t bury your library assets by giving them meaningless repetitive prefixes like putting UI in front of everything or Nav. Ex: NavTop, NavBottom, NavSub1, NavEct ect. This is what folders are for put these under the folder navigation and name them top, bottom, sub1 Ect. If you keep your names unique you can jump to them with the shift button and locate them in the library much faster. Make good use of folders, but do not over use, you can just as easily over organize and bury assets in a maze of nested folders. It is preferable to avoid nesting more than one level deep.
If you build components, organize all custom components into the componentsSomeName folder along with their assets so that they can easily be transported and reused else where. This is particularly important if the component uses linked assets in the library that won’t get transferred by a simple copy and paste of the root of the component. Any time you are using linked library elements they should be packaged with their base movie and corresponding components.
Timeline layout
Developers should avoid using the default layer names (Layer 1, Layer 2, etc.) as this can become confusing. Timeline layers should always be named intuitively. Layers should also be grouped together using folders, where it makes sense. For example, there could be a Script folder in each timeline if your timeline is already crowded with other layers of graphics. Within that folder there will be layers called Labels, Actions, Classes and Functions respectively. Attention to the order that your SWF layers are being loaded which is defined in the publish settings, this effects the functionality of where your functions are being loaded and being called.
ActionScript conventions for timeline coding.
Keep actions together
You should avoid coding in the time line whenever possible. All code should be placed in one location, unless the process of doing this further complicates your code. This is true of timeline coding try to keep as much code as you can in localized and organized spots. This makes the code easier to find and debug. One of the primary difficulties in debugging Flash movies is finding the code. If most of the code is placed in one frame, this problem is eliminated. Usually, the best place to put the code is on frame 1. This of course is only a problem with timeline coding.
When large amounts of code are located in the first frame, make sure to separate sections with comments to ensure readability, with layers and/or as follows:
/*** Button Function Section ***/
/*** Variable Constants ***/
One exception to the practice of placing all the code in frame 1 arises when movies will be preloaded. In an application with preloading movies, placing all the code in frame 1 may not be possible. However, authors should still strive to place all of their code in a centralized location.
For movies that have a preloader, start the actions in frame 2. Use two layers for actions-one layer for functions, and another layer for state dependent actions.
Versioning Control Systems and External ActionScript (.as) Files
Finding objects in the library.
You don’t need to give the full path to the movie name but the movie name should be a unique name in the library. You should prefix library class names that have no external as file with some sort of indicator so that it is known that the symbol is found in the FLA. For instance F for FLA or Lib for library. An example of this would be when I have created a symbol in the library called FBackground when I pull this symbol from the library in my .as file it is instantly obvious that the symbols implementation is in the FLAs library. If it’s placement in the FLA is at all ambiguous you should have a comment in your .as file at the top that informs the user of its particularities. For example:
//found in: someFile.fla : library item wheel, found on stage(timeline) under (/holder_mc/wheel_mc)
// lib item wheelBarrel, found on time line under (/holder2_mc/wheelBarrel_mc, /holder2_mc/wheelBarrel2_mc)
//found in: someOtherFileTo.fla : library item ect ect
Developers often only use in-line code in the frame action to define the state of the application. This practice is discouraged.
For proper code organization, use key frames to delineate application states. Place any actions necessary for a particular state into a function and then call the function as the only action done in that keyframe.
Optimizing Your Code
Remember the following guidelines when you optimize your code:
1.) Avoid calling a function multiple times from within a loop. It is better to include the contents of a small function inside the loop. Function calls are the most time intensive single operation. If the code is only used once then use in-line code. However this is not acceptable if it renders the code difficult to read where it is crucial that the code is readable.
* Use native functions when possible. Native functions are faster than user-defined functions.
2.) Don't overuse the Object type. Data-type annotations should be precise, because it improves performance. Use the Object type only when there is no reasonable alternative.
3.) Avoid using the dynamicObject[“aMember"] or array access operator to access the same piece of data over and over. Often, setting the local reference once is preferable and more efficient. aMemberRef = dynamicObject[“aMember"]; then you can call your access over and over on aMemberRef.
4.) Assign the Array.length to a variable before a loop to use as its condition, rather than using myArr.length itself.
5.) Focus on optimizing loops, and any repeating actions. Flash Player spends a lot of time processing loops (such as those that use the setInterval() function or onEnterFrameevent). Don’t let onEnterFrames run needlessly.
Security
Always protect your SWFs from imports with a good password.
Caution: Never store any information or code in a SWF file that you don't want users to see. It is easy to disassemble SWF files and view their contents using third-party software. With web applications you can put a lot of your functions in scripts on the server and just make calls to them from flash making each function a black box.
Use the final keyword for class methods: Making a class or a method final prevents other programmers from extending the class or overriding the method for the purpose of examining the class’s internal structure. Such prevention is considered one of the ways to safeguard an application from being maliciously exploited. Keep in mind that on the other hand, others argue that final methods and classes contradict the general object-oriented principle of polymorphism, wherein an instance of subclass can be used anywhere an instance of its super class is expected.
Perhaps the most obvious security measure for your application to add is a cross-domain policy, which prevents unauthorized domains from accessing your assets.
For more info: http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_print.html
- Macromedia’s white paper “ActionScript Coding Standards" written by Michael Williams (March 2002)
- ActionScript 2.0 Best Practices by Jen deHaan (20 February 2006) http://www.adobe.com/devnet/flash/articles/as_bestpractices.html
- Essential Actionscript 3.0 by Colin Moock