Wednesday, November 19, 2003

onKeyUp and Key Listener woes

Well I was tearing my hair trying to figure out why an onKeyUp handler in a component I was building was firing twice.

To be more exact it was firing twice "sometimes", you could even hit the same key 10 times and it was ok then all of a sudden it would start firing twice and stay that way for a while, then all of a sudden stop again.

In the end I figured out the cause of the problem though not why it was random, and it is a useful one to know as you may do this yourself without seeing it as a problem.

In the onFocus handler for my component I called Key.addListener(this) so that events would go to my onKeyUp handler, and then removed the Key Listener in the onKillFocus handler.

BUT movieclip(which is the base class for all components) also has the old onKeyUp property which will fire WHEN THE MOVIECLIP IS FOCUSED so when I created onKeyUp = function(){} I then had two possible triggers for the event, one from the Key listener and one from the movieclip itself and it appears that sometimes both can fire for the same underlying event

So the lesson here is dont do Key.addListener(this) if "this" is itself a movieclip that will be focused, what you should do is create a seperate object that will recieve the onKeyUp events and then have that object callback to methods on your component that are not named the same as the standard movieclip properties




Friday, November 7, 2003

RIAs and Patterns

RIA's are still in there infancy, a stage of development where it seems all you need to do to become an "expert" is write an article about RIA's.

As a Java developer Pattern's have become a way of life. If you are not using Pattern's you must by definition be a) Stupid, b) a very poor programmer, c) not professional or d) all of the above, Patterns are PC for Java developers.

As people talk more about RIA's and Flash I am seeing the mention of Patterns in association with these applications. Whilst there are some good points to pick up in these articles I feel that often the patterns are being misapplied in this context and that some people seem to think that you can make Flash "Professional" by making it "buzzword" compliant.

For example terms like "MVC" or "ServiceLocator" popup frequently. In Java we are really using these terms in the context of Web Application development. So people are using it in the same context with Flash RIA's, what's my problem?

Well its this, in Java a Web App is run from a Java App Server and it (mostly) responds to http requests. We are really talking about a Request driven model here. My controller is invoked by a request and it in turn invokes methods in my business tier. This is all done synchronously, my controller(and my request
) always wait on the return of any method call The business method invoked returns back the result directly to the caller. Caller and callee are explicitly bound together. Within a users context at any one time only one method or line of code is executing. Only one response can ever be made back to a requester.

However in an RIA we have an Event driven model not a Request model. At any time, multiple business methods maybe invoked and the responses occur some time later in a random order. There is no explicit bond between caller and callee, a callee has to figure out (or be told) how to get a response back to the right caller.

What I am getting at here is the two environments are fundamentally different and as such just blindly applying patterns because they sound cool is not helping.

Also we should take into account that much of what is done server side is because of the restrictions of the HttpRequest model and limitations in the client side capabilities. Flash and Remoting remove much of those restrictions, but that's a discussion for another day.


Thursday, November 6, 2003

Forms, Fields and Vars

Well now we are in the brave new world of Form based development in Flash, I thought it would be interesting to try a few experiments.

So I have a Form and I have a TextField, now we know TextField's can be connected to a Var and then automatically update themselves, so wouldn't it be interesting to see if I could connect a TextField to a Form class property.

So I created a setter/getter in my forms class file and connected up the TextField to the parent Forms property and ran it.

Initially it looks like nothing has happened, the TextField is blank

So lets enter some text in the TextField and see whats happens.

Wow, the setter on my Form fires, but then something really strange happens. The TextField then tries to call the getter to retrieve the updated value of the property to display in its textbox(cool!), but for some reason it can't find the getter and instead displays 'undefined' in the TextField.

After a bit more poking around I found I could resolve this problem by 'resetting' the TextFields 'Var' property after my Form has loaded, then it quite happily found both setter and getter.

A bit more poking around and I found that if I hooked the TextField Var directly to a Form member variable rather than to a property then it worked without any resetting of the Var pointer.

So there you have it, you can connect a TextField directly to a Form class file either directly to a member variable or to a getter/setter property, though the later needs to be set and initialized in the Forms onLoad method.

There might not be much use for this feature, but on the other hand...... you could have a dataProvider property on your Form and when it is set, say by new data arriving from the server, you can just update the Forms own properties with new values from the dataProvider array and your TextFields will automatically update themselves.

You could call this a poor mans databinding and it at least does indicate that somethings can be achieved without needing components, and that could be significant with MM suggesting a 125 component limit per application.


Tuesday, November 4, 2003

Its the framework dummy!

There has been an awful lot of "noise" in recent weeks from the flash fanatics about how bad MX2004 is but as one of the those Java J2EE developers who MM maybe were trying to target with MX2004 I have to say that I really love it!!

That's not to say everything is rosy in this brave new world, but my beef with MX2004 is not so much with what they have tried to do but the way it was done......... namely the new framework!

Lets start by talking about one particular aspect of the framework that I feel represents one of its more serious flaws.

The framework fundamentally is composed of two tiers. One tier is the components tier, i.e. the visual elements that we see, like comboboxes, grids etc. The second low level tier underlies the component tier and seems to be patching broken functionality in the player or extending the player for missing basic functionality.

A good example of this is the DepthManager class.

This class extends the MovieClip's limited depth management capabilities by adding features like the ability to insert into a layer above or below a target by shuffling existing layers up or down to make space or features like reserving depths for special classes like tooltips or finding a vacant depth rather than simply the next highest.

It turns out this sort of functionality is really essential to anyone who is serious about trying to manipulate flash movies regardless of the component framework in use and it seems MM agrees as they decided this was so "core" that they made the Depth Manager implement its functionality by changing the MovieClip prototype rather than have it function as a real class object.

Ok so whats the problem here, isn't this a good thing?

Well buried inside the DepthManager is a call to a method of MovieClip called createClassObject. Didn't know that this was a MovieClip method? Well neither did I. Is it an undocumented method maybe? No, you see buried away elsewhere in a tiny corner of the framework is another class UIObjectExtensions. This class is also adding to the MovieClip prototype but it is doing it by using methods of the class UIObject, the foundation class of the whole framework, instead of using defining its own methods.

So DepthManager requires UIObjectExtensions which requires UIObject which requires...... well........
Practically the whole damn framework gets "included" one way or another and this is really symptomatic of how this whole low level tier has been implemented.

The problem with this is two fold, firstly because the implementation is so interconnected it will be almost impossible to migrate this core functionality into the player at a future date and derive any benefit from it.
Imagine for a moment that MM saw the light and realized a huge performance gain could be achieved by adding this functionality to the player in say Flash 8. Now when they release Flash 8 what are MM going to do in the framework. If they remove these functions from the framework as they are no longer needed then they will break all Flash 7 or lower apps in the same way they have just done to FlashMX or lower apps but this time they wont have the argument that it was needed to get the fundamental architecture right. Do you imagine they will be willing to do this a second time? Not likely! So they are probably going to have to leave it in there.

The second problem is that say as a developer of an independent framework of components, maybe like GhostWire, I need this same functionality and instead of creating another standard and possibly having conflicts with existing MM code I would like to make use of the DepthManager, well in doing so I will have to bring in all the code in the framework, unnecessarily burdening my app with code it doesn't use or want and eliminating many of the benefits of a streamlined lightweight framework.

So this is bad for both MM and for independent developers.

But enough of my complaints, could I have done it any better?

Well maybe, lets say if the patches and basic extensions had been packaged up in a single independent class say called "SystemExtensions" then it would allow for changes in future player versions to be handled inside this class by checking the player version at run time and adding the appropriate missing functionality. Its only executed one time so speed is not really a big issue here.

Now one obvious problem with this is how to get all the framework classes to compile if the make calls to any of these "extensions" as the compiler is unaware that MovieClip has been changed.
Well the answer is simple, MovieClip2. Create a base class MovieClip2 that extends MovieClip and simply DECLARES but not implements these extension methods and then make UIObject extend from MovieClip2 not directly from Movieclip.

Now the compiler is happy and it doesn't matter whether the functionality is implemented directly in the player or in an extension class, our application will self adapt to take account of optimizations built into future players, and it is even trivial to "backport" the extension class as newer versions of flash are released so that even those who don't upgrade can benefit from player enhancements.