AS3 Coding Standards

The AS3 coding standard shares the same baseline as the PHP coding standard, but has some new rules that are specific to the AS3 programming language. The AS3 related portions of this standard document mainly come from the |Flex SDK coding conventions and best practices document.

Note that not all rules come from it since some of them were conflicting with the general coding standards of Structured Dynamics opensource projects.

= Language Usage =

Encoding
All the AS3 and MXML files should be encoded in UTF-8

Indenting and Whitespace
Use an indent of 2 spaces, with no tabs.

Lines should have no trailing whitespace at the end.

Files should be formatted with \n as the line ending (Unix line endings), not \r\n (Windows line endings).

The width of a code page has to be 120 characters wide.

Operators
All binary operators (operators that come between two values), such as +, -, =, !=, ==, >, etc. should have a space before and after the operator, for readability. For example, an assignment should be formatted as foo = bar; rather than foo=bar;. Unary operators (operators that operate on only one value), such as ++, should not have a space between the operator and the variable or number they are operating on.

Statements
Terminate each statement with a semicolon. Do not use the optional-semicolon feature of ActionScript 3.

Do this:

a = 1; b = 2; c = 3;

Not this:

a = 1 b = 2 c = 3

String Concatenations
Always use a space between the plus sign and the concatenated parts to improve readability.

foo = bar + "test"; foo = "test" + bar; foo = bar + "test";

Hexadecimal Values
Use a lowercase x and uppercase A-Z in hexadecimal numbers.

Do this:

0xFEDCBA

Not this:

0Xfedcba

Always write an RGB color as a six-digit hexadecimal number.

Do this:

private const BLACK:uint = 0x000000;

Not this:

private const BLACK:uint = 0;

Indexes
When dealing with indices, use the value -1 to mean “no index”.

String literals
Use quotation marks (double quotes), not apostrophes (single quotes), to delimit strings, even if that string contains a quotation mark as a character.

Do this: "What's up, \"Big Boy\"?" Not this: 'What\'s up, "Big Boy"?' Use \u, not \U, for unicode escape sequences.

Array literals
Use Array literals rather than new Array.

Do this:

[]

Not this:

new Array

And this:

[ 1, 2, 3 ]

Not this:

new Array(1, 2, 3)

Use the Array constructor only to allocate an array of a prespecified size, as in new Array(3), which means [ undefined, undefined, undefined ], not [ 3 ].

Object literals
Use Object literals rather than new Object.

Do this:

{}

Not this:

new Object

And this:

o = { a: 1, b: 2, c: 3 };

Not this:

o = new Object; o.a = 1; o.b = 2; o.c = 3;

Or this:

o = {}; o.a = 1; o.b = 2; o.c = 3;

RegExp literals
Use the literal notation rather than constructing a RegExp instance from a String.

Do this:

var pattern:RegExp = /\d+/g;

Not this:

var pattern:RegExp = new RegExp("\\d+", "g");

XML and XMLList literals

Use the literal notation rather than constructing an XML instance from a String.

Do this:

var node:XML = ;

Not this:

var node:XML = new XML("");

Use double-quotes rather than single-quotes around XML attribute values:

Do this:

var node:XML = ;

Not this:

var node:XML = ;

Class literals
Use a fully-qualified class literal only if necessary to disambiguate between two imported classes with the same unqualified name.

Do this:

import mx.controls.Button; ... var b:Button = new Button;

Not this:

import mx.controls.Button; ... var b:Button = new mx.controls.Button;

But here a fully-qualified name is required and therefore qppropriate:

import mx.controls.Button; import my.controls.Button; ... var b:Button = new mx.controls.Button;

New Operator
Use parentheses after the class reference, even if the constructor takes no arguments.

Do this:

var b:Button = new Button;

Not this:

var b:Button = new Button;

Control Structures
Control structures include if, for, while, switch, etc. Here is a sample if statement, since it is the most complicated of them:

if(condition1 || condition2) { action1; } elseif(condition3 && condition4) { action2; } else { defaultaction; }

No space between the control structure's name and the open parenthesis. One line per open/close bracket.

You have to always use curly braces even in situations where they are technically optional. Having them increases readability and decreases the likelihood of logic errors being introduced when new lines are added.

For switch statements:

Do this:

switch (condition) { case 1: {   action1; }   break;

case 2: {   action2; } break;

default: {   defaultaction; } break; }

Not this:

switch (condition) { case 1: action1; break;

case 2: {   action2; } break;

default: defaultaction; break; }

Function Declarations
ASDoc doesn't create documentation from private function. However, ASDoc should always be written for all kind of functions:


 * Private
 * Protected
 * Public

ASDoc is used for both inline code documentation and publishable code documentation. It is the reason why even private function have to be documented with ASDoc comments.

Variable/Member Declaration
Write a type annotation for every constant, variable, function argument, and function return value, even if the annotation is simply :* to indicate “no type”.

Do this:

var value:*;

Not this:

var value;

Use the narrowest type that is appropriate. For example, a loop index should be a int, not a Number, and certainly not an Object or *. As another example, a mouseDownHandler should declare its argument as event:MouseEvent, not event:Event.

Use int for integers, even if they can't be negative. Use uint only for RGB colors, bit masks, and other non-numeric values.

Use * only if the value can be undefined. You should generally use Object rather than *, with null being the “object doesn't exist” value.

If you declare something to be of type Array, add a comment of the form /* of ElementType */ immediately after Array indicate the type of the array elements. A future version of the language is likely to have typed arrays.

Do this:

var a:Array /* of String */ = [];

Not this:

var a:Array = [];

And this:

function f(a:Array /* of Number */):Array /* of Object */ {   ... }

Not this:

function f(a:Array):Array

All members that are declared have to be initialized. If the member shouldn't be initialized with any specific value, then we have to initialize them with "empty" values, by example:

An empty string:

public var foo:String = "";

An empty integer:

public var foo:int = 0;

An boolean value should always be initialized to false:

public var foo:Boolean = false;

An non-existing class instantiation:

public var foo:Object = {};

A empty class instantiation:

public var foo:Array = [];

All declared variables have to be commented with ASDoc:

/** This variable is used for... */ var foo:String = "";

This is particularly useful since Flash Builder 4 is not using them (even if no documentation is generated by ASDoc for these comments) within the IDE.

Comments of the developer(s)
All comments by the developer should be using the ASDoc comment type:

/** */

Notice the 2 starts in the comment above. These are ASDoc comments for AS3 code.

If the comment takes more than two lines, it should be written with one star at the beginning of each new line:

/**  * Comment...  * Comment continued... */

If the comment only takes one line, it should be written on one line:

/** Comment... */

Getter/Setter properties
Only document the first function of a get/set function pair for a property.

Comments of the developer(s)
All comments by the developer should be using the ASDoc comment type:

Notice the 3 dashes in the comment above. These are ASDoc comments for MXML code.

If the comment takes more than two lines, it should be written on multiple lines:

If the comment only takes one line, it should be written on one line:

Special ASDoc tag
Event if not supported by ASDoc, these tags have to be used if needed.

@todo

 * The @todo tag is used to specify a task to be completed in the code.
 * @todo [description]

@patch

 * The @patch tag is used to specify that someone had to fix/enhance something that is part of another library
 * @patch [author name, organization] -- [date]

= Naming =

Choosing good names for variables, functions and classes is critical to creating code that is easy to use and easy to understand. You should always take the time to think about whether you have chosen the right name for something.

Properly name and comment things is one of the most critical task of open source projects. At all time, developers should care about this critical task.

Abbreviations
Avoid them as a general rule. For example, calculateOptimalValue is a better method name than calcOptVal.

Acronyms
An acronym is always all-uppercase.

do:

var recordURI:String = "";

Not:

var recordUri:String = "";

Word boundaries
When an identifier contains multiple words, we use two ways of indicating word boundaries: intercaps (as in LayoutManager or measuredWidth) and underscores (as in object_proxy). See the rules below for which method to use.

Class names
Start them with an uppercase letter and use intercaps for subsequent words: Foo, FooBar, etc.

Event names
Start them with a lowercase letter and use intercaps for subsequent words: "move", "creationComplete". Style names

Start them with a lowercase letter and use intercaps for subsequent words: color, fontSize.

Constant names
Use all uppercase letters with underscores between words: OFF, DEFAULT_WIDTH.

The words in the identifier must match the words in the constant value if it is a String:

public static const FOO_BAR:String = "fooBar";

Property (variable and getter/setter) names
Start them with a lowercase letter and use intercaps for subsequent words: i, width, numChildren.

Storage variable names
Give the storage variable for the getter/setter foo the name _foo.

Method names
Start them with a lowercase letter and use intercaps for subsequent words: measure, updateDisplayList.

Method names should always be verbs.

Event handler names
Event handlers should be named by concatenating “Handler” to the type of the event: mouseDownHandler.

If the handler is for events dispatched by a subcomponent (i.e., not this), prefix the handler name with the subcomponent name and an underscore: textInput_focusInHandler.

Argument names
Use value for the argument of every setter:

Do this:

public function set label(value:String):void

Not this:

public function set label(lab:String):void

Or this:

public function set label(labelValue:String):void

Or this:

public function set label(val:String):void

Use event (not e, evt, or eventObj) for the argument of every event handler:

protected function mouseDownHandler(event:Event):void