The Sharendipity Blog » Posts for tag 'porting'

Moving to Flash, Part 4: Anonymous Classes and the Adapter Pattern

This is the fourth in a series of posts describing our port from Java to Flash. For the previous posts, see:

Part 1: We’re Moving to Flash. Here’s Why
Part 2: Important Differences Between Java and ActionScript 3
Part 3: Beginning the Actual Port

This post describes an implementation that allows you to get around the lack of anonymous classes in ActionScript. My biggest complaint about this solution is that it moves compile time errors to runtime. It does, however, hide these issues from the consumers of the implementation.

Adapters

One of the reasons that we were able to perform the port so quickly was because we have a generic asset description. All of our data is passed from the server via XML, so we just needed to figure out how to handle that data in ActionScript. We rely heavily on the adapter pattern to do this. In Java, we used anonymous classes to implement these adapters.

Anonymous classes are nice because using them allows you to define functionality through a particular interface. Here’s an example of an implementation of our XmlStringAdapter:

addAdapter(ATTRIBUTE_NAME, new XmlStringAdapter() {
	public void setString(String sValue) {
		// handle setting
	}
	public String getString() {
		return [object's local value];
	}
}

Ignoring the actual implementation of the getter and setter, it’s easy to see that we have provided an adapter that allows us to set and get values through a specific interface. Pretty handy, but impossible in ActionScript, at least in this manner.

In order to do this in ActionScript, we rely on flash.utils.Proxy. This is actually based off of the Decorator pattern in the book Object-Oriented ActionScript 3.0. We have our own class called DynamicImplementation:

package com.sharendipity.util {

	import com.fived.error.RuntimeException;
	import flash.utils.Proxy;
	import flash.utils.flash_proxy;

	public dynamic class DynamicImplementation extends Proxy {

		private var mtProperties:Object = new Object();

		public function DynamicImplementation() { }

		/**
		 * Add a function to the dynamic implementation.
		 */
		protected function addFunction(sName:String, tFunction:Function):void {
		    if (mtProperties[sName] == null) {
		        mtProperties[sName] = tFunction;
		    }
			else {
			    throw new RuntimeException("Duplicate function: " + sName + " in object: " + this);
			}
		}

		/**
		 * Execute the dynamically added functions.
		 */
		override flash_proxy function callProperty(name:*, ...rest):* {
			var tReturn:Object = null;
			var tFunction:Function = mtProperties[name];

			if (tFunction != null) {
			    try {
			        tReturn = tFunction.apply(mtProperties, rest);
			    }
			    catch (tError:ArgumentError) {
			        throw new RuntimeException("Incorrect number of parameters to function: " + name);
			    }
			}
			else {
				throw new RuntimeException("Function [" + name + "] is not initialized for object: " + this);
			}

			return tReturn;
		}
	}
}

That’s a lot to digest. In essence, this class allows you to add dynamic, named functions to an object in a controlled manner. Note that there are no publicly visible functions. The idea is that your own objects can extend DynamicImplementation in order to provide their own interface. Let’s look at an example of how the above XmlStringAdapter might be implemented:

public dynamic class XmlStringAdapter extends DynamicImplementation implements IXmlStringAdapter {	

	private static const GETTER:String = "getter";
	private static const SETTER:String = "setter";

	private static const GET_VALUE_TYPE:String = "get_value_type";
	private static const COMPARE_TO:String = "compare_to";

	public function XmlStringAdapter() { }

        /**
         * Add the setter implementation to this adapter.
         */
	public function addSetString(tFunction:Function):void {
		addFunction(SETTER, tFunction);
	}

        /**
         * Add the getter implementation to this adapter.
         */
	public function addGetString(tFunction:Function):void {
		addFunction(GETTER, tFunction);
	}

	public function getString():String {
		return this.getter();
	}

	public function setString(sValue:String):void {
		this.setter(sValue);
	}
}

This implementation shows that we have four publicly available functions. It is expected that the IXmlStringAdapter exposes only the getString() and setString() functions and this is the interface that will be passed around, so most people will not see the addSetString() and addGetString() functions. Those functions are designed to be available only to the creator in order to define the dynamic functionality.

The new XmlStringAdapter class achieves a lot of what we’re looking for from anonymous classes. Mainly, external consumers of the class access it through a specific interface which is unchanged from the previous implementation. Furthermore, this interface is compile-time checked. As we’ll see later, however, the internals of the adapter are not.

If you look a little closer at the implementation, you’ll also notice that the underlying function names that the adapter is using are “getter” and “setter.” It is important that these names are different than the externally visible names of the functions in the class. If not, they can never get called. The names are also arbitrary, they are simply internal names that the object uses to call the functions being defined.

Let’s look at the corresponding ActionScript example that will implement the same functionality that we showed in Java in the beginning of this post:

var tAdapter:XmlStringAdapter = new XmlStringAdapter();
tAdapter.addSetString(
	function setString(sValue:String):void {
		// perform setter
	}
);
tAdapter.addGetString(
	function getString():String {
		return [object's local value];
	}
);
addAdapter(ATTRIBUTE_NAME, tAdapter);

As you can see, this is very similar to the original Java implementation. The main difference is that functionality is added through the addGetString() and addSetString() functions, rather than defining the implementation of the class itself.

The important underlying difference, however, is that several problems are not checked at compile time. This can create some frustrating results. First, it’s possible that you switched the getString() and setString() functions and passed the setter into addGetString(), and the getter into addSetString(). Second, you need to look into the XmlStringAdapter class to determine what the correct parameters are to the function that you’re implementing. If the types or number of parameters differ, you’ll get a runtime error.

Runnables

I mentioned in the previous post that the Runnable object can be implemented differently as well. In fact, it can use the same underlying DynamicImplementation:

package com.sharendipity.util {

	import com.fived.error.ExceptionHandler;
	import flash.utils.flash_proxy;

	public dynamic class Runnable extends DynamicImplementation implements IRunnable {

		public static const RUN:String = "perform_run";

		public function Runnable() { }

		public function addRunnable(tFunction:Function):void {
			addFunction(RUN, tFunction);
		}

		public function run() {
			this.perform_run();
		}
	}
}

Note that we will also have the Runnable class implement an IRunnable interface so as to hide the addRunnable() function from the consumers.

While ActionScript is inherently single-threaded, Runnables can be used to define tasks that run at specified intervals as managed by a global task manager. This can be nice for a lot of different reasons. As one example, which we’ll see in the next post, using Runnables may better facilitate the move from a multi-threaded environment to a single-threaded one when performing communication with the server.

Conclusion

You can get pretty close to the implementation of anonymous classes in ActionScript, but it’s certainly not fool proof. You’ll have to do more debugging at run time so be sure to check over your code with a fine-toothed comb when you come across these issues.

The next post will address issues of porting your communication code in a multi-threaded environment to a single-threaded one.

Reblog this post [with Zemanta]
Tags:, , , , , ,

Moving to Flash, Part 2: Important Differences Between Java and ActionScript 3

In my last post I mentioned that we are moving to Flash. The response has been crazy, just check out the comments there.  In the next few posts I will highlight some of our experiences in doing the port. It’s been an interesting ride… stay tuned for more.

There are a couple of places you can go to see what the main differences are between ActionScript and Java. Most of those posts address syntactical differences in the languages.   In this post I’ll highlight the things that were either really important or a big problem for us and what you might want to address before undertaking a port to Flash.

Data Structures

I’m putting this item at the top because I cannot stress how important it was that we used our own interfaces to data structures for arrays, stacks, maps, etc. rather than relying on Java’s implementations directly.   ActionScript only supports Array and Dictionary; no stack, no linked list, no queue.   If you performed a port to ActionScript and were relying on these Java classes, you would be in trouble.  If, however, you used your own interfaces for all of the data structures, you will only need to re-implement the data structures that you are wrapping, saving you a ton of time.

Interfaces

I dislike ActionScript Interfaces for one reason: no data members.  What does this mean?  For every high level type of object that you have, you are probably going to need another class for the constants associated with that class.  It isn’t a huge deal but it contributes to code bloat and is a pain in the butt when you’re porting all the references to data members in the interface.  Other than that, they’re identical to Java.

Abstract Classes

The lack of true abstract classes in ActionScript means that you must implement every method in an interface in a class that provides limited functionality from that interface.  This can be done via the “virtual” keyword, but as with the interface issue, it also adds to code clutter and doesn’t seem truly necessary.   If you have a lot of abstract classes in the chain from an interface to the concrete class, this gets annoying and messy.

EDIT: It seems that functions are declared virtual by default, so using this keyword does not provide any shortcuts, and you still need to declare the function bodies. It is unclear what exactly the virtual keyword does.

Anonymous Inner Classes

I’ll be addressing this one in a later post as well because it can lead to a lot of problems depending on your architecture.  Suffice it to say that ActionScript lacks anonymous inner classes. If you use the Decorator or Adapter patterns the actual implementation can be a burden.   As you’ll see, it pushes errors from compile time to runtime which can make development much more difficult.

Anonymous Functions

Java doesn’t have anonymous functions.   Anonymous functions are actually really cool, except for one problem: what appears to be the lack of a local activation stack.  Take this ActionScript code:

var i:int = 1;

var tFunction:Function = function() {
    trace(i);
}

i += 1;

tFunction();

You get a print out of “2.”  This can be incredibly confusing if you’re debugging complex code.   In Java, you would have had to declare your variable as final and you could use it to your hearts content inside a method, such as a Runnable.  In Flash, you need to create an additional local copy of the variable that is only used inside the function and initialize it to the desired value.

Another important point: anonymous functions are not compile-time checked for the number and types of parameters that are passed in, pushing more debugging off to runtime.

Exception Handling

Exception handling is pretty similar in ActionScript and Java, except for one big thing: There is no “throws” declaration in ActionScript. These types of problems are along the same lines as my biggest complaints with ActionScript: it makes debugging the application so much harder.

The availability of a “throws” declaration requires the programmer to handle the exception or pass it up to the caller.   In either case, the programmer is acutely aware that there is an exception that might get generated as the result of calling a method.  Without this, exception handing can propagate up the call stack until it is finally handled, causing unexpected runtime issues.

Function Overloading and Default Parameters

ActionScript does not allow the programmer to overload functions.   This isn’t a huge problem, as they do allow for default parameters.  In java, I might write:

public void defaultSetter(int iValue) {
    setter(iValue, false);
}

public void setter(int iValue, boolean bForce) {
    // whatever
}

In ActionScript, I write

public function setter(iValue:int, bForce:Boolean = false):void {
    // whatever
}

I like it. What I don’t like: what if you have multiple setter methods that take different types?  Well you end up with a lot of functions like setFromString() and setFromInt(), etc.  Fine.  But, what if your constructor is the one being overloaded with different parameter types?  Now you need a factory for your objects (which maybe you should have anyway…), which means more code bloat.  There may be other ways to get around this via setters but refactoring that functionality can be a pain.

Nested Classes

ActionScript also lacks nested classes.  Again, for Decorator or Adapter patterns this can be troublesome.  It means that you need package-private access to functions or data members, slightly breaking some of the object oriented rules.

Recommendations

If you know about these problems then you can act before hand.  If you have a project you want to port to Flash, use your IDE to do address these some of these issues before you perform the actual port.  Learn to use the refactoring tools.  It will make your life so much easier.  Here are some tips:

  • Wrap references to language-specific data structures in your own interfaces, even if they’re just pass-through.
  • Pull data members out of interfaces into their own constant classes.
  • If possible, name your anonymous inner classes and put them in their own file.  A later post will address often-used anonymous inner classes such as Adapters.
  • Pull out nested classes into their own files.
  • Create Factories for classes that have lots of different types of constructors.
  • Refactor setters that take different types of parameters.  You can address default parameters after the port.

I’ll be following up this post with some thoughts about beginning the actual port to ActionScript.  Check back soon!

Tags:, , ,

We’re Moving to Flash. Here’s Why

This post is the first in a series regarding a complete port of a very large Java project to ActionScript. Stay tuned for the intricacies that arise in doing so.

Duke, the Java Mascot, in the waving pose.
Goodbye, indeed.
Image via
Wikipedia

I’ve been developing in Java for about four years now.   For four years, I’ve defended the Java language.   I’m moving on.

Up front, I’ll say that the reason we are moving to Flash is because of Java’s adoption rates.   It is not, in fact, because of the language itself but because of Java’s deployment model.   We suspect that we lose somewhere between thirty and fifty percent of users due simply to the fact that we are in Java.

This isn’t pure speculation, but backed up by a significant amount of internal data.  There are also other game companies that have experienced the same thing.

The Technology

I’d actually prefer that we remained in Java.  My background is in high-end visualization so I love that we could use OpenGL.   This also means that in the future we could do lots of really fancy special effects.   The problem is that OpenGL ties you to the hardware, and anytime you do that you are opening yourself up to a world of support problems.  We’ve already seen our fair share.

The hardware isn’t really the problem though.  We could have avoided using OpenGL and just used SWT, AWT, or Swing.  There are other open source projects that we were using that we’ll have to dump as well.

It’s unfortunate, really. The Java language is way better than ActionScript and Java compilers are much more advanced. There are also more possibilities with Java.   Moreover, even though Flex Builder is built on Eclipse, the Eclipse development environment for Java is years ahead. I say that with no bias, having just finished porting about 800 classes and nearly 60,000 lines of Java code to ActionScript.

The Java Brand Is In Trouble

Java’s brand is failing.  JavaFX has long been touted as the solution to Java’s woes, but it has been too long in getting released.  In the meantime, Flash has continued to dominate.  Silverlight has come on as a competitor, but it will be years before it has the kind of market penetration that Flash has.

The single biggest problem with Java right now is the name itself. If you see the Java applet loading, you click every visible link that you can to get off the page.

Why Java In the First Place

We got to where we are now faster because we were in Java.  We even knew that we would probably port to something else eventually.  Because of that, we built a flexible architecture that wasn’t tied to the language but abstracted in many ways.  From the way we used data structures to the way we persist our asset data, we made sure we weren’t reliant on Java.  In doing so, we were able to take advantage of the tools that we were familiar with in order to get to the point where we had a complete understanding of the architecture we were building.

That’s where we were two weeks ago.  In that time, we ported our player architecture to ActionScript, and I still have 41 days on my trial version of Flex Builder.

In the upcoming week or so I’ll be following up this post with a lot of the lessons that we learned along the way. It’s been a very rewarding and, at times, frustrating process.   I hope you stay tuned.

Reblog this post [with Zemanta]
Tags:, , ,
© 2009 The Sharendipity Blog is powered by WordPress