March 2004 Archives

The many faces of EventDispatcher

| 13 Comments | 3 TrackBacks

So there's more or less 3 different schools of thought for implementing EventDispatcher in your classes. I've attempted to summarize the three most common approaches that I've seen, as well as the pros and cons of each approach. This is by no means a definitive list, but rather just a list from my perspective as an application developer. Feel free to add to it or contradict me in the comments.

  1. Using a static initializer in the class:

    This approach looks like this...

    private static var EventDispatcher_mixin =
    EventDispatcher.initialize(MyClass.prototype);

    In this approach, the class is responsible for declaring function variables for addEventListener, removeEventListener, and dispatchEvent. Then, the actual method implementations are mixed in from EventDispatcher to the class' prototype allowing the instances to use the EventDispatcher functionality themselves without further reliance on EventDispatcher.

    Pros:

    • The methods are mixed into the class prototype, thus saving memory and improving instantiation performance. The methods are only copied from EventDispatcher one time, so every time your class is instantiated the instance will automatically have the methods available to it through the prototype.
    • Out of all the approaches I touch on, this one has the least overhead.

    Cons:

    • See the word prototype in there? It hasn't been deprecated, but who knows how long ActionScript classes will be compiled down to prototypes. Maybe this is really a non-issue, but I wouldn't want to have to re-write all of my classes in the future to work with Flash Player X if the runtime implementation changes.
    • Really, the class should implement an "EventBroadcaster" interface so that the intention of the class is made known at compile-time. Yes, the class will have a "public var addEventListener:Function;" in it, but interfaces in ActionScript can only define methods, so you can't implement an interface. Thus the intent to dispatch events is not made explicit at compile-time, which could be construed as a design shortcoming.
    • Something about that code just looks "ugly" and screams "hack" to me. Of course, that's totally my opinion...

    Further reading:


  2. Using the constructor to initialize the instance as an event source:

    This approach looks like this...

    // in the constructor
    EventDispatcher.initialize(this);
    

    This approach is much the same as above. However, instead of initializing the prototype of the class, each instance of the class has to be initialized as an event source. In a singleton situation, this should provide roughly the same performance as copying the methods to the prototype. If you're going to be creating a lot of instances though, the performance of the constructor will be slightly slower (not by much though).

    Pros:

    • See the word prototype in there? Nope, not at all. Doing things this way is almost the same as above, except we're not relying on the underlying run time implementation for functionality.
    • I think this approach is a little cleaner than the approach above, as far as readability is concerned.

    Cons:

    • Like the above approach, some sort of event broadcasting interface should be implemented. The class in this situation again needs to define function variables that get their implementations mixed in, but again, interfaces cannot define variables in AS 2.
    • As stated, there are slight performance penalties for each instantiation.
    • Some will argue that this code is redundant, since we're doing the same thing for every instance when it makes more sense to do it once at the class level.

    Further reading:


  3. Using composition:

    This approach looks like this...

    // in class body
    private var eventSrc:Object
    
    // in constructor
    EventDispatcher.initialize(eventSrc);
    
    // methods:
    public function registerView(view) {
    	eventSrc.addEventListener("change", view);
    	// more...
    }
    public function removeView(view) {
    	eventSrc.removeEventListener("change", view);
    	// more...
    }
    private function doSomething() {
    	var eventObj:Object = new Object();
    	
    	eventObj.target=this;
    	eventObj.type = "change";
    	
    	eventSrc.dispatchEvent(eventObj);
    }
    

    This approach is radically different. Instead of making the instance the event source, we're using composition to create an object that will be the source of the events for a particular instance. Then, instead of defining function variables that are mixed in, we're instead providing methods to register views (think MVC) that will automatically register the view for all of the applicable events via addEventListener on the eventSrc.

    Pros:

    • By using this approach, the intent can be made clear since we can finally implement an event broadcasting interface because there are no functions declared as variables. In this situation, we would implement an interface that defines the registerView and removeView methods.
    • Again, there are no prototype tricks here. This is straight-up legit, "still-works-even-if-prototype-dies" code.
    • I think this approach provides the most flexibility. If we want to change to AsBroadcaster instead of EventDispatcher we can just modify the event source and the few lines in registerView and removeView. The interface for our class stays consistent then with minimal effort. If we were using one of the previous 2 approaches we would have to make addEventListener a method that would invoke addListener, or we would have to update the interface and therefore force users of our class to change their code as well.

    Cons:

    • This method provides a bit of overhead for the extra function call to register the view.
    • Like the above approach, we're initializing the eventSrc in the constructor, so every instance being created will have a slight performance hit.
    • Obviously, registerView is somewhat specific to the MVC design pattern, but that may not be a con... I tend to use the MVC design pattern a lot in my Flash applications. You could, of course, just change the method name.

    Further reading:

So, there you go.. that's my take on using EventDispatcher. I tend to use the third approach, composition, for the reasons listed above. Of course, you're free to use whatever method you like best. If you have anything to add, go ahead and leverage the comments.

Happy Birthday... to me!

| 18 Comments

My birthday is actually tomorrow, but I don't plan on using my computer much this weekend so I thought I'd post this today. I'll be turning 23 on March 20th, the first day of spring here in the States.

Some other people who share my birthday: My co-worker Mike, Spike Lee, Mr. Rogers (from the neighborhood), B.F. Skinner, and a whole lot of other people.

So who made me a cake? Anyone? Anyone?

Something you may not know...

| No Comments

The private keyword is meant to keep users of your class from accessing the class internals. Trying to access private variables and methods in an instance will result in compilation failure. By now we should all know that that "private" is actually "protected", that private visibility is only checked at compile-time, and that there are ways to bypass the compiler's visibility checking since the keyword has no affect at run-time.

So private data really isn't private, and you have it engrained in your head that anytime you mark something as private you can no longer access it through an instance unless you trick the compiler. As it turns out.. compiler trickery is not always necessary.

What I'm about to show you is generally regarded as well known to those with experience in C++, Java, etc. It's not something that jumps out as obvious to those without a programming background, and it doesn't seem to be documented anywhere in Macromedia's documentation (private, controlling member access). Without further ado, here's a simple demonstration class.

class com.darronschall.weblog.PrivateAccessDemo {
	private var n:Number;
	private var creation_date:Date;
	
	public function PrivateAccessDemo(n:Number, d:Date) {
		this.n = n;
		this.creation_date = d;
	}
	
	/**
	 * Returns true if the current instance has the same internal
	 * data as the instance passed in.  Note that n and creation_date
	 * are both private, but because we're inside the PrivateAccessDemo
	 * class file, we're able to access p's internal data.
	 */
	public function equals(p:PrivateAccessDemo) {
		return (this.n == p.n && this.creation_date.toString() == p.creation_date.toString());
	}
}

Usage is simple in a .fla file:

import com.darronschall.weblog.PrivateAccessDemo;

var p1:PrivateAccessDemo = new PrivateAccessDemo(3, new Date(2004, 2, 15));
var p2:PrivateAccessDemo = new PrivateAccessDemo(7, new Date());
var p3:PrivateAccessDemo = new PrivateAccessDemo(3, new Date(2004, 2, 15));

trace(p1.equals(p2)); // false
trace(p1.equals(p3)); // true
trace(p2.equals(p3)); // false

All the above code does is create 3 instances of my PrivateAccessDemo class, and compare some of them to each other. I've defined one class being equal to another as "each instance needs to have the same date and number value internally." The only way we can check this is by accessing the private variables directly in the instance passed into the equals method.

Normally, when you try to access a private variable or method of an instance, you get a compile error. In this case, we don't. So what happened?

It's simple really. Because we're inside of the PrivateAccessDemo.as class file, the compiler knows that we're the creator of that class. As such, it allows us access to any of the private data in a PrivateAccessDemo instance simply because it assumes that we know what we're doing (we're the creators of the data type, after all).

While this is obvious to a lot of you out there, I'm sure there are some who haven't even given this subject any thought. Because of that, I wanted to just demonstrate an exception to the rule when it comes to accessing private data and generating compile errors. Anytime you pass in an instance of the class who's .as file you're currently working in, you have free reign to access that instance's private data.

Have fun!

Enumerated Types in ActionScript

| 7 Comments | 1 TrackBack

An enumerated type is a data type that maps names to numbers. At first this doesn't sound like a big deal, but enumerations can bring major readability benefits to code, making it easier to understand and therefore easier to maintain.

In my college days I coded mostly with C and C++. As such, I grew to love the enum keyword and the benefits that it provided. When I made the switch to ActionScript, I was a little disappointed to find that support for enumerations wasn't included in the language (although it's a future reserved word in ECMAScript 4). No worries though, it's pretty easy to fake with this handy little class.

/* A simple way to create enumerated types in ActionScript.  Just
	provide a list of string arguments to the constructor and 
	the strings will become identifiers in the instance.
*/
class com.darronschall.weblog.EnumeratedType {
	
	public function EnumeratedType() {
		for (var i = 0; i < arguments.length; i++) {
			// set up the identifier in the instance, and give
			// it a numerical value, unique to the instance
			this[arguments[i]] = i;
		}
	}
}

You would use it in your scripts like this:

import com.darronschall.weblog.EnumeratedType;

// create an enumeration for the days of the week
days = new EnumeratedType("Sunday", "Monday", "Tuesday",  "Wednesday", 
						  "Thursday", "Friday", "Saturday");

// the line below much easier to read than: 
//		today = 4;
// because the meaning of the code is clear
// just by looking at it
today = days.Thursday; 

// we can do neat things with enumerations as well,
// like use them as loop counters
for (var day = days.Sunday; day <= days.Saturday; day++) {
	if (day == today) {
		trace("Found a match.. day == today == days.Thursday");
	}
}

// or even in a switch statement
tomorrow = days.Friday;
switch(tomorrow) {
	case days.Monday:
		trace("Monday.. back to work.");
		break;

	case days.Friday:
		trace("Alright!  Tomorrow is Friday!");
		break;
}

Hopefully from the above example you can see some of the readability benefits that enumerations offer. Creating enumerations is remarkably easy with the class provided above. In the future, if the enum keyword is implemented, it will be even easier (in theory).

Have fun!

Further reading: http://www.alumni.caltech.edu/~leif/OO/Enum.html (Specifically on Enumerated Types in Java, but the concepts can be applied to ActionScript as well)

Answering Mike's Challenge

| 5 Comments

Did you see the challenge Mike Chambers posted for created a search engine in 4 lines of ActionScript? Well.. I've done it, and I'm pretty sure this is the best solution given thus far. Are you ready?

I'm using 2 components from the v2 framework, a Button and a TextInput. Drag them both onto the stage, name the Button "search_btn" and the TextInput "search_txt" and then add the following code to the timeline:

function click() {
	search_txt.text = "No results found for " + search_txt.text + "!";
}
search_btn.addEventListener("click", this);

Pretty slick, right? Of course, you'll never find any results no matter what you search for.. but the specification didn't say that it had to actually return useful information! What do I win? :-)

Flex.org - The Directory for Flex

Archives