THE PASZ.COM BLOG

Thursday, August 18, 2005

Coding Style: Please Don't Build JavaScript Classes Like This!

I just picked up DHTML Utopia: Modern Web Design Using JavaScript & DOM by Stuart Langridge. Overall this is an excellent, informative book, and one of the only books out there with up-to-date AJAX information. However, I was extremely disappointed at their choice in OOP style.

The author suggests building "Library Objects" like this one:

var myObj = {
  prop: "hello",
  method1: function() {
     document.write("this is method1");
  },
  method2: function() {
     document.write(myObj.prop + "");
  }
}//end myObj

myObj.method1(); //output: this is method1
myObj.method2(); //output: hello

Here are some of the reasons why I think this is poor practice:
  • You can't instantiate multiple copies of your object.
  • You don't have a constructor function that can be called when the object is created.
  • The syntax requires an additional level of nesting.
  • It's easy to forget to add a comma between items and create an error.
I'm not saying there's anything wrong with creating Objects "on the fly" using the above syntax. What I take issue with is using this syntax to create re-usable "Library Objects".

If you're going to use OOP in JavaScript (and you should!) you really need to use the techniques in the seminal JavaScript: The Definitive Guide from O'Reilly. Please use constructors and prototype and new. As described in a previous post, the ideal way to create a Class for the Object listed above is:

var myObj = function(){
  this.prop = "hello";
}

myObj.prototype.method1 = function(){
  document.write("this is method1");
}

myObj.prototype.method2 = function(){
  document.write(this.prop);
}

var obj = new myObj();
obj.method1(); //output: this is method1
obj.method2(); //output: hello

Tuesday, August 16, 2005

Flash 6 UI Components

Sometimes newer isn't better.

Looking for an alternative to the much-maligned Macromedia Version 2 Components that shipped with Flash MX 2004? You might consider the Version 1 components, which are available available on Macromedia Exchange. By installing thie extension, you can have access to the V1 components through the Flash MX 2004 Authoring Environment.

The nice thing about the V1 components is that they're smaller and faster. In my test, an SWF published with just a V1 Scrollpane was 8.64KB. An SWF published with a V2 Scrollpane was 38.3KB! They're also compatible with Flash 6 player.

Of course the V1 components aren't as powerful, and don't look so sexy, with their boring colors and square corners. (I think you can still skin them, though.) Also, the API is very different, and you might have to hunt around to find adequate documentation. There's still a Flash MX ActionScript Dictionary on Macromedia's site, which is a good place to start. (Try searching for "component".)

Thanks to Mick Gow on flashcoders for bringing this to my attention.

Sunday, August 14, 2005

Acrtionscript: Working With Interfaces

I'm starting a new Flash project -- a strategy war game. Not only will this be the first project I'm going to build primarily with FAME, I've also decided to use interfaces extensively.

The typical description of interfaces usually mentions how great they are when you're working with a team of developers. But the question is, can interfaces help little old me working by myself? On the face of it, interfaces can seem like unnecessary overhead. I've definitely taken this position in the past. After all, they don't implement any functionality. But my hope is that they will impose some useful structure on my code, especially now that I'm working with MTASC's amazingly detailed compiler errors.

If you're using strict data typing (that is, putting the data type after each variable declaration, e.g. var myInt:Number), interfaces give you some added flexibility. For example, say I have several types of vehicles that have been derived from a Vehicle parent class. So I'll have a class Plane and Helicopter that extend Vehicle. Then I'll instantiate the objects myPlane and myHelicopter. Now I can define a function fly(flier:IFlier) that will take a vehicle object as a parameter, provided it implements the IFlier interface.
fly(myPlane);
fly(myHelicopter);
.
.
.


This method is better than being able to pass any subclass of Vehicle into fly() because the compiler will generate an error if a non-flier is passed in.
fly(myCar);
...
ERROR: type error Car should be IFlier


An alternative without interfaces would be to create multiple functions like this:
flyPlane(flier:Plane){...}
flyHelicopter(flier:Helicopter){...}
.
.
.

As you can see, this implementation is much messier.

One warning: If you have other objects that also implement IFlier you will be able to pass them into fly() as well. This may not be desirable!

If you're not strict about data typing in your code then I'm not sure interfaces can offer much for you. But if you have decided to enforce the discipline of strict typing on yourself, interfaces may complement your programming regimen, and can help you write code that is more consistent and organized.