Wednesday, December 24, 2008

Mac Usability Overrated

A few years ago, I switched back to a Mac after a 15 year hiatus. Overall, it was a positive experience. And overall, I prefer the Mac OS X Leopard to Windows XP. I have no experience with Vista, so I can't comment on that. But given my general tendency of complaining and my annoyance of religiously fervent Mac fans, I feel I should share a few things that, in my opinion, represent poor usability design in the Mac.

Now there is no way to gauge how skewed my opinions are by the fifteen years of Windows experience. Sometimes people judge something as crappy just because it is new to them. As a teacher, I see this in my students. Most people taking my class are moving from an old technology to a new technology. And many of my students complain that the "new way" of doing things sucks and that their "old way" (in Cobalt, Fortran, PowerBuilder, etc) was much better. Sometimes, they are right. But sometimes, they just haven't gotten used to the "new way". Its probably impossible to separate "poor design" from "I'm just not used to it", but none-the-less, I'll try.

#1 Context Insensitive Menus
Most Mac applications have a global menu bar. And this is how you access most of the app's functionality. What's more, the menu is anchored to the top of the screen. Not the top of the document. Not the top of the panel - the top of the computer screen. This, in my opinion, isn't just different from what I am used to. It's a poor design. It violates the UI design Principal of Context. Most user actions apply to a specific context (i.e. object): a paragraph, the selected cells, the current document, etc. This is the fundamental concept of OO (an object is really just a context). Imagine you have a dual monitor setup. You have a graphics application running on the right screen. And you want to modify a rectangle. Where do look for a list of possible actions? The rectangle? No. The document? No. You look to a menu bar at the top of your left monitor. The only argument, in favor of this design is that it saves a bit of screen real estate. And old Mac people are used to it. But, overall, in my opinion it is just poor usability design.

#2 No Maximize Button
Mac windows do not have a maximize button. They have something kind-of (but not really) comparable: the Zoom Button. It is one of the 3 tiny circle buttons in the upper left corn of every Mac window. The zoom button attempts a "size to fit". Most UI programming toolkits have a function like this built-in. In Java Swing, it's called the pack() function. Basically, the window attempts to find the optimal size (not too big, not too small) based on the window's contents. The problem with this approach is that the algorithm is wrong most of the time. And it takes control away from the user. Often, when browsing with Safari, I just want the whole screen. Obviously, it's not a deal breaker. I can just drag the window bigger if needed. It's just a pain in the butt. By the way, many (non apple) vendors simply have their zoom buttons do a maximize. But Safari, Finder and iTunes do not.

#3 The Window Buttons
Most windows on my Mac have 3 buttons in the upper left corner (one of them is the Zoom button mentioned above). These buttons are just circles. There is no indication of what they do. If you hover your mouse over the button, then an image appears. But you get no tool tip telling you (in words) what the button does. This, in my opinion, is not just different from what I am used to. It's just poor usability design. Why not just have the image visible all the time? Why not have a tool tip? Perhaps some designer thought it looked prettier this way. I don't know.

I think Apple is great at creating interfaces that look great. But as far, as usability goes, I think they are probably good. Above average. But not great. At least not based on my Mac experience.

Tuesday, December 23, 2008

Composite Widgets and Blur Events

It is a common need in web applications to create a single logical widget (aka UI component) that internally is composed of multiple native html elements. A few examples:
  • A DateWidget composed of 3 html SELECT elements (month, day and year)
  • A custom combobox composed of a textbox, a button (placed to the right of the textbox) and a popup (or more accurately a drop-down) div that contains a pick list and appears when the button is clicked or a letter is typed.
  • A DatePicker (same as custom combobox mentioned above, except the drop down is a calendar instead of a pick list)
Below is a problem with this kind of widget that i have not been able to easily solve:
Problem Definition
It is often desirable to have a single blur event that applies to the composite as a whole. Using the blur event for the internal html elements may be the wrong granularity for validation or change notifications. For example, suppose that for the above mentioned combobox, we chose to use the textbox's blur event (because the combobox as a whole has no blur event) for validation. Then imagine this scenario:
  1. The user types 1 letter into the textbox
  2. The popup appears
  3. User clicks on the popup - perhaps to scroll the pick list or (in the case of the DatePicker) to scroll the month
  4. Boom! The TextBox's change and blur events fire.
  5. Our app, in response to the blur event, attempts to validate
  6. Our validation function reads the value in the textbox and, detecting that it is only 1 character long, displays an error message.
This is clearly not the desired behavior.

Desired Behavior 

Test #1:
Does the composite widget have its own blur event as distinct from those of its child widgets? And (more to the point) is there an obvious way to add a blur listener to the composite (again, as distinct from its child elements)?

Test #2: 
Assuming we passed test #1, does the composite's blur event fire in a way that is logical for the composite as a whole:

Test 2a (comboBox with down-arrow trigger button):
  1. Click into the textbox portion of the combobox
  2. Type a few letters
  3. Click the down-arrow-button (to reveal the drop down list). This should not fire the composite's blur event.
Test 2b (date picker with no trigger button):
  1. The user types 1 letter into the textbox
  2. This causes the popup calendar to appear
  3. The popup contains a "Scroll Next Month" button. Click on that. This should not fire the composite's blur event.
Workarounds
This isn't a deal breaker issue for most applications. We can just hold off on validation until later, when the entire form is submitted. But none-the-less, many customers prefer field-level errors to appear sooner rather than later. This is, after all, one of reasons we have blur and change events.

Other Widget Libraries
I did a quick survey of composite widgets from various web widget libraries, to see if they handled blur events as desired (see "desired behavior" above). Here is what I found:

Library Widget Composite blur/change events Demo Link
DOJO dijit.form.FilteringSelect Yes TODO
jQuery ui.datepicker No TODO
Spry SuggestText ?? No TODO
GWT 1.5 SuggestBox No TODO
GWT 1.6 SuggestBox Maybe TODO
GWT Incubator DateBox No TODO

Possible Solutions
  • Timer solutions. TODO: elaborate
  • Global focus tracker. TODO: elaborate
  • Try to figure out what DOJO did (their solution was not easy for me to follow)
Event Bubbling
Note that what we are describing here is not the same as bubbling. Event bubbling refers to the fact that if a child element does not handle an event (or more specifically cancel the event) then that event bubbles up to the parent element. But a div containing 3 select elements (as in the date selector described above) would still fire 3 change events in either case:

Case #1: three select#changeListeners
Case #2: one div#changeListener.

This is not to say, that bubbling might not be used in the solution. But bubbling, in and of itself, is not the solution.

Objective
Come up with a solution that:
  1. Provides the desired behavior described above
  2. Is general enough to componentize (for example, in GWT, a generic parent class called BlurableComposite). Note: GWT has a class called FocusPanel, but I can't figure what it's purpose is and if it is designed to address the problem I am describing here.
  3. If the solution is not general enough to express as a reusable class, then a solution general enough to express in the form of a design pattern/solution
  4. Perhaps tie in the solution with GWT's new HasValue/HasValueChangeHandler (in 1.6 trunk)


Friday, December 19, 2008

JavaScript Virtual Properties

Some programming languages have a particular feature that I find very useful. This feature allows a setter method to disguise itself as a variable assignment. For example, instead of:

person1.setAge(42);

You would do this:

person.age = 42;

Under the covers, it's actually not setting a variable (as it appears) but rather it's calling a setter method.

The same language feature allows a getter method to disguise itself as a variable read. For example, instead of:

print( person1.getAge() );

You would do this:

print( person1.age );

Again, under the covers, we are actually not setting a variable (as it appears) but rather we are calling a getter method.

Virtual Properties


The above described language feature does not have an industry standard name (that I know of). The old VB used to call it "property procedure". I've heard it called "getters and setters", but that is a confusing term because languages like Java have "getters and setters" but they do NOT have the above mentioned language feature. C# calls them properties. But this is also a confusing term. JavaScript and Java both use the term property to mean something different. Also, many people use the term property interchangeably with "field" or "instance variable". Ruby uses the term "attr_accessor".

But JavaScript (as of ECMAScript 4th edition) will soon be supporting this feature. And they use the term "Virtual Property" which makes the most sense to me. So that is what I will use. To be more specific, ECMAScript 4 defines three terms:

Value Property: A value property is the new name for what used to be called "property" (without the "value" prefix). Value properties are just plain old instance variables (aka fields). The reason for the new term is to distinguish a value property from a "virtual property".

Virtual Property: A virtual property is really a getter and/or setter method that (to the caller) appears to be an instance variable.

Property: The term "property" is now inclusive of both value properties and virtual properties. Thus, clients of the object just see "properties" there is no way they can tell whether they are accessing a virtual property (i.e. calling a setter or getter method) or accessing value property (i.e. a variable). The fact that the caller is hidden from these details is really the whole point of virtual properties.

Why Use Virtual Properties


You may be asking yourself, "why would I want to use this feature?" Well let me explain by reviewing setter/getter methods in general.

Most of the time, setter methods (the old kind of setters and the new "virtual property" style setters which I will show shortly) don't do much that is interesting. They usually, just turn around and set a variable:

function setAge(newValue){
this._age = newValue;
}

But sometimes, the setter adds a bit of value beyond merely setting an instance variable. For example, validation:

function setAge(newValue){
if(newValue) > 150) throw new Error("Too Old");
this._age = newValue;
}

Or perhaps the setter may trigger some other action (or side effect):

function setAge(newValue){
this._age = newValue;
recalculateDateOfBirth();
}

And sometimes the setter has no corresponding underlying instance variable at all. For example, storing age and dateOfBirth is redundant. So you may have:

function setAge(newValue){
this.dateOfBirth = computeDateOfBirthFromAge(newValue);
}

But the vast majority of the time, setters just set a variable:

function setAge(newValue){
this._age = newValue;
}

This results in a whole ton of boiler plate code for setter methods. The same is true of getter methods, some times they do something interesting like this:

function getArea(){
return this._length * this._width;
}

But most of time they just do the same old boring thing, return the value of a variable:

function getLength(){
return this._length;
}

Again, this results in a ton of boring, noisy, boiler plate code. In fact, most modern IDE's have a shortcut called "generate getters and setters".

So now, with virtual properties, any time you have a setter or getter that does nothing but set or get the value of an instance variable, just get rid of it. Instead allow direct access to the instance variable.

The payoff: all those boilerplate do-nothing getters and setters just go away!

How to Create a JavaScript Virtual Property


So now in JavaScript you have two new keywords: get and set. These are placed write after the word function like this:

function get age() {
return this._age
}

function set length(newValue) {
if(newValue > 150) throw new Error("Too Old");
this._age = newValue
}


Browser Support


As it turns out Safari, FireFox and Opera all support virtual properties. And now (from what I have read), virtual properties will be supported in IE8.

More Info


Mozilla: Defining Getters and Setters
Cedric on gettersand setters
ECMAScript 4 Look for section titled: Property States

Wednesday, December 17, 2008

Safari DevelopMenu

Just discovered something cool in Safari. Under Safari -> Preferences -> Advanced, there is a checkbox: "Show Develop Menu in Menu Bar". This adds a new menu item called "Develop" with all sorts of web developer tools.

One Language for Client and Server

Some web developers categorize themselves as a "front-end" developer or a "back-end" developer. For large teams, this specialization is a nice luxury. But more often than not (I think) most developers end up playing both roles. I'm glad that I play both roles, because often it takes an intimate understanding of both, to create the best overall architecture. Often the most important part of an architecture is deciding what should be part of the the front-end and what should be part of the back-end and the communication protocol between the two. Thus, I proudly categorize myself as an end-to-end developer (or a front-back developer?).

Side-note #1: The terms front-end and back-end is not necessarily the same thing as client-side and server-side. But for this post, this is how I am using them.

So here is the problem with being an end-to-end developer. The predominate programming languages for front-ends are JavaScript and ActionScript. The predominant language for back-ends are: Java, C#, VB.NET, PHP, Ruby and Python. This means developers must learn at least two languages to do their job (lets ignore CSS, HTML and SQL for the moment). This is good for me personally, because I enjoy learning new languages and (as luck would have it) I already know most of the server-side and client-side languages. But most of my clients (corporate IT developers) must also spend time learning their own problem domain (insurance, medical, banking, or whatever). These people are not as geeky as me and don't enjoy learning new programming languages for sport. Many come from backgrounds where they used to create entire applications using only one language like VB, PowerBuilder or Oracle Forms. Thus, I ask the question, how much more productive can we be if we can use the same language end-to-end?

My guess: very much more productive.

Side-note #2: Sometimes additional, more special-purpose languages are a good thing. There is even an acronym to represent the concept: DSL - (Domain Specific Language). Examples of DSLs include things like HTML, CSS, SQL, XSLT and regular expressions. But when I speak of a single programming language for front-end and back-end, I am talking about general purpose languages. The predominant front-end and back-end languages mentioned above are general purpose programming languages.

So, if you would like a single end-to-end language for web development. Here are your options:

  1. Compile your favorite server-side language-to-JavaScript

  2. Find an Application Server that supports JavaScript

  3. Use a server-side framework that generates all the JavaScript
Below are a few examples from each of these categories.

[Update: 7/10/2012] : This post pre-dates nodejs and dart, both of which enable same-language development on client and server. 

GWT: Google Web Toolkit

GWT compiles Java into JavaScript. Thus, you can use Java for the front-end and Java for the back-end. Think of JavaScript as the new byte-code. In both cases the Java part is really an illusion; at runtime the Java is gone and all that's left is JVM byte-code (server-side) or JavaScript (client-side). But once you are coding in Java on both sides, network (i.e. AJAX) programming becomes much easier; you can now send Java objects back and forth RPC-style.

Pyjamas


Pyjamas is similar to GWT except it compiles Python to JavaScript.

Other X-to-JavaScript Compilers


Java2Script

Ruby to JavaScript

Harmony Framework - PHP to JavaScript


ASP.NET and JScript


One can create ASP.NET pages using JavaScript. Thus, in principal, one can use JavaScript for both front-end and back-end development. The only problem is that JScript is a more modern version of JavaScript (more like ActionScript 3) thus client and server languages are not technically the same.

JSF AJAX


JSF (JavaServer Faces) when coupled with an AJAX JSF tag library like ICEFaces, allows one to create an entire AJAX application and not see a lick of JavaScript. Just as traditional server-side tags are expanded into HTML before being served to the browser, AJAX aware JSF tags are expanded to HTML + JavaScript. Thus you get most of the benefits of a rich JavaScript client, but you are only coding in one language: Java. The only problem with this is that, in reality, you are coding in all sorts of languages: JSP, JSF tags, EL (the Java Expression Language). Plus large chunks of the application ends up in JSF specific XML files (faces-config). This model is the least flexible of the solutions mentioned in this article.

Sun's Phobos


Phobos, like Jaxer, is a server-side JavaScript web application server. However, Phobos is based on the rhino JavaScript engine. Rhino itself is a pure Java application. This means it will be slower than C based JavaScript engines (like SpiderMonkey, TraceMonkey used in Jaxer). But it also means its very easy to make use of existing java code and libraries - a potentially huge benefit. Plus, Phobos takes the form of a standard Java WAR file. Meaning it can run on top of any Web Container that supports the Java Servlet 2.4 spec such as Tomcat, Jetty, IBM WebSphere, etc.

Jaxer


Jaxer is a server-side JavaScript application server. Technically speaking Jaxer takes the form of a web server plug-in. It currently runs on Apache 2.0 and Jetty (with plans to support IIS). It uses the SpiderMonkey JavaScript engine, the same one used by Firefox. They claim that "Jaxer performance is comparable to PHP and Rails". However, they will soon be switching to Firefox's newest JavaScript engine (TraceMonkey) which should prove much faster. One interesting point about Jaxer is that it's server-side programming model is essentially the same as the client-side programming model, namely DOM. Thus client and server not only use the same language, they also use the same API.

10Gen


10Gen (like Jaxer and Phobos) is a server-side, application server that supports JavaScript, Ruby and Python. There whole schtick is that the platform is "cloud-aware" from the get-go. In that since it's a bit like Google's app engine. You can use their platform as a "service" or you can run their software in your own cloud (i.e. on your own servers).

My Own Experience

I have dabbled with all of these technologies. But the ones I have the most experience with are GWT and JSF/ICEFaces. Presently, my favorite tool for web development is GWT. It doesn't have the most feature-rich widget library in the world. But that is because they focus their efforts on making the "core" as good as it can be, then leave some of the widgets to third party vendors (of which there are dozens). If you work with GWT you will become a better web developer. There is some serious "smarts" contained in GWT. And it will rub off on you. Things that took days in JSF take minutes in GWT (creating your own component, for example). GWT is a thin layer on top of DHTML. It doesn't try to hide anything and generally doesn't create a whole new abstraction layer. But I could go on all day about GWT, but that would be a subject for a different post. Here are a few links about the general philosophies behind GWT:

GWT Mission Statement
GWT Design Axioms

Tuesday, December 16, 2008

User Experience (UX)

I am a developer. But I am also an avid user of web sites and web applications. And as a user, I happen to really like the applications put out by Google. In particular, I like how they keep things simple, clean and uncluttered. And they don't get side tracked adding features and frills that impress everyone except the actual user of the application.

Then I found this on Google's web site, Ten principles that contribute to a Googley user experience, that summarizes their design philosophies.

I also like the apps by 37signals, specifically: BaseCamp and Highrise. As luck would have it, 37signals also has a web site explaining their UX and development philosophies called Getting Real.

Thursday, December 04, 2008

GWT apps are Small!

I just wrote a small DOJO page that has nothing on it but a combobox with 10 hard coded entires. I ran it thru firebug and the total download size was: 268 kb. Then I ran the gwt app i am working on thru firebug ( a full app with multiple screens, dozens of widgets). The entire download size of the gwt app was 98 kb. To summarize:

268kb: DOJO app with one combobox
98kb: a complete gwt application