Idealism is what precedes experience; cynicism is what follows...

Wednesday, August 27, 2008

IDEFactory... currently in Beta… soon in production…

When using Adobe Flex to build enterprise scale systems, the limitations of Flex Builder becomes not only very apparent, but also a limitation for productivity and flexibility (note the irony :-) )

However, a group of talented developers have started on the quest to deliver architectural features to us inside Flex Builder… fortunately they have decided NOT to change the base, but build it as a plug-in to Eclipse / Flex Builder.


IDEFactory… looking really good sofar (however not in this picture :-) )…

http://www.idefactory.com/

RSL and the lack of a build-in map over class-definitions

In response to the lack of Reflection in ActionScript and the emergence of techniques such as RSL and Modules and the combination of these two, several initiatives have been launched to facilitate a map of class definitions within a SWF.

One is the SWFExplorer by ByteArray which is still in a very early stage of development, but it appears to become a simple and easy way to get the definitionNames from a SWF at Runtime.

Another is the getDefinitionNames by Dennis Kolyako which is a bit more complex in its implementation than SWFExplorer, but yields the same gross results.

SWFExplorer overall seems to fit the OO design model of Flex more than the latter implementation by Dennis which seems to match a more traditional Flash Authoring design model.

Adobe Flex training in a nutshell: Flex in a Week

Adobe has started an initiative they call "Flex in a Week".

It consists of a predefined set of tasks which put in sequence presumably should take the average intro-level developer about a week to complete…

Days 4 and 5 are still to be defined, but sofar it looks like a nice way to get new developers started… :-)
 

Check it out…

http://www.adobe.com/devnet/flex/videotraining/

Guice (pronounced 'Juice')

Guice (pronounced 'juice') is a lightweight dependency injection framework for Java 5 and above, brought to you by Google, however the principles are sound and could be used for other frameworks too.

Writing factories and dependency injection logic by hand for every service and client can become tedious. Some other dependency injection frameworks even require you to explicitly map services to the places where you want them injected.

Check it out... exciting stuff
http://code.google.com/p/google-guice/

Curved Scrollbar

Charles Petzold did a simple implementation of a curved scrollbar in XAML.
Nevertheless its probably more cool than useful, I have decided to do an implementation in Flash to match...



However... check the original posting by Charles...
http://www.charlespetzold.com/blog/2008/08/Curved-ScrollBars.html

Tuesday, August 26, 2008

.NET Reflector... no more Lutz Roeder

It appears that Luts Roeder have decided to leave development and maintenance of .NET reflector...

If you have ever used Reflector, you probably already know how cool a tool it is...
Creator and Inventor has left it to Red Gate to continue the further development...

Check it out...
http://www.simple-talk.com/opinion/opinion-pieces/the-future-of-reflector-/

Friday, August 22, 2008

ClassMappings between WebORB and Adobe Flex

Basically there are three methods to obtain a classmapping between WebORB and Adobe Flex.

1. ClassAlias in WebORB configuration.
2. ClassAlias in your ActionScript code through the "registerClassAlias" class.
3. ClassAlias in your ActionScript classes through the RemoteClass metatag.

1. ClassAlias in WebORB configuration
Add the following to your WebORB configuration file (This can also be done through the WebORB management console):


Name of ClientClass
Name of ServerClass
Name of assembly


2. ClassAlias in your ActionScript code through the "registerClassAlias" class.

var clientClass:Class = getDefinitionByName( clientClassName ) as Class;
registerClassAlias( serverClassName, clientClass );

3. ClassAlias in your ActionScript classes through the RemoteClass metatag.


[RemoteClass(alias="com.companyname.namespace.ClassName")]


The result is almost identical (some differences in behavior exists, but outside the scope of this short note) and will eventually mean that serverclasses returned and send to the server will be serialized and deserialized between the two class-definitions automatically by the WebORB server and the Flas Player respecitively.

The other Adobe Flex ACE's in Europe

Among ACE's in Europe within Flex, there are currently 3 others...

They are as follows...

Xavi Beumala from Barcelona... he had just been hired by Adobe Consulting when I last saw him to Flex 360 in Milan. A very sympathetic guy with great talent with the will to bring it far.

Dirk Eismann from Hannover... last i saw him it was at MAX in Barcelona where he was working for Herrlich and Ramuschkat. Extremely skilled and versatile developer which I have the outmost respect for.

Giorgio Natili from Rome... a real trailblazer and a true community leader from central Italy with a community of more than 3000 active users and 100.000 visits every month. I met him last time I was in Italy, a real fire-spirit...

Peter Elst from Belgium... one of the nicest guys in the community and on top of that an innovative and tech-savvy cool guy who contributes more to the community than averages...

...so obviously I am in very good company and I only hope that I some day can grow to match these true icons in the community and contribute as much as the have...

I got my Adobe Community Expert (ACE) designation today

I was delighted to learn today that I have been designated an Adobe Community Expert (ACE). Many know the program as the segue from Team Macromedia.

It may take a few days to get the listing on the site, however I look forward to continuing to contribute to the Flex/RIA and broader Adobe community.



Check out the existing ACE's on the listing...
http://www.adobe.com/communities/experts/all.html

Saturday, August 02, 2008

The MyLifeBits Project

I try to keep the clutter on this blog to an absolute minimum, I try to attain this by carefully considering what to blog about and by having a personal blog which tries to cover all the non-technical stuff I find relevant to share.

However, sometimes very interesting comes along which does not exactly reside in my knowledge domains but is technical enough to belong here, and hence "forces" me to blog about it in "The Combined Corner".

One such things is The MyLifeBits Project by Mr. Gordon Bell at Microsoft.

Ever try to remember who you bumped into at the store a few days back? Or exactly what the company president said at the morning meeting?

Well, you're not alone. And IBM researchers are working on software that just may help you better recollect all the forgotten pieces of your life.

This week, the company unveiled software that uses images, sounds and text recorded on everyday mobile devices to help people recall names, faces, conversations and events. Dubbed Pensieve, the software organizes bits of collected information, stores them and then helps the user extract them later on.

"Today, we're flooded with information. It's an information overload and we're not capable of handling it," said Eran Belinsky, an IBM project leader. "This would relieve us from the anxiousness or need to try to remember everything. And there's the issue of trouble with recollection. [It's like] your index is broken. You know you know something, but you can't get there. This could help people having trouble with their memory reconstruct their memories."

IBM's project is akin to one that of Mr. Gordon Bell and a couple of other scientists at Microsoft Research have been working on for the past nine years. Bell, a longtime veteran of the IT industry and now principal researcher at Microsoft's research arm, is developing a way for people to remember different aspects of their lives.

MyLifeBits has Bell supplementing his own memory by collecting as much information as he can about his life. He's trying to store a lifetime on his Dell laptop. Collecting telephone conversations, music, lectures, books he's written and read and photographs he's incessantly taken, Bell is amassing a great database of his life.

Interesting stuff... :)

Sunday, July 27, 2008

Adobe Flash Player : MultiThreading

These days I am recontemplating on my vision for a multithreaded AVM instance.

Jim Corbett said multithreading wasn’t being built into the ActionScript Virtual Machine, however, looking ahead into the inner workings of Flash Player 10, processing for the new bitmap filters using the programming language Hydra would be using multithreading! What’s more is that you don’t need to focus on manipulating DisplayObject items with Hydra, but are able to send it plain math equations as well, which it will be able to crunch blazingly fast, thanks to multithreading! So any math heavy Flash applications will get a HUGE performance boost, not to mention the various 3D engines and physics engines.

Adobe Flash Player : Codenames

On a funny sidenote... :)

While the Adobe code-name for Flash Player 10 is “Astro”, the Flash Player team has their own code-name for it… Bacon! That’s the name that the team voted for, they didn’t get that name, but still refer to it internally as Bacon. Flash Player 9 Update 3 was code-named Moviestar, but once again the internal Flash Player team referred to as Frogstar.

Google Gears : WorkerPool

The WorkerPool behaves like a collection of processes, rather than threads. Workers do not share any execution state. Changing a variable in one worker has no effect in any other worker. And created workers do not automatically inherit script code from their parents.

Members of a WorkerPool interact with each other only by sending message objects.

http://code.google.com/apis/gears/api_workerpool.html#workerpool_class

Google Gears

The latest entry among the candidate RIA technologies is Google Gears.



Still in version 0.3 at the time of this writing, its obvious that a lot of work needs to be done.

However, Google Gears (GG) has a couple of neat features...

* Database based on SQLLite.
* WorkerPool (JavaScript MultiThreading).
* Desktop Module to interact with the OS.

The Database module provides browser-local relational data storage to your JavaScript web application. Gears uses the open source SQLite database system. Ergo exactly as we have grown accustomed with Adobe AIR.

The WorkerPool module allows web applications to run JavaScript code in the background, without blocking the main page's script execution.
In web browsers a single time-intensive operation, such as I/O or heavy computation, can make the UI unresponsive. The WorkerPool module runs operations in the background, without blocking the UI. Scripts executing in the WorkerPool will not trigger the browser's "unresponsive script" dialog.
Nevertheless, since the browser's XmlHttpRequest object is not available in the context of a worker, Gears provides its own HttpRequest object to fill that need. Gears HttpRequest provides most of the features of XmlHttpRequest except for the ability to access the response as an XML DOM object and the ability to send a request synchronously.

Check it out...
http://gears.google.com/

A couple of more cool features are scheduled, but lets see which ideas actually make it out of the labs alive.

Some reasons to consider GG are that it does not require an explicit installation, just that you allow a specific site to run Gears enabled and that its open source in contrast to e.g. Adobe AIR and there a couple of more pretty interesting features of GG, but I will not get into that now.

When this is said, in my very humble graphical understanding - I think there exist a striking resemblance between Adobe AIR logo and the Google Gears logo and to be totally honest, the feature set if we disregard the very promising multi-threaded Javacsript... do you see what I mean ?

Adobe Flex : Change between Debug and Production Builds

Sometimes FlexAnt is just too troublesome to get working correctly (extisting projects tends to be difficulty to FlexAntify) so you need an easy way to toggle between Debug and Production builds...

Instead of going through your projects and setting the variables to Debug=false (even if you have a script / application that does it for you) it makes more sense to use the optimizer application from the Adobe SDK.

Then all you have to do is to call the following command on your binaries...
optimizer bin-debug/[binary].swf –output bin/[binary].swf –keep-as3-metadata=Bindable,Managed,ChangeEvent,NonCommittingChangeEvent,Transient

You can read more about the Optimizer here...

http://livedocs.adobe.com/flex/3/html/help.html?content=rsl_07.html

Adobe Flex : Code Quality of Flex 4

To be honest, I have great expectations to Flex 4... and as always, when I feel my expectations starting to rise - I begin to worry about the lurking disappointment which is one of the most frequent outcomes of high expectations...

Am I the only that think the note to the Scrollbar implementation sounds like an API problem (read: behavioral inconsistency) in the making ?



Check it out...

http://opensource.adobe.com/wiki/display/flexsdk/Gumbo+Component+Architecture#GumboComponentArchitecture-ExistingGumboComponents

Archived Adobe Flash Player Installers

When I was testing my theory regarding the AXIS cameras and the lack of a crossdomain file being the only obstacle to using the SWF stream, I needed the Flash Player 7 installer and I found this list in the Adobe KnowledgeBase:

http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_14266

It contains a download link to all players since Flash Player 2... for some reason they don't have an installer for Flash Player 1... please feel free to comment if you know of an explicit reason for this :-)

On a side-note, its interesting to see the peculiar growth in file-size.

Saturday, July 26, 2008

Debugging WebORB from Visual Studio

Its quite easy to debug applications running within the WebORB for .NET container with Visual Studio, however there are a few precautions to observe before its possible.

Some of the things I mention may seem obvious to you, but based on my experience - some of these very obvious details can be some of the pitfalls that prevent many developers from debugging their applications once deployed to WebORB, so now I include them here in my list for the seasoned developers to ignore and the novices to use.

First make sure that your assemblies are compiled with DEBUG information, you don't have to deploy the PDB files to the WebORB BIN directory. PDB files are the program database files which holds debugging and project state information for your program, but Visual Studio and the .NET runtime can map the debug assembly to the code in Visual Studio if just the PDB files are available in the output directory of the Visual Studio project.

From Visual Studio (I am using 2008, but its the same for 2005) with the code open used to generate the assemblies, you open the "Attach to Process" window found from the "Debug" menu.



Make sure that the checkbox "Show processes in all sessions" is selected.

Find the w3wp.exe (The IIS Worker Process) and attach the debugger to it.

I have for the sake of convenience mapped the following keyboard shortcut for opening this window: CTRL+SHIFT+ALT+F5. That has enabled me to start the debugging process with the following key sequence:

* CTRL+SHIFT+ALT+F5
* "w" or "W"
* RETURN

Now Visual Studio will start the debugging session and map the debugging assembly to the code in Visual Studio.
As the debugging information are loaded you will see your breakpoint indicators be filled out, effectively indicating that debugging information mapping to the current code have been loaded. If your breakpoint indicators remain unfilled circles, it is not working, a likely cause for this is that the deployed assemblies have been compiled without DEBUG information.



Once your assemblies are loaded correctly and your breakpoint indicators are correctly filled, you turn your attention to either your application or the WebORB management console (I recommend the latter as its always a good idea to test each tier isolated).

Once you execute the code which eventually will hit the breakpoints, control will be transferred to Visual Studio and your debugging session should be fully active.

PS. Yes, the code in the second screendumb is a joke :-)

Friday, July 25, 2008

AXIS IP Cameras SWF Streams are not loadable with recent Flash Players

Due to changes in the security settings of the Flash Player Platform its not possible to view SWF streams from AXIS IP cameras with Flash players later than Flash Player 7 effectively preventing anyone from using the build-in SWF streams of the AXIS IP cameras as is.

I therefore uninstalled my Flash Player 9, installed Flash Player 7 and then, voila... no problem loading the SWF's directly from the cameras :-)

Nevertheless, since the cameras are NOT shipped with a crossdomain file, and therefore does not allow the SWF to be loaded from other domains than the camera itself, there is no other option than to get a crossdomain file into the camera's webserver's root.
Unfortunately did a quick examination of AXIS's Management Software for their cameras not indicate that it would be possible to access the filesystem on the camera. However, after registering that the there was a FTP server on the camera, i quickly connected through FTP and could easily browse, however I could still not write a file - so only read-access.

However, the AXIS Custom Firmware Tool allows for this, but unfortunately "AXIS Custom Firmware Tool is exclusively available for members of the Axis ADP Program".
(http://www.axis.com/files/tech_notes/development_guidelines_1_00.pdf)

Therefore, I'm gonna do five things now.

1. Examine the Management Tool to see if there is an undocumented way to get access to the filesystem of the Cameras.
2. Examine if there is alternative way to access the filesystem.
3. Apply for membership of the AXIS Application Development Partner (ADP) Program.
4. Ask the vendor providing the cameras here in Denmark to add a crossdomain file to the image.
5. Ask AXIS customer support if they are planning Firmware updates addressing this issue.

WebORB : Installing on Vista

A few precautions have to be observed when installing WebORB on a Windows Vista machine.
Fortunately Mark Piller from MidnightCoders have published an easy-to-follow guide to installing it successfully.

Check it out...
http://www.themidnightcoders.com/weborb/dotnet/vistainstall.shtm

Thursday, July 24, 2008

Adobe MAX 2008 in Milan is now open for registration

Today Adobe has opened for registration for this year's Adobe MAX Conference in Milan.

Check it out...
http://max.adobe.com/eu/register/

Wednesday, July 23, 2008

Adobe Flex : MXML 2009 Specification

The MXML 2009 (Adobe Flex 4, Gumbo) specification is made available in an "as is" version...

Check it out...
http://opensource.adobe.com/wiki/display/flexsdk/MXML+2009

Adobe Flex : Documentation for Gumbo (Flex 4)

The Adobe Flex 4 (Gumbo) documentation is made available in an "as is" state...

Check it out...
http://livedocs.adobe.com/flex/gumbo/langref/

Adobe Flex : 3 methods for Deeplinking

Adding support for deep-linking is simple in Flex.
The three most popular methods these three in no particular order:
* http://code.google.com/p/urlkit/
* http://code.google.com/p/swfobject/
* http://labs.adobe.com/wiki/index.php/Flex_3:Feature_Introductions:_Deep_Linking

Tuesday, July 22, 2008

Workaholics United : Push, Pull & Standardization

Waste is a constraint. Reducing waste in your organization is one the easiest ways of reducing constraints.

And here’s a surprise—waste in offices is usually greater than in factories, especially because it’s easy to hide waste in cumbersome or non-existent processes. Creating unnecessary information inventory is another common waste in offices. Doing too many tasks “in anticipation” of a possible client, for example…

One way to think about waste is in terms of push and pull systems. A push system, like much of traditional manufacturing, produces as much product as the company can and/or wants to produce and then gets it out to the customer. The result is usually large inventories.

A pull system only produces what a customer needs and has asked for. You want to have as much “pull” in your systems as you can. Toyota has very little excess inventory. That’s why when the Prius was so unexpectedly popular, people found themselves on waiting lists for the car. Seems like a problem, but Toyota is much more profitable as a result of being so lean. You might also hear this concept referred to as “just-in-time production” or JIT (remember? — it came from the supermarkets).

I think of it this way — there’s a place for everything and everything in its place. No more. No less.

Here’s a story on how to reduce waste (figuratively and literally), by integrating people and process in a pull system.

Many places all over South East Asia (And many other places for that matter), you don’t have a conventional toilet. However, some places in Japan you don't only have a hole in the ground, instead there is an incinerator toilet as many Japanese are shy to have their bodily disposables exposed to even sewer rats. You first press a button to start the heating system and then put a special purpose coated paper bowl liner (like a coffee filter, but don’t try using one for this purpose it won’t work) down between two sloping pieces of steel (sort of like a toilet bowl liner). You do “your business” into the paper filter, step onto a lever, and wave goodbye to your waste and any toilet paper. The toilet incinerates the filter and extra donations from you at a very high temperature, somewhere around 6,000 degrees Celcius or the surface temperature of the sun, whichever is hotter. It’s a great way to eliminate waste. However, you can’t use the toilet without these special purpose coated paper bowl liners—they’re needed to keep the steel clean while also aiding in the incineration process. Many have tried and got a good scolding for it.

A friend of mine and his wife have implemented a very simple “pull system” so that we always have just the right number of liners. Not too many, which ties up money and takes up extra space with excess inventory. Not too little which can shut down the incinerator if it’s overburdened by non-regulation uses.

Over time my friend and his wife have determined just how many boxes of this paper to keep on hand, based on the frequency of use. It happens to be four boxes. These boxes are then stacked on a specific shelf (the one closest to the toilet, not down the hall, which would create a different kind of production problem, but right where you need them—and can reach them).

On the bottom box is written—when you open this box tell Daniel or Yuko. You do tell them because it’s built into the culture of the dojo and you are part of the smooth functioning of the system. They then order 4 more boxes—and have determined, through learning by doing, just how long it takes to receive a shipment of 4 new boxes. It’s a very simple pull system that, in this case, only produces the right kind of waste.

As you can tell, there are a number of keys to success in this process.

Everything about this process is clearly visible and apparent to everybody involved in the process. If the box marked when you open this box tell Daniel or Yuko was inside a dark, hard to reach, cabinet, or it was written on the bottom of the box instead of on the flap that you have to open to get at the liners, it might not get noticed. The process relies on this visual indicator. Visual indicators or management charts, or checklists, etc. allow for communication and sharing. You can create standardized work sheets, but if you don’t have a way of seeing them, and the process, as if it were in a glass box, it’s likely that the standard practice won’t be followed and breakdown and waste will occur.

Problems have a way of bubbling up to the surface. The longer you let them simmer the bigger the problem will be when it surfaces. Our goal is to create standardized work processes that bring issues and problems to the surface, using visual indicators so no problems are hidden, at the earliest possible moment. People are stimulated by the visual, tactile and audible. People are part of the process.

Remember, we’re integrating. So it stands to reason that being able to see everything you manage is a balanced and harmonious way of creating flow in your work.

Monday, July 21, 2008

Workaholics United : Consider All Factors (CAF)

In any situation, certain givens define the range of how we perceive it. By expanding the scope of considerations with a conscious effort, we can increase the span of our attention to aspects that might have otherwise been missed.

Consider All Factors (CAF) is an attention directing tool designed to do this. During a defined interval of time, you mentally list every consideration about a topic you can think of, as opposed to just the first few that come to mind.
An example

A shy person is invited to a party. His default reaction is to think, “I’m just not an extrovert.” For this exercise he decides to enrich his perspective by considering other factors in that social situation:

* Body language
* Greetings
* Response to questions
* Questions to ask others
* Dressing for impact
* First impressions
* Smiling
* Who’s there that I already know?
* Purpose of attending
* Anxiety created by unfamiliarity

Some considerations arguably overlap: first impressions, dressing for impact, smiling. It doesn’t matter, and would be counterproductive to censor new angles on what might be thought of as the same theme, since the only way to really know is in hindsight. In this case, the person might not have previously paid any attention to the role of personal appearance in creating good first impression, despite that factor being obvious to others.

By consciously distributing cognition around a topic, he gives himself new things to think about. The consideration “purpose of attending” might contrast with going to the party simply because he was asked, instead of having a deliberate focus to guide to his behavior. The consideration, “anxiety created by unfamiliarity” is interesting. One strategy for overcoming his social apprehension is to familiarize himself with everyone in the room, making as many introductions as possible to avoid being confronted with a crowd of strangers.
Other examples

We can “do a CAF” for a couple of minutes on just about any topic, either for better planning or simply for its own sake as a mental exercise. Doing a CAF on apartment hunting might yield:

* Commute to and from work
* Length of lease
* Rent
* Total move-in cost
* Impression of landlord
* Square footage
* Aesthetics
* Noise level of surrounding area
* Walking distance to amenities (e.g. stores, parks)
* Parking
* Consensus with other decision makers
* Furniture
* Pets
* Terms of rental agreement

Again, some overlap. Pets and lease length would be covered in the rental agreement, but isolating “terms of rental agreement” as a separate item might prompt the apartment hunter to look more carefully for unreasonable clauses instead of taking the contract for granted. Notice that the apartment hunter has also factored in “impression of landlord” as a conscious consideration rather than leaving it as an afterthought or subliminal intuition.

Starting a exercise program:

* Type of exercise
* Clothing
* Equipment
* Schedule
* Home, gym, personal trainer?
* Fitness goals (e.g. weight, running distance)
* Handling eventual decline in discipline or enthusiasm
* Nutrition
* Documenting progress

This person has identified a decline in discipline and enthusiasm as something to deal with before its onset. It’s much easier to plan for setbacks in advance than trying to address them while they’re happening.

And now to the essence of my point... If you apply CAF to a software programming task, and the benefits become much more apparent. Make it a habit to perform a CAF at the inception of a programming assignment, and you will experience that your estimates will be closer to actual outcome and that your solution quality will increase because you become able to handle many issues pro actively, which may in other cases have become problems and forced you to do hacks-tweaks in order to get the code to conform to functional requirements within your estimated time frame.

The more you practice the CAF operation, the easier it gets, and less inclined you are to be satisfied with accepting the first considerations that immediately come to mind. When you think about a new topic, you’ll begin to instinctively ask yourself, “What am I missing?”

Sunday, July 20, 2008

Estimation : Off-The-Cuff Estimates

Project teams are sometimes trapped by off-the-cuff estimates.

A projectmanager on a team asks, for example, "How long would it take to implement this component", while showing the developer a wireframe. The immediate response is typically, "I don't know. I think it might take a week. I'll check into it", and of the developer is to his/her desk to investigate the functional requirements further. Back at the desk the developer looks at the design and code for the component, back at the desk the developer notices a few things forgotten when the PM asked the question, adds up the changes and decides that it would take about 3 weeks. The developer hurry over to the PM's desk to update the first estimate, but the PM is in a meeting and therefore not to be found. Later that day the PM suddenly appear at the developer's desk and happily notifies the developer (before this can get a word out): "Since it seemed like a small project, I went ahead and talked to the customer about it. He was very excited about it and can't wait to see the component next week. Can your start working on it today?".

I have found that the safest policy is NOT to give off-the-cuff estimates. Using intuition and guessing as basis of software estimates are almost always related with cost and schedule overruns.

One of the errors people commit when estimating solely from personal memory is that they compare the new project to their memory of how long a past project took, or how much effort is required. Unfortunately peoples sometimes remember their estimate for the past project rather than the actual outcome of the past project. If they use their past estimate as the basis for a new estimate, and the past project's actual outcome was that it overran its estimate, guess what? The estimator has just calibrated a project overrun into the estimate for the new project.

While guessing and intuition most definitely are positively correlated with project overruns, another less recognized fact is that the use of documented facts are negatively correlated with project overruns. In other words, there is a world of difference between giving the PM an off-the-cuff estimate versus saying, "I can't give you an answer of the top of my head, but let me go back to my desk, check a few notes, and get back to you in 15 minutes. Would that be OK?".

While this is a simple point, off-the-cuff estimates is one of the most common errors that project teams make. So in order to become a better software engineer, we need to stop delivering off-the-cuff estimates !

This blog post is the first in a long series about estimation I will be doing. Estimation is probably the single most important skill next to actual programmatic skills for a programmer, and even for non-programmers estimation is one of the most frequently performed activities, however also one of the skills that we pay the least attention to.

First step in becoming a better estimator is to realize that off-the-cuff estimates are invalid and errorprone, and should be replaced by a structured analysis of the entity being estimated based on documented facts.

Flash Player is the most ubiquitous Platform available

In the past, I’ve voiced that the non-pervasiveness of Flash (rather an average user’s ability to install plug-ins) is one reason website designers should consider before going for Flash. I officially scrap that as a point no longer valid.

Millward Brown, one of the world’s leading market research agencies, recently closed a survey commissioned by Adobe Systems, Inc. with a goal “to track and compare Plug-In technology used to view content on the web.” This study, conducted quarterly, placed Adobe Flash Player at a comfortable 99% as the most pervasive software platform. Java (85%), Microsoft Windows Media Player (79.3%), Apple QuickTime Player (65.5%) and Adobe Shockwave Player (59.2%) round up the top five. The maximum margin of error was reportedly +/-6%.

Pervasiveness, or penetration, is defined based on the presence of a platform on Internet-enabled desktops in mature markets (US, UK, Canada, France, Germany and Japan). The study has results from countries like mainland China, South Korea, Russia, India, and Taiwan as well. However, nothing explicit was mentioned about Philippines, Brazil and Romania which according to my latest trend check are among the top 9 regions searching for RIA technologies.

To me, the biggest surprise is the high position of QuickTime. Can anybody explain it?

Visit the methodology page for in-depth details about the study, and the version penetration page for statistics by version.

Writing Final Classes and Methods

Final Classes
You can declare that your class is final; that is, that your class cannot be subclassed. There are (at least) two reasons why you might want to do this: security reasons and design reasons.

Security
One mechanism that hackers use to subvert systems is to create subclasses of a class and then substitute their class for the original. The subclass looks and feels like the original class but does vastly different things possibly causing damage or getting into private information. To prevent this kind of subversion, you can declare your class to be final and prevent any subclasses from being created. The String class is a final class for just this reason. The String class is so vital to the operation of the compiler and the interpreter that the system must guarantee that whenever a method or object uses a String they get exactly a String and not some other string. This ensures that all strings have no strange, inconsistent, undesirable, or unpredictable properties.

If you try to compile a subclass of a final class, the compiler will print an error message and refuse to compile your program. In addition, the bytecode verifier ensures that the subversion is not taking place at the bytecode level by checking to make sure that a class is not a subclass of a final class.

Design
Another reason you may wish to declare a class as final are for object-oriented design reasons. You may think that your class is "perfect" or that, conceptually, your class should have no subclasses.

To specify that your class is a final class, use the keyword final before the class keyword in your class declaration. For example, if you wanted to declare your (perfect) EncryptionAlogrithm class as final, its declaration would look like this:

final class EncryptionAlogrithm
{
. . .
}

Any subsequent attempts to subclass EncryptionAlogrithm will result in a compiler error.

Final Methods
If creating a final class seems heavy handed for your needs, and you really just want to protect some of your class's methods from being overridden, you can use the final keyword in a method declaration to indicate to the compiler that the method cannot be overridden by subclasses.

You might wish to make a method final if the method has an implementation that should not be changed and is critical to the consistent state of the object. For example, instead of making your EncryptionAlogrithm class final, you might just want to make the decrypt method final:

class EncryptionAlogrithm
{
. . .
final void encrypt( message:IMessage )
{
. . .
}
. . .
}

Workaholics United : Playing the Percentages

Whenever management lays down some new policies for customers or employees, there will inevitably be some degree of blowback. Any change, from moving to a outsourcing to India to moving furniture from one department to another, disrupts our sphere of comfort.

Since I can’t get away with simply saying, “Well, that’s different from what I’m used to,” I would be inclined to gather some negative results designed to invalidate the new policy. One time I was asked to implement an email autoresponder with text I disagreed with. After a few days, I got a couple of complaints from customers, so I argued to the boss that we should scrap the autoresponder. Referring to the complaints, he asked the question I’d come to expect from him:

“What percentage of the time does this happen?”

I sighed, knowing that not only had I been shot down, but that he was right in principle. I felt foolish telling him that I had received three complaints out of hundreds of email exchanges.

With any new project, some things are bound to go wrong. A zero-defect mentality is a zero-action policy. For practical goal realization, the operative principle should be to contain risk, not eliminate it. A certain amount of risk analysis is healthy. The trick is to identify the point of diminishing returns where further steps to reduce risk are actually attempts to eliminate risk, which is unrealistic.

There’s no formula for determining that point, only an intuition or an arbitrary definition that involves asking an answer certain questions:

* How seriously would the problem impact this?
* What percentage of the time does the problem happen?
* What percentage is acceptable?
* Is the problem irreversible?
* What other problems could happen?
* What steps could be taken to fix the problem?
* What steps could be taken to prevent the problem without abandoning the project?
* What problems would result from abandoning the project?
* Does the positive impact of success outweigh the negative impact of failure?

Psychologically, risk is “contained” when it’s given precisely the amount of attention appropriate to it, not more. The focus is predominantly on the likelihood of a negative outcome rather than the details of it. Problems are converted into projects, defined in terms of successful outcomes and next actions.

Recognize the difference between creating slack and being a slacker. Define your margin for error and embrace the art of strategic failure as a practical price to pay for accomplishing bigger goals.

Saturday, July 19, 2008

21 laws of Programming

1. Any given program, once deployed, is already obsolete.
2. It is easier to change the specification to fit the program than vice versa.
3. If a program is useful, it will have to be changed.
4. If a program is useless, it will have to be documented.
5. Only ten percent of the code in any given program will ever execute.
6. Software expands to consume all available resources.
7. Any non-trivial program contains at least one error.
8. The probability of a flawless demo is inversely proportional to the number of people watching, raised to the power of the amount of money involved.
9. Not until a program has been in production for at least six months will its most harmful error be discovered.
10. Undetectable errors are infinite in variety, in contrast to detectable errors, which by definition are limited.
11. The effort required to correct an error increases exponentially with time.
12. Program complexity grows until it exceeds the capabilities of the programmer who must maintain it.
13. Any code of your own that you haven’t looked at in months might as well have been written by someone else.
14. Inside every small program is a large program struggling to get out.
15. The sooner you start coding a program, the longer it will take.
16. A carelessly planned project takes three times longer to complete than expected; a carefully planned project takes only twice as long.
17. Adding programmers to a late project makes it later.
18. A program is never less than 90% complete, and never more than 95% complete.
19. If you automate a mess, you get an automated mess.
20. Build a program that even a fool can use, and only a fool will want to use it.
21. Users truly don’t know what they want in a program until they use it

Workaholics United : Upgrade an Unproductive Day by Mentally Rehearsing a Better One

There’s no going back in time, but there are ways to learn from the past rather than live in it.

Every day we walk through a minefield of potential distractions, sometimes arriving on the other side unscathed, sometimes not. One digression leads to another, the cycle repeats, and hours later we wonder where the time went. It’s tempting to criticize ourselves for getting nothing none that day, and even if the criticism is somewhat accurate (it’s unlikely that nothing got done), the diagnosis itself is idle — which is to say, “So what?”

Figuring out the obvious moves nothing forward. On the other hand, recognizing the problem implies recognizing the solution. When I run into this situation, I ask myself to process questions:

* How did I get nothing done today?
* What will I do differently tomorrow?

Since a day’s accomplishments, or lack thereof, is the sum of many behaviors, neither of these questions can be addressed by a single answer — at least to have the level of precision necessary to make a substantial change.
Mental modeling

It’s not enough to know our worst practices in general. To make tomorrow a more accomplished day than today, we need to rewind the film strip to the precise moment where we got derailed.

For instance, I noticed that whenever I boot a computer and don’t seem to get straight to business, the problem usually starts at boot time. Since I can’t do anything on the laptop for two or three minutes, I start to zone out. What I would be doing if boot time wasn’t a factor is doing a daily review on the IPhone Desktop, looking at each of my action lists.

Asking myself, “What would I do differently?”, it took about 10 seconds to realize that I needed to have my lists — especially my @Computer list — available before the computer was. So I started scanning my todo's on my cell-phone, so that by the time the hourglass on my computer’s screen disappears, I can hit the ground running.

I have introduced daily standup meetings on my team at 9:30 where we one by one describe the tasks that we have planned for the day and thereby get a chance to both think the day through at its beginning, but also to use the team to share problems or ideas.
The basic idea is to mentally step through the day, looking for the forks in the road that compelled you to do X when you know in hindsight that you should have been doing Y. When was the precise moment what your attention shifted to the path of less resistance? What precisely was the distraction?

I believe the sequence of behaviors is critical, and that the earlier ones have the most leverage. If you can maintain a chain of focused activity in the first few hours, you create the momentum necessary to minimize the effects of distractions later on.

Sometimes the problems aren’t necessarily distractions, but behavioral patterns that yield predictably regrettable results. Having too many sugared foods or beverages in the morning leads to an energy crash in the afternoon. Driving past a great bookstore on the way home from work leads to the unbearable lightness of wallet. A change of environment or route may be in order.

After reviewing the dysfunctional day, mentally step through what a focused tomorrow would look like, moment to moment, from morning to evening. What better practices will you be implementing? Which behaviors will you avoid doing?

Always make tomorrow a better day.

Flex : URI Class implementation

Browsing through the my company's code repository (what else to do Saturday night ?) I found a number of different URI class implementations... whereas they did differ a little bit in implementation, the overall implementations were very similar and mostly differed in quality.

None of them however were as good as Mike Chambers' implementation which can be found in the AS3CoreLib.

If you have not yet checked it out yet and you sometimes find yourself in need of a good URI class implementation, consider using this one...

http://code.google.com/p/as3corelib/source/browse/trunk/src/com/adobe/net/URI.as

Flex : Pageable ArrayCollection with support for active paging

Yesterday one of the developers in my company had the need for a PagedArrayCollection. A quick search on Google revealed only this implementation, which turned out to be buggy so I decided to implement one myself.

I designed an interface called IPagedCollection which in combination with an extension of the existing mx.collections.ArrayCollection implementation would do the job.

Only hurdle was the need to override addItemAt and removeItemAt as the autoUpdate doesn't seem to work when a filterFunction is employed. I will look in to this phenomena, but as for now a call to refresh after inserting or removing does the job nicely.

The code itself is quite simple, I have also created a small demo-application which illustrates the use of the collection.

Live Demo

Download of Sources

/**
* Copyright(c) 2008 HelloGroup A/S, some rights reserved.
* Your reuse is governed by the Creative Commons Attribution 3.0 Denmark License
**/
package com.hello.collections
{
public interface IPagedArrayCollection
{
function get currentPage() : Number
function set currentPage( value:Number ) : void;

function get numberOfPages() : Number;

function get pageSize() : Number;
function set pageSize( value:Number ) : void;

function get lengthTotal() : Number;
}
}



/**
* Copyright(c) 2008 HelloGroup A/S, some rights reserved.
* Your reuse is governed by the Creative Commons Attribution 3.0 Denmark License
*
* Known Issues:
* - When the collection changes in size or pagesize, the currentPage is not updated. This is a problem if currentPage is set to a higher value than in the new collection.
**/
package com.hello.collections
{
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;

public class PagedArrayCollection extends ArrayCollection implements IPagedArrayCollection
{
private var _currentPage:Number = 1;
private var _numberOfPages:Number = 1;
private var _pageSize:Number = 10;

public function PagedArrayCollection(source:Array=null)
{
super( source );
filterFunction = filterData;
addEventListener( CollectionEvent.COLLECTION_CHANGE, onChange );
}

/**
* Adds an item to the collection at the specified index.
*
* @param item Item to be added
* @param index Index of the item to be added
*
* Note: Needs to be overridden in order to trigger refresh. AddItem eventually calls this function so its not needed to override addItem
*/
override public function addItemAt( item:Object, index:int ) : void
{
super.addItemAt( item, index );
refresh();
}

/**
* Removes the item from the collection at the specified index
*
* @param index Index of the item to be removed
* @return The item removed
*
* Note: Needs to be overridden in order to trigger refresh
*/
override public function removeItemAt( index:int ) : Object
{
var removedItem:Object = super.removeItemAt( index );
refresh();
return removedItem;
}

protected function onChange( event:CollectionEvent ) : void
{
if( _numberOfPages != numberOfPages )
{
_numberOfPages = numberOfPages;
onPagingChange( PagedCollectionEventKind.NUMBEROFPAGES_CHANGE );
}
}

protected function onPagingChange( kind:String ) : void
{
dispatchEvent( new CollectionEvent( CollectionEvent.COLLECTION_CHANGE, false, false, kind ) );
}

[ChangeEvent("collectionChange")]
public function get currentPage() : Number
{
return _currentPage;
}
public function set currentPage( value:Number ) : void
{
_currentPage = value;
refresh();
onPagingChange( PagedCollectionEventKind.CURRENTPAGE_CHANGE );
}

[ChangeEvent("collectionChange")]
public function get numberOfPages() : Number
{
var result:Number = source.length / pageSize;
result = Math.ceil( result );
return result;
}

[ChangeEvent("collectionChange")]
public function get pageSize() : Number
{
return _pageSize;
}
public function set pageSize( value:Number ) : void
{
_pageSize = value;
refresh();
onPagingChange( PagedCollectionEventKind.PAGESIZE_CHANGE );
}

[ChangeEvent("collectionChange")]
public function get lengthTotal() : Number
{
return source.length;
}

private function filterData( item:Object ) : Boolean
{
var dataWindowCeiling:Number = pageSize * currentPage;
var dataWindowFloor:Number = dataWindowCeiling - pageSize;

var itemIndex:Number = getItemIndex( item );

var result:Boolean = dataWindowFloor <= itemIndex && itemIndex < dataWindowCeiling;
return result;
}
}
}


/**
* Copyright(c) 2008 HelloGroup A/S, some rights reserved.
* Your reuse is governed by the Creative Commons Attribution 3.0 Denmark License
**/
package com.hello.collections
{
public class PagedCollectionEventKind
{
public static const CURRENTPAGE_CHANGE:String = "currentPageChange";
public static const PAGESIZE_CHANGE:String = "pageSizeChange";
public static const NUMBEROFPAGES_CHANGE:String = "numberOfPagesChange";
}
}


This is the small demo-application which illustrates and validates that the collection works.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="vertical"
initialize="onInitialize(event)"
creationComplete="onCreationComplete(event)">

<mx:HBox width="100%">
<mx:Label text="Key:" />
<mx:TextInput id="keyInput" text="NEW KEY" />
<mx:Label text="Value:" />
<mx:TextInput id="valueInput" text="NEW VALUE" />
<mx:Button id="addButton" label="Add Item" />
<mx:Button id="removeButton" label="Remove Item" enabled="{ grid.selectedItem != null }" />
<mx:Label text="Set PageSize:" />
<mx:ComboBox id="pageSizeSelector" dataProvider="{ [ 5, 10, 25] }" selectedIndex="1" change="{ collection.pageSize = Number( pageSizeSelector.value ) }" />
</mx:HBox>
<mx:DataGrid id="grid" dataProvider="{ collection }" width="100%" height="100%" />
<mx:HBox>
<mx:Label text="Count: { collection.length } ({ collection.lengthTotal })" />
<mx:Label text="( { collection.currentPage }/{ collection.numberOfPages } )" />
<mx:Label text="PageSize: { collection.pageSize }" />
<mx:Button label="Previous" enabled="{ collection.currentPage > 1 }" click="{ collection.currentPage-- }" />
<mx:Button label="Next" enabled="{ collection.numberOfPages > collection.currentPage }" click="{ collection.currentPage++ }" />
</mx:HBox>

<mx:Script>
<![CDATA[
import mx.events.CollectionEvent;
import mx.events.FlexEvent;
import com.hello.collections.PagedArrayCollection;

[Bindable]
private var collection:PagedArrayCollection;

private function onInitialize( event:FlexEvent ) : void
{
var collection:Array = new Array();

for( var i:Number = 1; i <= 20; i++ )
{
collection.push( { key:"Item_Key_"+ i, value:"Item_Value_"+ i } );
}

this.collection = new PagedArrayCollection( collection );
this.collection.addEventListener( CollectionEvent.COLLECTION_CHANGE, onItemsChange );
this.collection.refresh();
}

private function onCreationComplete( event:FlexEvent ) : void
{
addButton.addEventListener( MouseEvent.CLICK, addButton_Click );
removeButton.addEventListener( MouseEvent.CLICK, removeButton_Click );
}

private function addButton_Click( event:MouseEvent ) : void
{
collection.addItem( { key:keyInput.text, value:valueInput.text } );
}

private function removeButton_Click( event:MouseEvent ) : void
{
collection.removeItemAt( collection.getItemIndex( grid.selectedItem ) );
}

private function onItemsChange( event:CollectionEvent ) : void
{
trace( event.kind +" collectionchanged" );
}

]]>
</mx:Script>

</mx:Application>

Wednesday, July 16, 2008

PV3D : Training in Cologne

The Rich Media Institute are having one of their renown PV3D training courses in Cologne at the end of this month.

I am still hoping to to have the time to go there, perhaps not as much for the sake of learning new stuff as I have already attended some courses and have some experience already, but also to hang out with a lot of cool people and get a peek at all the amazingly cool stuff that is going on out there in the community.

Check it out...
http://www.richmediainstitute.com/papervision_cologne

Tuesday, July 15, 2008

Flex SDK : Skinning in Flex 4 (Codename: Gumbo)

The Flash Player is the delivery mechanism for some of the most creative work to be found on the web today. Flex applications however have gained a reputation for looking too similar to each other, as many developers choose to use the Flex default look and feel (known as Halo) as opposed to applying extensive styling or skinning. Research performed by Adobe shows that only 46% of our frequent Flex users do extensive skinning while only 22% even do major style adjustments. This is not to say that customization never happens, but Adobe found that it remains too challenging to create a truly custom experience. It is therefore a priority for Gumbo (The new version of the Flex SDK) to make easy customization of Flex application experiences the norm instead of the exception.

Exciting stuff... Check it out...
http://opensource.adobe.com/wiki/display/flexsdk/Gumbo+Themes

Thursday, July 10, 2008

ILog Elixir 2.0 Beta Program Started

The ILog Elixir Team have created a cool Beta program which allow developers a early preview of things to come.

Just sign up and check it out...
http://blogs.ilog.com/elixir/2008/07/03/ilog-elixir-20-preview-program-starts/

Wednesday, July 09, 2008

Google Trends of XAML and MXML

Despite the huge momentum Adobe Flex have gained the last year or so, its clear that XAML still have more momentum overall, according to Google Trends.

XAML is the markup language from Microsoft to create RIA's and one of the cornerstones in Silverlight, MS's "new" primary RIA platform. MXML is the markup language used in Adobe Flex, Adobe's primary RIA platform and has been around for quite a shorter time than XAML.

Here is a direct link to the comparison I did:
http://www.google.com/trends?q=xaml%2Cmxml



An interesting observation is related to the geographical distribution of the searches, seeing that India is top-ranking in regards to Country, however in regards to City its Redmond, VA (The home of Microsoft).

Another interesting point is that Denmark and Danish is at the time of this comparison (it's off course subject to change, partly due to the dynamics of the Google indexing system based on statistically enhanced numbers and off course due to the fact that the numbers eventually do change over the course of time) ranked 10 and 6 respectively, positioning the Danish RIA community high on the international rank.
Combine this with the positions of our brothering countries, Sweden and Norway, Scandinavia is definitely in the super-liga of RIA regions.

A Flex SEO contest (by Ryan Stewart)

Mr. Ryan Stewart has announced a Flex SEO contest to get people involved in helping the Flex SEO possibilities evolve into a set of techniques and likely some practices as well.

Check it out...
http://blog.digitalbackcountry.com/?p=1478

Tuesday, July 08, 2008

Adobe Flex : The Undocumented StaticEventDispatcher

There is an undocumented feature of the Flex Compiler which can come in quite handy.

If you have wanted to listen for changes to static variables, there is an undocumented static variable called "staticEventDispatcher" on classes that have one or more static variables prior to compilation.
The way it works is that as part of compiler pre-processing, the Flex compiler adds a static EventDispatcher object to the class, which eventually can be used to listen for PropertyChangeEvents on the class-reference itself.

If the class does not have a static variable at compiler preprocessing time, the staticEventDispatcher is not added. Despite the i-logic of the fact that a public static property (getter/setter functions) does NOT result in the pre-processor adding the staticEventDispatcher reference it can off course be worked around by adding a variable which references the function in which you have not broken the "contract" of the class, but still have "triggered" the Flex compiler to add your staticEventDispatcher.

The code below is just exploratory-code, and should off course NOT be used anywhere, it just proves the point about the discrepancy about static properties and variables.
public static var getSomethingFunction : Function = something as Function;
public static function get something() : String { return "Hello World"; }

This feature of the Flex compiler is very closely related to an undocumented class in the Flex framework, its the StaticPropertyWatcher which extends its more wellknown cousin, the Watcher class in the same mx.binding.* namespace.
Seeing that the StaticPropertyWatcher actually uses the staticEventDispatcher mechanism of the Flex compiler, and seeing that the ordinary Watcher class uses the StaticPropertyWatcher there is no reason not to use this feature.

However, an important point is that in order to ensure forward-compatibility I recommend that you use the staticEventDispatcher in a more type-strict fashion then the StaticPropertyWatcher implementation.

The following excerpt is taken from the StaticPropertyWatcher, and as you can see - they reference it through the class-index and not directly. By doing this you don't allow the compiler to capture classes attempting to use the static EventDispatcher reference without having a static variable resulting in runtime errors in situations where you don't check for it's existance prior to use.
        parentObj = Class(parent);

if (parentObj["staticEventDispatcher"] != null)
{
for (var eventType:String in events)
{
if (eventType != "__NoChangeEvent__")
{
var eventDispatcher:IEventDispatcher = parentObj["staticEventDispatcher"];

eventDispatcher.addEventListener(eventType, eventHandler, false,
EventPriority.BINDING, true);
}
}
}


In the above case its not possible to do a more type-strict notation seeing that its generic framework code, however in cases where the code is more business-logic-oriented the following notation would make a bit more sense for the compiler
parentObj.staticEventDispatcher.addEventListener( PropertyChangeEvent.PROPERTY_CHANGE, onSomeobjectChange );

This is the preferred way and also a pretty cool way to listen for changes to static variables, despite the fact that its not documented.

Tuesday, July 01, 2008

SWF now supports SEO !

Adobe has provided Flash Player technology to Google and Yahoo! that allows their search spiders to navigate through a live SWF application as if they were virtual users.

Adobe is working with Google and Yahoo! to enable one of the largest fundamental improvements in web search results by making the Flash file format (SWF) a first-class citizen in searchable web content. This will increase the accuracy of web search results by enabling top search engines to understand what's inside of RIAs and other rich web content created with Adobe Flash technology and add that relevance back to the HTML page.

Check it out...
http://www.adobe.com/devnet/flashplayer/articles/swf_searchability.html

Saturday, June 28, 2008

"Is it Flex ?" Online Service (by James Ward)

James Ward created an online service some time ago to test if a SWF is created with the Flex compiler.
It can come on quite handy :-)

Check it out...
http://www.jamesward.com/is_it_flex/

Friday, June 27, 2008

DFUG meeting in Aarhus - Indian Summer Knowledge

On the 23rd of July DFUG has a summer meeting...

Be there or be a { someComponent.graphics.drawRect( 0, 0, 50, 50 ) }...
http://flashforum.dk/events/dfug-mode-i-arhus-indian-summer-knowledge

Wednesday, June 25, 2008

Remembering the pre-AJAX days ?

Back in the early days of AJAX development, before the name was even cornered around 2004... there were many ways to obtain the AJAX-like effects of todays omnipresent XMLHTTP implementations.

One I found particularly nice was the "Webservice.htc" HTML-component which mimicked todays Webservice-proxies.

One of the guys on my team asked me a question leading me to look it up, and to me great amusement it was still available for download right there on Microsoft's website.

Check it out in case you never had the chance to work with it, and if you have worked with it... pay it a visit and remember the "fun" times we had doing AJAX-like effects before it even had a name.

http://msdn.microsoft.com/en-us/library/ms531034(VS.85).aspx

Monday, June 23, 2008

3D Charts Using PaperVision3D (by Andrew Trice)

Andrew Trice has created a simple yet very expressive example of how to use Papervision 3D to display data i multiple dimensions...



Check it out...
http://www.insideria.com/2008/06/3d-charts-using-papervision3d.html

Saturday, June 21, 2008

Workaholics United : The Two Minute Rule

According to the Two Minute Rule, if an action takes less than two minutes, you should do it right then, even if it’s a low-priority item. Otherwise it would take more time to write it on a list and review it later. The converse of the rule is that if an action takes longer than two minutes, you should write it down to avoid getting lured into an activity whose priority hasn’t been evaluated against other tasks on your list.

That’s good advice if understood in context. When you’re batch processing an in-basket, the best way to avoid getting derailed is by adhering to the guideline that each item should take no longer than two minutes. So if you have 40 items in your intray, it should theoretically take a maximum of 80 minutes to process it to zero. In practice, it should take far less, since many items will be filed or discarded more or less instantly.

But there are times when the two-minute interval should be lenthened, shortened or dispensed with altogether. When I’m doing a weekly review, even doing two-minute actions can pull my attention away from a more appropriate project-level focus. So I write them down with checkmarks denoting them as action items to do immediately after the review.

If the action takes longer than two minutes, and you’re not in processing mode, then it might be more efficient to handle the item in the moment, especially you’re reasonably sure that it will only take a few minutes. If you’re not sure that something else might take precedence, don’t hesitate to review your calendar and action lists.

But the main point is that if there’s something that you need to get done, challenge yourself to see if there’s anything you can do this very moment to carry it forward. What can you do right now?

Synergy working with Microsoft Windows Vista

There has been a lot of discussion about getting the 2 year old release of Synergy, which at the moment is the latest release, to work on Vista OS. The very old release could be indicating that there would likely be problems getting the darn thing to work with Windows "Trouplemaker" Vista.
However, due to the low-tech techniques used by Synergy (TCP over IP) there are no problems if you run the Synergy process with local administrator privileges.

This is good news, because at current Synergy is still the only one to support all platforms (Some setup issues with Leopard which are solvable).

However, despite the latest release being from 2006, it appears that the lead-dev behind the application is planning a new release during 2008.

Check it out if you are interested in a Software based KVM switch which works with any machine supporting TCP over IP.

http://synergy2.sourceforge.net/

PureMVC : Lazily Instantiated Components

One small caveat when working with PureMVC - If your View object is defined at design time, but not created at application startup you’ll need to defer the

facade.registerMediator( )

Joshua Ostrom wrote a nice little piece about this.

Check it out...
http://www.joshuaostrom.com/2008/06/06/puremvc-lazily-late-instantiated-components/

Friday, June 20, 2008

Adobe Flex : Flex 3 Compiler Design Document

Now there is a design document available at the Adobe site... nice move :)

http://opensource.adobe.com/wiki/display/flexsdk/Flex+3+Compiler+Design

Adobe Flex : Custom ToolTip Implementation Sample

Every sample out there illustrating ho to use custom ToolTips involve calling a method upon registering a ToolTip event... however, that requires you to add toolTip code to every item you want to have showing a custom tooltip.

The preferred way to do it would be to set the ToolTipManager.toolTipClass property to point to your custom tooltip class.
This way an instance of your own class is created in place of the default instance of the ToolTip class.

Doing this requires you to Implement IToolTip and in order to get most of the logic done for you, its preferred that you inherit from UIComponent or one of its inheritants.

In my previous post I have pointed out that there is a bug in the Adobe Flex ToolTipManager implementation, so doing it my way requires you to override commitProperties and set the text property yourself... however, its a small price to pay for getting the power of the ToolTipManager at your disposal instead of having to implement it all by yourself.

I here illustrate a small mock implementation of an application using custom tooltips

First we create a couple of custom toolTip classes, I call the CustomToolTip1 and CustomToolTip2

package
{
import mx.containers.Panel;
import mx.controls.Label;
import mx.core.IToolTip;
import mx.managers.ToolTipManager;

public class CustomToolTip1 extends Panel implements IToolTip
{
private var _label:Label;

public function CustomToolTip1()
{
super();
}

override protected function createChildren():void
{
super.createChildren();

_label = new Label();
addChild( _label );
}

override protected function commitProperties():void
{
super.commitProperties();
text = ToolTipManager.currentTarget[ "toolTip" ];
}

public function get text() : String
{
return _label.text;
}
public function set text( value:String ) : void
{
_label.text = value;
}
}
}


package
{
import mx.containers.Canvas;
import mx.controls.Button;
import mx.core.IToolTip;
import mx.managers.ToolTipManager;

public class CustomToolTip2 extends Canvas implements IToolTip
{
private var _button:Button;

public function CustomToolTip2()
{
super();
}

override protected function createChildren():void
{
super.createChildren();

_button = new Button();
addChild( _button );
}

override protected function commitProperties():void
{
super.commitProperties();
text = ToolTipManager.currentTarget[ "toolTip" ];
}

public function get text() : String
{
return _button.label;
}
public function set text( value:String ) : void
{
_button.label = value;
}
}
}



Then finally we create an application which facilitates setting the toolTipClass of the ToolTipManager
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
xmlns:mx="http://www.adobe.com/2006/mxml"
layout="horizontal">

<mx:Button id="button" label="Hello World" toolTip="{button.label}" />
<mx:ComboBox id="stateChanger" dataProvider="{states}" labelField="name" change="stateChanger_Change(event)" />

<mx:Script>
<![CDATA[
import mx.controls.ToolTip;
import mx.managers.ToolTipManager;
import mx.events.FlexEvent;

private function stateChanger_Change( event:Event ) : void
{
currentState = stateChanger.selectedItem[ "name" ];
}

]]>
</mx:Script>

<mx:states>
<mx:State name="NORMAL">
<mx:SetProperty target="{ToolTipManager}" name="toolTipClass" value="{ToolTip}" />
</mx:State>
<mx:State name="CUSTOM_1">
<mx:SetProperty target="{ToolTipManager}" name="toolTipClass" value="{CustomToolTip1}" />
</mx:State>
<mx:State name="CUSTOM_2">
<mx:SetProperty target="{ToolTipManager}" name="toolTipClass" value="{CustomToolTip2}" />
</mx:State>
</mx:states>

</mx:Application>

Blog Archive

My Network