August 16, 2009

My Critique of AS3 Events - Part 1

I've been thinking about AS3 Events a lot lately. I'm finding them a little bit annoying.

Don't get me wrong. After so many changing event models in Flash 5 through 8 (4 if tell target counts as an event), having one formalized in Flash Player 9 was a huge relief. I'm also aware that Macromedia didn't invent this event model. They used a standard: DOM Level 3 Events.

But even standards have room for improvement, on occasion. What follows is a good-natured roasting.

Event constants are inconsistent


Let's say I'm creating my first custom event, and I want to name it according to standard conventions.
What better place to start than the constants in flash.events.Event, beginning with "A":
  • ACTIVATE (verb, present tense)
  • ADDED (verb, past tense)
That didn't take very long. Past or present? Pick a side; we're at war. War with time-traveling virtual machines.

There must be a hidden logic to this. Perhaps I can decipher the pattern by looking at DisplayObject events:
  • render - Dispatched when the display list is about to be updated and rendered.
Oh, I see! It's present-tense because the render hasn't happened yet.

Wait, what's this?
  • removed - Dispatched when a display object is about to be removed from the display list.
I give up. Time paradox = retcon fail.

addEventListener() ordered options awkwardly are


Here is EventDispatcher.addEventListener() in all its glory:
public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void

A general goal in designing a method is to arrange the parameters from the most important or frequently used to the least.

Think fast!
Which optional parameter of addEventListener() do you use the most?

I'll bet you dollars to donuts you said useWeakReference. If not, you need to heed the G. [EDIT: Many have told me it's better to use strong references and meticulously clean up after yourself. I don't use weak listeners anymore.] When you do, you'll get to type this, over and over:

addEventListener(yada, yada, false, 0, true);
addEventListener(yada, yada, false, 0, true);
addEventListener(yada, yada, false, 0, true);

You'll say to yourself: "One of these days, I'm going to write true, 0, true. I just know it."

Tech interview question!
How often do you useCapture with your custom events? [EDIT: I was thinking of events not dispatched from a DisplayObject.]

[Dwight voice]
Trick question. It is impossible. FACT: Only DisplayObjects can have a capturing phase and a bubbling phase in addition to the targeting phase.

But impossibility doesn't mean I have to forget about them! The useCapture will be with you, always.

Event forces irrelevance on you


Want to create your own event class? No problem! You can do whatever you like, as long as what you like is to extend one special class. "Interface is hard!" says Developer Barbie.

Are you wondering how these exotic and intriguing APIs can benefit your custom event class?
  • bubbles
  • currentTarget
  • eventPhase
  • stopImmediatePropagation()
  • stopPropagation()
[EDIT: Sönke and Matthew commented that the "default" APIs can be used in non-DisplayObjects.]

Keep wondering! You don't get to use them. Players Club only.

[EDIT: To clarify, I'm saying that these APIs are applicable only to events dispatched from DisplayObjects.]

But look on the bright side. The code examples sucked anyway.

[EDIT: Here's a good article by Darron Schall: Creating Default, Cancelable Event Handlers.]

Sorry, that's not exactly true. If you follow the official recommendations, you'll spend time using these APIs even though they're no use to you.
  • You'll put bubbles and cancelable in your constructor and pass them to super().
  • That means you'll get to put bubbles and cancelable in your clone() override as well.
  • Top it off by overriding toString(), bringing in bubbles, cancelable, and (oh, neat!) eventPhase.
  • Now your event class looks busy. Busy equals important, right?
These are Adobe's documented recommendations. But all this typing has no benefit to you. None. If I missed something, please comment and enlighten me.
[EDIT: Commenters have pointed out that cancelable can be useful. But there's no need to put it in the constructor if you're not going to use it.]

I don't want this to sound like a big whinge. I mean, really, this stuff isn't horrible. When it comes to events, AS3 is way better than Java events. But not as good as C#.
To be continued.