JavaScript development – libraries and OOP coding conventions

As I wrote earlier I’m currently porting our ActionScript framework to JavaScript, which basically means I’m diving into JavaScript from and ActionScript developers perspective. Of course I’m still at the beginning of becoming a good JavaScript developer, but I made some progress I’d like to share.

I’ll start right away recommending some core libraries:

  • Objs – Namespaces and class inheritance
  • PureMVC Objs – MVC framework (Objs port)
  • JS-Signals – Event / Messaging system
  • jQuery – Helps with core functionalities and cross browser issues

The existing ActionScript project is based on PureMVC so it was obvious to settle on the same horse, but it wasn’t easy to decide which PureMVC port! This is a fundamental decision because it also defines how to write OOP JavaScript.

Objs has a clean syntax (and documentation) and after developer M. Saunier Frédéric was kind enough to resolve my license problem I used his lightweight version with one little customization: I changed the constructor function name from initialize() to __construct() as it looks more appropriate to me and I already used some initialize() functions for different tasks.
Changed versions: customized puremvc-objs-2.0.js and customized objs-2.0.js.

ActionScript developers probably know Robert Penners AS-Signals but I never implemented it in one of my projects so now I use the concept with JS-Signals.

And of course I also use jQuery with it’s great developer community.

So this is how a “class” with applied coding conventions would look like:

/**
 * Created by derRaab(); - http://blog.derRaab.com
 */
( function () {
 
	/**
	 * Namespace vars for minification (only necessary if used multiple times, but you get the idea how to save strings)
	 */
	var nsCom = "com.",
		nsComDerraab = nsCom+ "derraab.",
		nsComDerraabExamples = nsComDerraab+ "examples.",
 
	/**
	 * Final class
	 */
	ExampleClass,
 
	/**
	 * Temporary class prototype (separated because that helps with IDE code completion)
	 */
	ExampleClassPrototype =
	{
		/**
		 * Without leading underscore part of public API.
		 *
		 * @type {Boolean}
		 * @private
		 */
		publicVar : false,
 
		/**
		 * With one leading underscore part of protected API,
		 * Use it only in this and it's subclasses.
		 *
		 * @type {String}
		 * @private
		 */
		_protectedVar : "",
 
		/**
		 * With two leading underscores use it only in this class!
		 * @type {Number}
		 * @private
		 */
		__privateVar : 0,
 
		/**
		 * <code>ExampleClass</code> constructor (called on instance creation!)
		 *
		 * @param {Number}	privateValue
		 * @param {String}	protectedValue
		 * @param {Boolean}	publicValue
		 */
		__construct: function( privateValue, protectedValue, publicValue )
		{
			// Call to superclass constructor (See Objs documentation)
			// ExampleClass.$super.__construct.apply( this, arguments );
 
			this.__privateVar	= privateValue;
			this._protectedVar	= protectedValue;
			this.publicVar		= publicValue;
 
			// Use static values
			this.__privateVar = ExampleClass.DEFAULT_NUMBER;
		},
 
		/**
		 * Without leading underscore part of public API.
		 */
		publicMethod: function()
		{
		},
 
		/**
		 * With one leading underscore part of protected API,
		 * Use it only in this and it's subclasses.
		 */
		_protectedMethod: function()
		{
		},
 
		/**
		 * With two leading underscores use it only in this class!
		 */
		__privateMethod: function()
		{
		}
	};
 
	/**
	 * Let Objs create our "real" class (see Objs documentation for more details
	 */
	ExampleClass = Objs( nsComDerraabExamples + "ExampleClass", ExampleClassPrototype );
 
	/**
	 * Now add some "static" values
	 */
	ExampleClass.DEFAULT_BOOLEAN = true;
	ExampleClass.DEFAULT_STRING = "georgeous";
	ExampleClass.DEFAULT_NUMBER = 1;
 
}());

This style is still evolving but I think this is kind of how I like to work.

I suggest you read my last post regarding JavaScript library development using ANT and YUICompressor which might help you with project setup and code compression.

And a word to JavaScript IDEs:

I bought WebStorm but it doesn’t integrate ANT. Luckily I earned a IntelliJ IDEA license earlier this year but I’m not absolutely happy with it. It uses a lot of system resources, needs to set up an Java project and so on. Any hints?

JavaScript library development using ANT and YUICompressor

Since I need to port a huge ActionScript project to JavaScript I see myself confronted with different practices of code organization, workspace structures and a lot more JavaScript specific stuff. I’m used to big, strongly typed ActionScript library development with hundreds of classes and interfaces but I’m not quite sure how to transfer my programming skills from ActionScript to JavaScript.

After reading loads of informations I think I created an reusable and understandable build process for my JavaScript project. I bet you’ve already read a lot about YUICompressor and ANT so here you’ll find just some brief informations.

This is my example workspace with file type src subfolders and even another subfolder within the js directory named like the JavaScript library it contains. All ANT files can be found in src/ant:
 

Now let’s have a look at system.properties. This file bundles the system specific settings and usually won’t need changes at all after your initial setup. Only YUI_COMPRESSOR_JAR and YUI_COMPRESSOR_CHARSET will affect the build.xml. I still don’t know what’s the correct charset, but my encoding problems might be caused by the editor. I’ll figure that out later…

#
# SYSTEM PROPERTIES
#
 
# Version number separated for easy changes
YUI_COMPRESSOR_VERSION=2.4.6
 
# Absolut path to YUICompressor home directory
YUI_COMPRESSOR_HOME=/Users/you/.../YUICompressor/${YUI_COMPRESSOR_VERSION}
 
# Absolute path to JAR file (used in build.xml!)
YUI_COMPRESSOR_JAR=${YUI_COMPRESSOR_HOME}/build/yuicompressor-${YUI_COMPRESSOR_VERSION}.jar
 
# Charset used with YUICompressor - MAKE SURE THIS IS CORRECT FOR YOUR SYSTEM!!!
YUI_COMPRESSOR_CHARSET=MacRoman
#YUI_COMPRESSOR_CHARSET=UTF-8
#YUI_COMPRESSOR_CHARSET=ANSI
#YUI_COMPRESSOR_CHARSET=ISO-8859-1

The project.properties currently only contains the basic workspace structure.

#
# PROJECT PROPERTIES
#
 
# Workspace root relative to build.xml
WORKSPACE_ROOT=../..
 
# Main binary directory
BIN_DIR=${WORKSPACE_ROOT}/bin
 
# JavaScript bin directory
BIN_JS_DIR=${BIN_DIR}/js
 
# Main source directory
SRC_DIR=${WORKSPACE_ROOT}/src
 
# JavaScript source directory
SRC_JS_DIR=${SRC_DIR}/js

Finally there is the main build.xml. I was trying hard to write an understandable documentation. Just follow these steps (also found more detailed within the file):

  1. Replace the default library name and prefix with your’s.
  2. Add your source files.
  3. Choose your browser and html file (works at least with Mac OS X).
  4. Run the ANT task called YOUR_LIBRARY_PREFIX_run().
<?xml version="1.0" encoding="UTF-8"?>
<project name="JavaScript Project Tasks" basedir=".">
 
	<!--
		Created without much experience ;) by derRaab(); - http://blog.derRaab.com
	-->
 
	<!-- Load external properties -->
	<property file="project.properties" />
	<property file="system.properties" />
 
	<!--
		_createWorkspace() - Creates the basic workspace structure..
	-->
    <target name="_createWorkspace()" description="Creates the basic workspace structure.">
    	<mkdir dir="${BIN_CSS_DIR}"/>
    	<mkdir dir="${BIN_JS_DIR}"/>
        <mkdir dir="${SRC_JS_DIR}"/>
        <mkdir dir="${SRC_CSS_DIR}"/>
    </target>
 
	<!--
		__openBrowser( browserName, targetFile ) - Opens a browser with a specific file.
 
		This might be Mac OS X specific, so please refer to
		http://www.darronschall.com/weblog/2007/12/launching-firefox-from-ant-on-osx.cfm
		for further informations.
 
		@param browserName		e.g. 'Firefox', 'Safari', 'Chrome'
		@param targetFile		e.g. 'path/to/index.html'
	-->
    <target name="__openBrowser()" description="Utility task - Opens a browser with a specific file.">
        <echo message="__openBrowser( ${browserName}, ${targetFile} )" />
    	<exec executable="open" spawn="yes">
    		<arg line="-a ${browserName}" />
    		<arg line="${targetFile}" />
    	</exec>
    </target>
 
	<!--
		_concatenate( inputFileListID, inputFileSetID, outputFile ) - Concatenates a FileSet into one fresh file.
 
		@param inputFileListID
		@param inputFileSetID
		@param outputFile		e.g. 'path/to/file/name.ext'
	-->
    <target name="__concatenate()" description="Utility task - Concatenates a FileSet into one fresh file.">
        <echo message="_concatenate( ${inputFileSetID}, ${outputFile} )" />
    	<delete file="${outputFile}"/>
        <concat destfile="${outputFile}" fixlastline="yes">
            <filelist refid="${inputFileListID}"/>
            <fileset refid="${inputFileSetID}"/>
        </concat>
    </target>
 
	<!--
		_yuiCompress( workDir, inputFile, outputFile ) - Compresses a single JavaScript file into one fresh file within the same directory.
 
		@param workDir			e.g. 'path/to/file'
		@param inputFile		e.g. 'name.js'
		@param outputFile		e.g. 'name.min.js'
	-->
    <target name="__compress()" description="Utility task - Compresses a single JavaScript file into one fresh file within the same directory.">
    	<echo message="_yuiCompress( ${workDir}, ${inputFile}, ${outputFile} )" />
    	<delete file="${workDir}/${outputFile}"/>
        <apply dest="${workDir}" executable="java" verbose="true">
            <fileset dir="${workDir}">
                <include name="${inputFile}" />
            </fileset>
            <arg line="-jar" />
            <arg path="${YUI_COMPRESSOR_JAR}" />	
            <arg value="--charset" />
            <arg value="${YUI_COMPRESSOR_CHARSET}" />
            <arg value="-o" />
            <targetfile />
            <mapper type="glob" from="${inputFile}" to="${outputFile}" />
        </apply>
    </target>
 
	<!--
 
		SETTING UP YOUR BUILD PROCESS:
 
		1.	Recognise the default name ('library') and prefix ('LIBRARY_JS') in this default build.xml 
		1.	Choose a unique name and prefix for your library.
		2.	Use your editor's case sensitive replace all functionality to change the default values
			('library'->'yourLibrary' and 'LIBRARY_JS_'->'YOUR_LIBRARY_JS_')
			NOTE: You can add multiple libraries to one build.xml
		3.	Add a version number (see ...VERSION) if needed.
		4.	Add files to your file list (see ...FILE_LIST) - OR! add a bunch of files to your file set (see ...FILE_SET)
		5.	Choose your browser (see ...RUN_BROWSER_NAME)
		6	Choose your run file (see ...RUN_FILE_NAME)
 
	-->
 
	<!--
		...NAME					Library name used in file system
		...VERSION				Optional library version suffix e.g. '-1.2.6' or ''
		...BIN_FILE_DIR			Library binary folder e.g. 'bin/js'
		...BIN_FILE_NAME		Full file name of concatenated file
		...BIN_MIN_FILE_NAME	Full file name of minimized file (must be different!)
		...SRC_DIR				Library source folder e.g. 'src/js/library'
		...RUN_BROWSER_NAME		Your test browser of choice (Mac OS X only?) e.g. 'Firefox', 'Safari', 'Chrome' 
		...RUN_FILE_NAME		Your test file e.g. 'index.html' 
	-->
	<property name="LIBRARY_JS_NAME" value="library"/>
	<property name="LIBRARY_JS_VERSION" value=""/>
	<property name="LIBRARY_JS_BIN_DIR" value="${BIN_JS_DIR}"/>
	<property name="LIBRARY_JS_BIN_FILE_NAME" value="${LIBRARY_JS_NAME}${LIBRARY_JS_VERSION}.js"/>
	<property name="LIBRARY_JS_BIN_MIN_FILE_NAME" value="${LIBRARY_JS_NAME}${LIBRARY_JS_VERSION}.min.js"/>
	<property name="LIBRARY_JS_SRC_DIR" value="${SRC_JS_DIR}/${LIBRARY_JS_NAME}"/>
	<property name="LIBRARY_JS_RUN_BROWSER_NAME" value="Safari"/>
	<property name="LIBRARY_JS_RUN_FILE_NAME" value="index.html"/>
 
	<!--
		...FILE_LIST	File list used within _concatenate()
		...FILE_SET		File set used within _concatenate()
 
		Important:
 
		1.	YUICompressor will use the ...FILE_LIST first and ...FILE_SET afterwards!
			So you can first assign a special file order and then additionally add a bunch of unordered files
		2.	Avoid duplicates since YUICompresser doesn't check if a file was already added!
		3.	It's a good approach to only use one of them and leave the other one empty.
	-->
    <filelist id="LIBRARY_JS_FILE_LIST" dir="${LIBRARY_JS_SRC_DIR}">
    	<file name="core.js"/>
    	<file name="more.js"/>
    	<file name="evenmore.js"/>
    </filelist>
    <fileset id="LIBRARY_JS_FILE_SET" dir="${LIBRARY_JS_SRC_DIR}">
    	<exclude name="**/*.*"/><!-- by default file set is not used! -->
    	<!--<include name="**/*.js"/> this is how you add all js files-->
    </fileset>
 
	<!--
		..._createWorkspace()	- Creates the library source dir.
		..._concatenate()		- Concatenates the library.
		..._compress()			- Compresses the library.
		..._openBrowser()		- Open's the index.html in your preferred browser.
		..._run()				- Compresses the library and open's the index.html in your preferred browser.
	-->
	<target name="LIBRARY_JS_createWorkspace()" depends="_createWorkspace()">
		<mkdir dir="${LIBRARY_JS_SRC_DIR}"/>
	</target>
	<target name="LIBRARY_JS_concatenate()" depends="LIBRARY_JS_createWorkspace()">
		<antcall target="__concatenate()">
			<param name="inputFileListID" value="LIBRARY_JS_FILE_LIST"/>
			<param name="inputFileSetID" value="LIBRARY_JS_FILE_SET"/>
			<param name="outputFile" value="${LIBRARY_JS_BIN_DIR}/${LIBRARY_JS_BIN_FILE_NAME}"/>
		</antcall>
	</target>
	<target name="LIBRARY_JS_compress()" depends="LIBRARY_JS_concatenate()">
		<antcall target="__compress()">
			<param name="workDir" value="${LIBRARY_JS_BIN_DIR}"/>
			<param name="inputFile" value="${LIBRARY_JS_BIN_FILE_NAME}"/>
			<param name="outputFile" value="${LIBRARY_JS_BIN_MIN_FILE_NAME}"/>
		</antcall>
	</target>
	<target name="LIBRARY_JS_openBrowser()">
		<antcall target="__openBrowser()">
			<param name="browserName" value="${LIBRARY_JS_RUN_BROWSER_NAME}"/>
			<param name="targetFile" value="${basedir}/${BIN_DIR}/${LIBRARY_JS_RUN_FILE_NAME}"/>
		</antcall>
	</target>
	<target name="LIBRARY_JS_run()">
		<antcall target="LIBRARY_JS_compress()"/>
		<antcall target="LIBRARY_JS_openBrowser()"/>
	</target>
 
</project>

Notice that it’s possible to have multiple libraries within a single build.xml. Simply use different prefixes!

In the end I found most of the core informations at http://www.samaxes.com and http://www.darronschall.com/weblog. Thank you guys! And of course the ANT and YUICompressor manuals accessible through Google ;).

And now I have two question:

  • Will you tell me your preferred editor?
  • Will you give me a hint according to code organization?

Please.

Adobe AIR 2.7: Faster App Performance on iOS

Get a big performance boost on iOS using Adobe AIR 2.7 SDK!

Adobe’s current release version includes a number of feature enhancements:

  • Install AIR Runtime to SD (Android)
  • Improved performance on iOS
  • Media Measurement
  • Acoustic Echo Cancellation (Desktop only)
  • Enhanced HTMLLoader API
  • Interpreter Mode for iOS

Read full details here: http://blogs.adobe.com/flashruntimereleases/2011/06/14/air-2-7-runtimes-and-sdk-are-now-available/

See the performance:

Don’t know where to start? This guide is still valid: iOS development with AIR 2.6 using FDT and my new friend ANT

Flex compiler – application descriptor: invalid application identifier

Whenever your Flex compiler prompts
application descriptor: invalid application identifier“,
you might check your application description XML file. Your application ID might contain underscores (in my case) or other invalid characters. Since I found a hint to the solution only at koali.com.au, I think it’s a good idea to reblog it.

Quote from Adobe livedocs:

id – An identifier string unique to the application, known as the application ID. The attribute value is restricted to the following characters:

  • 0-9
  • a-z
  • A-Z
  • . (dot)
  • – (hyphen)

The value must contain between 1 to 212 characters. This element is required.

The id string typically uses a dot-separated hierarchy, in alignment with a reversed DNS domain address, a Java package or class name, or an OS X Universal Type Identifier. The DNS-like form is not enforced, and AIR does not create any association between the name and actual DNS domains.

More informations about the descriptor file:
http://livedocs.adobe.com/flex/3/html/help.html?content=dg_part_4_1.html

Safari Flash Player detection problems with ClickToFlash

I really like the concept of blocking Flash, mainly because I don’t see these unwanted, crappy developed Flash adds sucking performance, but also because it’s a nice way to recognise Flash parts in websites. You’ll have your own reasons.

Safari is, except for testing purposes, my browser of choice, but I was having trouble on different websites accessing Flash content because the Flash plugin was not detected correctly. Since I had to update the Flash Player on my system again, I decided to figure out what the problem is.

According to Playerversion.com an older Flash Player version – MAC 10,0,45,0 – was found first, then the display switched to my installed Flash version – MAC 10,3,181,14 (Debug player).

I used the Flash Player Uninstaller but Flash Player version MAC 10,0,45,0 was still displayed in Safari.

After some research I figured out that ClickToFlash doesn’t display the correct Flash Player version and therefore doesn’t work in all Flash detection scripts. Just check Safari - Help - Installed Plugins and search for "Flash" and you’ll see that ClickToFlash simulates somehow an outdated Flash Player version (seems to be hardcoded).

So until ClickToFlash will be updated displaying the correct installed Flash Player version I’ll use AdBlock For Safari. More Flash but less problems – hopefully. 🙂

Linked List Performance Test using Getter or Interface

Another test regarding linked lists. Since I heavily use interfaces within the frameworks I’m working on I tried to define interfaces for my linked list items. I would love to use an abstract interface but with the full linked list speed. Seems not possible. If you create an interface you need to use at least one getter function which kills performance.

I compared execution time using this code:

package
{
	import flash.utils.getTimer;
	import flash.events.Event;
	import flash.display.Sprite;
 
	public final class LinkedListPerformanceCheck extends Sprite
	{
		private var _firstItemWithPublicVar : ItemWithPublicVar;
		private var _firstFinalItemWithPublicVar : FinalItemWithPublicVar;
		private var _firstItemWithGetter : ItemWithGetter;
		private var _firstFinalItemWithGetter : FinalItemWithGetter;
		private var _firstIItemWithGetter : IItemWithGetter;
		private var _firstIFinalItemWithGetter : IFinalItemWithGetter;
 
		private var _c : int;
		private var _i : int;
 
		public function LinkedListPerformanceCheck()
		{
			loaderInfo.addEventListener( Event.COMPLETE, run );
		}
 
		private function run( event : Event ) : void
		{
			_c = 5000000;
			_i = 0;
			addEventListener( Event.ENTER_FRAME, onEnterFrame );
		}
 
		private function onEnterFrame( event : Event ) : void
		{
			switch( _i++ )
			{
				case 0 : createItemWithPublicVarTest(); break;
				case 1 : createFinalItemWithPublicVarTest(); break;
				case 2 : createItemWithGetterTest(); break;
				case 3 : createFinalItemWithGetterTest(); break;
				case 4 : createImplementedIItemWithGetterTest(); break;
				case 5 : createImplementedIFinalItemWithGetterTest(); break;
				case 6 : break; // wait
				case 7 : break; // wait
				case 8 : break; // wait
				case 9 : break; // wait
				case 10 : runItemWithPublicVarTest(); break;
				case 11 : runFinalItemWithPublicVarTest(); break;
				case 12 : runItemWithGetterTest(); break;
				case 13 : runFinalItemWithGetterTest(); break;
				case 14 : runImplementedIItemWithGetterTest(); break;
				case 15 : runImplementedIFinalItemWithGetterTest(); break;
				case 16 : runItemWithPublicVarTest(); break; // again - just to make sure...
				case 17 : runFinalItemWithPublicVarTest(); break; // again - just to make sure...
				default: removeEventListener( Event.ENTER_FRAME, onEnterFrame );
			}
		}
 
		private function createItemWithPublicVarTest() : void
		{
			var item : ItemWithPublicVar = _firstItemWithPublicVar = new ItemWithPublicVar();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ItemWithPublicVar(); }
		}
 
		private function runItemWithPublicVarTest() : void
		{
			var item : ItemWithPublicVar = _firstItemWithPublicVar;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runItemWithPublicVarTest( " +duration + " )");
		}
 
		private function createFinalItemWithPublicVarTest() : void
		{
			var item : FinalItemWithPublicVar = _firstFinalItemWithPublicVar = new FinalItemWithPublicVar();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new FinalItemWithPublicVar(); }
		}
 
		private function runFinalItemWithPublicVarTest() : void
		{
			var item : FinalItemWithPublicVar = _firstFinalItemWithPublicVar;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runFinalItemWithPublicVarTest( " +duration + " )");
		}
 
		private function createItemWithGetterTest() : void
		{
			var item : ItemWithGetter = _firstItemWithGetter = new ItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ItemWithGetter(); }
		}
 
		private function runItemWithGetterTest() : void
		{
			var item : ItemWithGetter = _firstItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runItemWithGetterTest( " +duration + " )");
		}
 
		private function createFinalItemWithGetterTest() : void
		{
			var item : FinalItemWithGetter = _firstFinalItemWithGetter = new FinalItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new FinalItemWithGetter(); }
		}
 
		private function runFinalItemWithGetterTest() : void
		{
			var item : FinalItemWithGetter = _firstFinalItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runFinalItemWithGetterTest( " +duration + " )");
		}
 
		private function createImplementedIItemWithGetterTest() : void
		{
			var item : IItemWithGetter = _firstIItemWithGetter = new ImplementedIItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ImplementedIItemWithGetter(); }
		}
 
		private function runImplementedIItemWithGetterTest() : void
		{
			var item : IItemWithGetter = _firstIItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runImplementedIItemWithGetterTest( " +duration + " )");
		}
 
		private function createImplementedIFinalItemWithGetterTest() : void
		{
			var item : IFinalItemWithGetter = _firstIFinalItemWithGetter = new ImplementedIFinalItemWithGetter();
			for ( var i : int = 0; i < _c; i++ ) { item = item.next = new ImplementedIFinalItemWithGetter(); }
		}
 
		private function runImplementedIFinalItemWithGetterTest() : void
		{
			var item : IFinalItemWithGetter = _firstIFinalItemWithGetter;
			var startTime : int = getTimer();
			while( item ){ item = item.next; }
			var duration : int = getTimer() - startTime;
			trace("LinkedListPerformanceCheck.runImplementedIFinalItemWithGetterTest( " +duration + " )");
		}
	}
}
 
class ItemWithPublicVar { public var next : ItemWithPublicVar; }
 
final class FinalItemWithPublicVar { public var next : FinalItemWithPublicVar; }
 
class ItemWithGetter
{
	private var _next : ItemWithGetter;
	public function get next() : ItemWithGetter { return _next; }
	public function set next( value : ItemWithGetter ) : void { _next = value; }
}
 
final class FinalItemWithGetter
{
	private var _next : FinalItemWithGetter;
	public function get next() : FinalItemWithGetter { return _next; }
	public function set next( value : FinalItemWithGetter ) : void { _next = value; }
}
 
interface IItemWithGetter
{
	function get next() : IItemWithGetter;
	function set next( value : IItemWithGetter ) : void;
}
 
class ImplementedIItemWithGetter implements IItemWithGetter
{
	private var _next : IItemWithGetter;
	public function get next() : IItemWithGetter { return _next; }
	public function set next( value : IItemWithGetter ) : void { _next = value; }
}
 
interface IFinalItemWithGetter
{
	function get next() : IFinalItemWithGetter;
	function set next( value : IFinalItemWithGetter ) : void;
}
 
final class ImplementedIFinalItemWithGetter implements IFinalItemWithGetter
{
	private var _next : IFinalItemWithGetter;
	public function get next() : IFinalItemWithGetter { return _next; }
	public function set next( value : IFinalItemWithGetter ) : void { _next = value; }
}

Result:

LinkedListPerformanceCheck.runItemWithPublicVarTest( 86 )
LinkedListPerformanceCheck.runFinalItemWithPublicVarTest( 88 )
LinkedListPerformanceCheck.runItemWithGetterTest( 1247 )
LinkedListPerformanceCheck.runFinalItemWithGetterTest( 1148 )
LinkedListPerformanceCheck.runImplementedIItemWithGetterTest( 1161 )
LinkedListPerformanceCheck.runImplementedIFinalItemWithGetterTest( 1160 )
LinkedListPerformanceCheck.runItemWithPublicVarTest( 64 )
LinkedListPerformanceCheck.runFinalItemWithPublicVarTest( 62 )

Using public variables instead of getter functions is much faster. To make sure memory allocation doesn’t kill performance I repeated the public variables test at the end. Even faster.

Is there a way to define Interfaces for public variables?

FFK11 – beyond tellerrand notes

I’m still not sure if “beyond tellerrand” is a subtitle or will become the new brand for the one and only Flashforum conference here in germany. Sascha Wolter and Marc Thiele did a great job as always and even I never went to another conference, FFK seems still to be a special one. Again I was lucky listening to some really cool stuff.

Interestingly most of my last year notes are still up to date, which doesn’t help if you don’t keep them in mind. So I think it’s a good idea to read my own notes from time to time. 😉

That’s what I became aware of this time:

AIR 2.6

  • Lee Brimelow mentioned AIR 2.6 on iOS is faster than on Android! Yeah.
  • Adobe is working hard on increasing performance near to native code.
  • Installing a runtime seems to be annoying for Android users, so Adobe is thinking about compiling for Android like for iOS. Which might bring some extra performance as well.
  • I asked Lee Brimelow about AIR on Windows Phone 7 and he said something like “Adobe is currently not working on that and it would be a lot of work”. Well, of course Microsoft is not interested having AIR on their system, but it would be a really important platform for all of us. So in my opinion Adobe at least has a small team checking out what’s possible. What do you think about Windows Phone 7 and AIR support?

Flex Builder 4.5

  • You can get Flex SDK 4.5 already, but there’s also a way to join the private pre-release program to get early access to Flex Builder 4.5. Just visit http://www.surveymonkey.com/s/flexprerelease. They are working on some useful stuff and it might be a good idea to test some of the new features.
  • Deepa Supramaniam mentioned spark MXML skins have performance issues on mobile devices. That’s why they created pure ActionScript spark skins for mobile applications. Hopefully, within the private beta Flex SDKs, we’ll find some great improvements: http://www.riagora.com/2011/03/preview-of-flex-on-ios/.

NUI

  • Wolfgang Henseler (Talk I missed at FFK10) opened my mind according NUI.
  • Don’t think of apps on mobile devices but of services allowing you reaching your goal faster than a website.
  • Think about providing services, combining them, rethinking them.
  • Use less design and let objects provide their functionalities (e.g. tap on image to get some options).
  • My brain is very busy with that NUI thing. E. g. he mentioned the Siri iPhone app. It’s not about how it looks like (not so cool) but how it works! Combining lots of possibilities with a really easy interface (speech) . He was also talking about “in body technology” (sensors and stuff like that.) and http://www.tedmed.com/
  • After Dennis Ippels Kinect (OpenKinect / http://www.primesense.com/) introduction I finally know something about the magic behind this device as well.

Molehill

Additional useful links:

iOS development with AIR 2.6 using FDT and my new friend ANT

Adobe recently released AIR 2.6 with improved iOS support, so I finally had to get into using ADT with ANT. My editor of choice is FDT so I wanted to do as less extra work as possible. Mainly because I’m no terminal-guy. I need a clean GUI holding my hand while setting up workspaces, linking libraries and stuff like that. In other words, command line and compiler arguments are freaking me out. 😉

I read a lot of blogposts and articles (see link list on the bottom of this post) but most of them compile SWFs using ANT, which means setting source path and stuff like that as command line arguments. But hey, FDT does this already during my daily workflow, so to me it seems natural reusing this within the iOS packaging process.

So I won’t comment a lot what I came up with because all of this can be read on one of the sites below, but show you simply a screenshot of my “IOSAIRTest” workspace structure and of course the ANT files. Notice that I’m not into having different directories for debug, publish, testing and so. I like to have all source files clean and separated by file type (would have an mxml folder too):

You will find the most interesting files in src/ant. Let’s start with local.properties which just defines the SDK path:

FLEX_HOME=/Users/{USERNAME}/Path/To/FlexSDKs/4.5.0.17689_AIR_2.6
MXMLC=${FLEX_HOME}/bin/mxmlc
ADT=${FLEX_HOME}/bin/adt

Within build.properties you setup all params regarding your project:

app.rootdir=./../..
app.descriptor=${app.rootdir}/bin/IOSAIRTest-app.xml
app.rootfile=IOSAIRTest.swf
app.sourcedir=${app.rootdir}/src/as
app.bindir=${app.rootdir}/bin
app.source=${app.sourcedir}/de/superclass/IOSAIRTest.as
app.includes=assets icons Default.png Default-Portrait.png
 
build.storetype=pkcs12
build.keystore=${app.rootdir}/resources/ios/iPhoneDevCert.p12
build.storepass={PASSWORD;)}
build.mobileprofile=${app.rootdir}/resources/ios/AIR_TEST.mobileprovision
build.name=IOSAIRTest.ipa
 
fdt.projectname=AIRTest
fdt.mainclass=${app.source}
fdt.target=${app.bindir}/${app.rootfile}

And build.xml contains four ways to create the IPA package and the according FDT tasks:

<?xml version="1.0" encoding="UTF-8"?>
<project name="AIR export" basedir=".">
 
	<property file="local.properties" />
	<property file="build.properties" />
 
	<!-- FDT tasks
 
		see http://fdt.powerflasher.com/docs/FDT_Ant_Tasks#fdt.launch.application - for documentation
		see http://fdt.powerflasher.com/docs/FDT_and_Ant_Tutorial#Your_First_Task:_Compiling_.26_JRE_Error - if you run into errors!
	-->
 
	<target name="FDT create SWF">
		<fdt.launch.resetFlexCompiler/>
		<fdt.launch.application
			projectname="${fdt.projectname}"
			mainclass="${fdt.mainclass}"
			profile="false"
			debug="false"
			target="${fdt.target}"
	    	startswf="false"/>
	  </target>
 
	<target name="FDT create SWF debug">
		<fdt.launch.resetFlexCompiler/>
		<fdt.launch.application
			projectname="${fdt.projectname}"
			mainclass="${fdt.mainclass}"
			profile="false"
			debug="true"
			target="${fdt.target}"
	    	startswf="false"/>
	  </target>
 
	<!-- ADT tasks -->
 
	<target name="iOS create IPA debug" depends="FDT create SWF debug">
		<exec executable="${ADT}">
			<arg line="-package
						-target ipa-debug
						-storetype ${build.storetype}
						-keystore ${build.keystore}
						-storepass ${build.storepass}
						-provisioning-profile ${build.mobileprofile}
						${app.bindir}/${build.name}
						${app.descriptor}
						-C ${app.bindir} ${app.rootfile} ${app.includes}
			"/>
		</exec>
	</target>
 
	<target name="iOS create IPA test" depends="FDT create SWF">
		<exec executable="${ADT}">
			<arg line="-package
						-target ipa-test
						-storetype ${build.storetype}
						-keystore ${build.keystore}
						-storepass ${build.storepass}
						-provisioning-profile ${build.mobileprofile}
						${app.bindir}/${build.name}
						${app.descriptor}
						-C ${app.bindir} ${app.rootfile} ${app.includes}
			"/>
		</exec>
	</target>
 
	<target name="iOS create IPA ad-hoc" depends="FDT create SWF">
		<exec executable="${ADT}">
			<arg line="-package
						-target ipa-ad-hoc
						-storetype ${build.storetype}
						-keystore ${build.keystore}
						-storepass ${build.storepass}
						-provisioning-profile ${build.mobileprofile}
						${app.bindir}/${build.name}
						${app.descriptor}
						-C ${app.bindir} ${app.rootfile} ${app.includes}
			"/>
		</exec>
	</target>
 
	<target name="iOS create IPA app-store" depends="FDT create SWF">
		<exec executable="${ADT}">
			<arg line="-package
						-target ipa-app-store
						-storetype ${build.storetype}
						-keystore ${build.keystore}
						-storepass ${build.storepass}
						-provisioning-profile ${build.mobileprofile}
						${app.bindir}/${build.name}
						${app.descriptor}
						-C ${app.bindir} ${app.rootfile} ${app.includes}
			"/>
		</exec>
	</target>
 
</project>

If you’re not sure how to get started with all this AIR 2.6 stuff because it’s currently not integrated in the Flex SDKs – follow this steps:

Loads of linked informations:

http://blogs.adobe.com/cantrell/archives/2011/03/how-to-use-air-2-6-with-flash-builder-4.html
http://www.mobilerevamp.org/2010/07/30/how-to-build-your-first-air4android-application-using-fdt-and-eclipse/
https://code.google.com/p/air-on-android-with-fdt/
http://www.beautifycode.com/flex-hero-mobile-project-template-for-fdt-4-2
http://www.beautifycode.com/publish-package-an-air-file-with-fdt4
http://labs.almerblank.com/2011/03/using-ant-to-compile-a-flex-mobile-project-for-ios/
http://va.lent.in/blog/2011/03/25/air2-6-app-for-ios/ (Thanks for ANT files!)
http://developerartofwar.com/2011/03/24/air-2-6-on-ipad-2-in-15-mins/
http://karoshiethos.com/2010/04/06/use-fdt-folder-path-variables-in-ant/
http://fdt.powerflasher.com/docs/FDT_Ant_Tasks#fdt.launch.application
http://labs.almerblank.com/2011/03/using-ant-to-compile-a-flex-mobile-project-for-ios/

Update:
http://www.blackcj.com/blog/2011/04/04/ios-android-and-blackberry-in-a-single-click-with-ant/

SWF meta tag

I’m always searching for it so here is a useful blogpost.

As the latest FDT version ( Beta 4 ) does not set compiler arguments concerning SWF-size, framerate etc. by default I started using SWF-Metatags to specify these settings.

I’m talking of these things:

[SWF(width="910", height="610", backgroundColor="#FFFFFF", frameRate="40")]

Just set this tag above your class opening in the one you’re going to compile. Here is a complete list of (useful) arguments you can pass in:

width
widthPercent
height
heightPercent
scriptTimeLimit
frameRate
backgroundColor

So basically this is the fastest way to set up common compile-arguments to your project. By the way there is no Flex-Framework required – these tags also work in pure AS3 projects.