nwebb

Flex, Flash, AIR

Archive for November, 2008

My Blog Posts – aims & considerations

I want to address a (very valid) question which has appeared several times in blog-comments. I’ve tried to pre-empt it in individual posts by stating that the examples are greatly simplified, but I think I need to further explain my approach in a central place so I can link to it next time the point is raised :)

Question: “You did X, wouldn’t it be *better* if you … “
I guess that can be paraphrased as “You showed me an example. Would you necessarily do it like that in a project?”, and nine times out of 10 the answer is a resounding “no”.

I may show a simplified example which traces the value of a button’s label, but you can bet your as3 that I wasn’t really attempting to trace the label of a button when I came across the issue. It may be “better” if I create a custom component which dispatches an event, but that assumes knowledge of creating components, event dispatching, plus an understanding of the reason for doing it that way (lose-coupling). What if my event exposes a collection, should I then also create an iterator? If I do it the “better” way I’ll be creating multiple classes whereas before I was only creating one. Which is the best solution considering the reason for the post? In my opinion, one that doesn’t cloud the original issue.

You’ll find other posts on my site which demonstrate an understanding of class responsibility, encapsulation, lose-coupling and many other architectural/best-practise techniques, and they concentrate purely on those issues. I rarely mix the two. Whether it’s right or wrong for me to do things this way is up for discussion, but I like that idea that people can take the essence of a post and be able to apply best practise techniques to what they’ve read … when *they* are ready to do so.

I also do a lot of spiking (“the practice of creating throwaway experiments during development”). This is often how I approach learning a new topic and it’s certainly not about best-practises. It means you generally throw all your code in one file … the test is throwaway anyway. Should something come out of it you can refactor at a suitable point. I realise I have to be more careful with these. Recently I posted up a spike test which was originally to do with collecting custom metadata  … recursing class hierarchies in order to collect this data, but it could have been taken as me suggesting it was the best way to examine class-hierarchies – it wasn’t. To me it was an unfinished script, intended to do much more than it currently does, and I’ll try to be more cautious in future and explain that. I’ll probably link to this post ;)

I still want those comments!! Question the way I do things and suggest other ways – that’s 50% of why I blog, because for me it’s also a great learning process, but at the same time be aware of the above and don’t take the code shown in an example as being my best-solution for the problem. It usually just simplifies everything to demonstrate a problem, discuss the possible causes and demonstrate a fix which confirms the cause (or at least tries to!)

One more thing …

I started writing tutorials and blogging out of frustration. I followed countless tutorials about x, only to find that they assumed knowledge of y  … examples of recursion assuming familiarity with the Fibonacci sequence … more recently examples of the Cairngorm framework, PureMVC or Mate using ColdFusion, when the example didn’t even cover the business logic side of things. I wanted to make sure I didn’t follow suit. After all why cloud the issue? Why make any unnecessary assumptions? If the tutorial isn’t about business logic, use dummy data and allow more people to fully understand the topic at hand. Too many assumptions in tutorials can be bad because they make the tutorial less accessible. I guess it depends to some extent on your intended audience but it’s certainly something every tutorial writer should bear in mind :)

As always, I’m interested to hear your views on this whole topic.

5 comments

Inheritance Chain Widget Thing

This afternoon I knocked together a little utility app … give it a class instance and it will visually display the inheritance chain using LinkButtons; Click one of the buttons and it will take you to the Livedocs documentation for that class.

Why? Not sure really. I was mulling over the idea of creating a video about custom metadata, which involved recursion up the hierarchy chain – so then I thought it would be a nice idea to cover recursion first … and then I got offered some interesting work so I won’t be doing either tutorial for a few weeks ;)

This is a basic idea with plenty of scope for expansion, so rather than let yet another bit of code sit in a cold dark folder, I thought I’d post it up. Right-click and “view source” to see the classes.

This example is also related to my last post.

3 comments

Dynamically Assigned Event Listeners (Gotcha)

Do you ever come across a problem and wonder how you've managed not to stumble upon it before?! This is one such case ...

Today I wanted to recurse over a hierarchical structure (in my case, to start with a class and find all the classes that it extends) and then create a button representing each class. The recursion wasn't an issue, but assigning event listeners was.

Take a look at the following example which highlights the issue:


Here is the code for the above example:

Actionscript:
  1. private function cc():void
  2. {
  3.     var classes:Array = new Array("MovieClip", "Sprite", "Object"); //fake the data
  4.    
  5.     /*
  6.         NOTE: Labels assigned correctly but Alert displays wrong item (the last one)
  7.             - because listener is passed by reference
  8.     */
  9.     for each (var item:String in classes)
  10.     {
  11.         var b:Button = new Button();
  12.         b.label = item;
  13.         var func:Function = function(e:Event):void{ Alert.show(b.label, "You clicked:"); }
  14.         b.addEventListener(MouseEvent.CLICK, func);
  15.         addChild(b);
  16.     }
  17. }

As you can see, every button has the correct label (assigned within the loop), but every button also traces the same thing - "Object" even though it was also assigned in the same loop. How can that happen? This is a sure sign that something is being passed by reference, not value.

The issue here is that when assigning an event listener, the second argument func is indeed passed by reference, and so it will always point to the last anonymous function created ... and in our case that is the one that traces "Object":

Actionscript:
  1. b.addEventListener( MouseEvent.CLICK, func ); //func is passed by reference

Most people will tell you that you can't pass the value in to a method like this either:

Actionscript:
  1. b.addEventListener( MouseEvent.CLICK, func(b.label) ); //try to pass arg to func - fail

However, I found one relatively simple way to achieve what I wanted, and the addEventListener code looks exactly the same as above, except there is a subtle difference in what you expect to happen, because func() returns a class of type Function.

The trick is to make func in to a call to a method which returns an anonymous function. Here is the example. As you can see, each button now traces the correct value:

func is still a reference, but it is a reference to a method which returns a unique anonymous function. The code is as follows.

Actionscript:
  1. private function cc():void
  2. {
  3.     var classes:Array = new Array("MovieClip", "Sprite", "EventDispatcher"); //fake the data
  4.    
  5.     /*
  6.         NOTE: Labels assigned correctly AND Alert displays correct item!
  7.             - because func returns a unique method for each button
  8.     */
  9.     for each (var item:String in classes)
  10.     {
  11.         var b:Button = new Button();
  12.         b.label = item;
  13.         b.addEventListener(MouseEvent.CLICK, func(b.label));
  14.         addChild(b);
  15.     }
  16. }
  17.  
  18. private function func (link:String):Function
  19. {
  20.            return function(mouseEvent:MouseEvent):void
  21.            {
  22.          Alert.show(link, "You clicked:");
  23.            };
  24. }

Note: The use of anonymous functions is not an issue as I don't ever wish to remove the listeners.

17 comments

Next Page »

Bad Behavior has blocked 399 access attempts in the last 7 days.