« October 2003 | Main | December 2003 »

November 15, 2003

Properties and Getter-Setters in Components

I'd started writing a comment to respond to Corlandt Winters' amazingly perceptive comments in my last post, dealing with component properties. My response was getting long and I realized I wanted to make sure people had a better chance to see his post and my response. So, new post. I'm starting to consider finishing a threaded forum app I've had in the works for a while.. Maybe it would make these conversations more readable? Anyhow, my response :

Wow.. Great comments Corlandt - thanks for your detailed thoughts. This blog might turn out useful after all. I'm not sure properties necessarily represent such a huge quantum leap, except maybe as it pertains to debugging, as you pointed out. In V1, you pretty much had a 'getXXX()' method for every property you can access in V2. V2 props do make sure you *have* to implement the getter, which was more optional in V1.

Interestingly though, V2 architecture is actually *harder* on the debugger - you're likely to have more troubles with it. The debugger does a lot of operations of properties on objects behind the scenes (whether initializing them briefly, or reading them so they can be displayed in panels). Since so many of these properties are now bound to function execution, it's easy to spend a ton of your debug tracing bouncing through getters and setters where you never expected them to fire (and indeed, where they wouldn't fire outside the context of the debugger). In general, it slows down the already sluggish debugger.

Hopefully it's something we can improve on the performance front, but I'm not sure I see the total panacea you do here. The state de/serialization was definitely a thought we had in mind as well, but it also brings up some difficult technical aspects :

The first, and the one I'll pose here as a riddle and see what you think (hint: yes, it's been solved), is state initialization sequencing. The hardest thing to do in components, whether you're initializing them from snapshots taken earlier, or through a set of XML attributes, is that there's no guarantee on the order of property setting. Example - say I take a snapshot of a listBox and store in object fields :


myListState = { vPosition:2, dataProvider:["one", "two", "three", "four"] };


Seems straightforward enough. Assume (correctly) that your de/serialization routines are unaware of sequencing dependencies in the components (as they have to be, or be riddled with special rules). You might end up with code like this :

myList = createClassObject(mx.controls.List, "myList", 1);
myList.vPosition = 2;
myList.dataProvider = ["one", "two", "three", "four"];

Anyone spot the problem here? Typically, certain component states are predicated on other component states. If I do proper boundary checking in vPosition, I don't let a vPosition get set that scrolls off the end of the dataProvider. Here, setting vPosition before setting dataProvider would rightly be ignored. But in this case, you need this to work without special-casing hell in your deserialization code.

How would you solve this problem? I'll post the answer in my next post, and comment on the problems the solution brings up (ain't life grand?).

Posted by nigel at 01:33 PM | Comments (9)

November 14, 2003

OOP and Idolatry

As suggested in the comments of the last post, I'd like to take some time to talk about Tom Muck's recent article about the MX 2004 components and "OOP Sacrilege" (nice title, very.. spanish inquisition, or something).

I'm a fan of Tom's site, which has consistently had real information (unlike some other blogs you might read). I also love a good argument, and Tom definitely knows how to provide. I don't think anyone has really responded to this post, so I'll give it a go (from my own perspective, I'm not speaking for the company).

No doubt, the changes in 2004 were sizeable. In many ways I was very resistant to a lot of these as well. The shift from methods exclusively to properties made it kinda confusing to use components if you were used to MX. For my part, I think it's a bit weird to have a language based on dynamic property lookup (anonymous object with properties) have certain properties that run code, and others that don't. I put up a fight.

The reason others put forth were pretty solid though


Anyhow, there's an overview for the seemingly "arbitrary" nature of the changes. We took framework consistency more seriously than is apparent at first glance, but seeing as how there are new contexts for using components coming, we had to adapt to those changes. In most cases, APIs stayed more than 80% consistent, and where they changed, there were reasons. It wasn't a psychotic joke on our users (although if we were psychotic, we'd just be lying to .. never mind). On to rebuttals of the article:

There is a flash checkBox and a flash 2004 checkbox. This simple piece of code from Flash MX will fail in Flash MX 2004 :
trace(myCheckBox.getLabel());

I typed this into Flash MX 2004 Professional 2004 MX, with a new checkBox component on stage :

myCheckBox.setLabel("Muck"); trace(myCheckBox.getLabel()); // traces "Muck"

The dirty secret behind component properties is that they're almost always backed up by a getter-setter of the same name. It helps keep the property easier to extend (for reasons we can go into later, maybe after drinks), as well as make it more backwards compatible with MX project code. Poor communication, maybe, complicated requirements, definitely, but bad planning? I think we solved this the best way we could. Tom also brings up the comboBox and "addItem(), addItemAt(), etc". Those certainly didn't change, so I'm not sure where some of this is coming from.

On to the DataGrid example on Tom's article. We definitely argued over setColumns a bit in speccing the new components. It was obvious that this was a method that wanted to be a property (for the reasons listed above), but we had a conflict : Had we named the property "columns", we would be implying that you actually pass an array of DataGridColumn objects to the property. That was bad planning, definitely - back in 2002, when we released the DRK. Looking back, I do agree it would have been helpful to alias a "setColumns" method on the grid to keep it more backwards compatible.

But this brings me to the obvious point about backwards compatibility in the components. The biggest problem with carrying deprecated methods around is that it would have a negative impact on download size. Where it cost nothing in KB, we chose to keep things compatible, but when it came to things like aliasing new functions to old names, we made the difficult choice not too, and hope bandwidth savings would balance the pain to developers. We'd love to have left the old "changeHandler" or styleProperty mechanisms in place to gradually wean users off them, but in the end, it wasn't worth the cost of carrying them around.

I'm not going to bring up the bug in the help content Tom pointed out (except that I just did). The updater got it.

Tom brings up his most valid point when he mentions :

The problem is, how can we trust that anything we build today will be usable in the future? If a simple checkbox, combobox, or even text field cannot be made consistent from one version of Flash to the next, how is a programmer supposed to maintain or update existing applications without having to relearn property names, method names, and event names?

I agree totally, and I think this is something we at MM need to be communicating more clearly. I'll try to get someone with more authority than me to comment on this, but I can say that more and more projects at Macromedia are built using the current architecture as a foundation. It would take a huge, enormous reason to get us moving in any radical new directions for the next loooong while. I know I have no plans on writing new architectures, if that helps you any - converting to this one was probably more of a pain to me than anyone else :-). Stabilizing this platform is a top priority for us, and I think that focus is going to show. If you have more concerns about this subject, leave me a note.

rock. on.

Posted by nigel at 07:01 PM | Comments (7)

November 13, 2003

Portrait of the Engineer as a Young "Blog"ger

Umm.. Hi.

I've been trying to break the ice on this "blog" thing for a while.. No mean feat while working on a couple of MM projects at once (hint : one just shipped, and the other has something to do with hamburgers and Samuel L Jackson). It's easy for inertia to build up - I got the original design done months ago while fiddling with Fireworks + Dreamweaver one boring Sunday night, and it's been sitting here ever since, waiting for.. well... content.

Mission Statement : The Law of 3 Identical Questions

The main reason for the "blog" is that I get asked questions. Hopefully a sign I have answers. Problem being, sometimes I get asked the same questions about components like 10 times in the course of a week. After identical answer #3, I start to think "it would be a lot easier if I'd write this down". Hence, "blog".

So, here's the pledge I'm going to make and nearly immediately forget about and neglect : if I hear a problem/question/concern more than 3 times, relating to components, I'll try and figure some way of addressing it here. I tend to like technical issues the best ("how can I make component x do y?") and will spend more attention on them. I can't guarantee speediness of responses (or responses at all); I have work to do too, but I do want to help people get into the new components, which I think are pretty keen. So I'll try, and we'll see how it works out.

The best way to ask the questions would be on the FlashCoders list, which I'm most likely to be reading on a daily basis, and where the answer can be directed to the widest possible audience. Second best would be comments on this "blog", third best would be somewhere else in the "blog"-iverse or -osphere or whatever the kids are calling it. Compiling AS takes a while these days, so I have little fragments of time to read.

Awright, on with it. The first topic of the day will be : cellRenderers and customizing the Tree component, which is the coolest component out there, completely independent of my making it, I promise.

Posted by nigel at 02:39 PM | Comments (19)