Geek Spike

When learning a new technology, I like to start with a “canonical example spike”. A spike is a XP term for trying something new in a short burst to get a better idea how long a full implementation is going to take. When trying a new framework (or Ajax library), I look first for an example application that demonstrates common uses cases from your target application.

At work, we have a PhoneBook application that we used when we were first learning .NET. At the time, it was an actual intranet application. Even after we started building other applications, we would often go back and try something new with the PhoneBook example first. Over time, it became our best-practices reference application.

So, when it came time to lean YUI, the first thing we did is reach for the PhoneBook use case and have at it. It took some time to do, but it’s much easier to learn a new technology in the comfort of a well-known application.

And, of course, starting with a throw-away example gives you a chance to make all the mistakes up front. :) I think that’s what I like best about software development: You only have to get it right the last time!

But can Ajax make popcorn?

If you’re a Struts developer dabbling with Ajax, the new Ajax tags in Struts 2 can make it easy to get started. Both Struts 1 and Struts 2 are excellent Ajax environments for Java web developers. A S1 action can return whatever text stream your Ajax widgets might need. For S2, pop in the JSON plugin, and, bingo, instant Ajax computability! Better yet, just fire up DWR.

If the Ajax bug bites, and you go beyond dabbling, it’s likely that you will want to add an Ajax library to the mix. After peeking at the source for an Ajax library, it may begin to dawn that you don’t know so much about JavaScript after all. YUI and Dojo are not the tinkertoy scripts we cut and paste into our markup for the odd special effect.

An excellent way for a Java developer to lean more about Ajax is the YUI Theater site. It’s a virtual convention, featuring sessions with Douglas Crockford (JSON), Joe Hewitt (Firebug), and Chris Wilson (IE). You can’t pop out a question, but you can pause the action, and view the material at your own pace.

For starters, I heartily recommend the “Browser Wars Episode II” clip. It’s an absolute must-see for anyone doing web development, whether it be bleeding edge or trailing edge. You won’t learn many stupid browser tricks, but you will get a look around the bend at what’s happening with browser development

For frontline JavaScript development, Doug crockford’s video trilogy is another must-see. For more about that, see my prior blog.

Featured this week is a brief but rich session with Gopal Venkatesan: “Writing Efficient JavaScript”. Some of the material overlaps with the Crockford Clips, but there’s are new goodies too. At 22 minutes, it’s well worth the time.

Sadly, the slides aren’t posted with the video clip, though I’m told that they will be posted eventually. [Evidentially, the laptop with the presentation and Venkaesanis are now in different zip codes :)] In the meantime, here’s a set of summary bullets:

 

  • Do not use eval() when there are alternatives
     

 

  • Do not pass a function as a string to setTimeout. (It uses eval.) Pass an inline function instead.
     

 

  • Do not use the “with” statement. Set a local var instead.
     

 

  • Do not use try/catch wihin loops. Put the loop inside try/catch.
     

 

  • Avoid global variables. Period.
     

 

  • When concatenating several strings (or DOM), use Array.join() or String.concat()
     

 

  • Hide element before modifying several properties
     

 

  • Avoid setting multiple element attributes by replacing the CSSText property
     

 

  • Setting HTML to the innerHTML attribute is faster than going through DOM (but less pure)
     

 

  • Detach DOM properties before appending several elements
     

 

  • Attach common event handlers to the elements’ container and let the events bubble up
     

 

  • Use consistent naming conventions to help identify elements that share event handlers
     

Next in line for me is Joe Hewitt’s Firebug video. I truly enjoyed Firebug 1, but the latest version is so featureful, I feel a bit lost. Hopefully, Joe can machete me a path through the new interface.

Or, maybe I should just use Aptiva, which embeds Firebug into a very slick-looking Ajax IDE.

You know, sometimes, I do feel like the machine is us/ing us!

S2 Tip - Always set devMode to false in production

In the Struts 2.0.6 release, we made the mistake of setting devMode to true in some of the example applications. As a result, some developers copied the setting, and then wondered why their Struts 2 application seemed sluggish!

As of Struts 2.0.7 (hopefully coming soon), we’ve added a Performance Tuning page to the documentation. Here’s the highlights:

 

  • Do not use interceptors you do not need
     

 

  • Use the correct HTTP headers (Cache-Control & Expires)
     

 

  • Copy the static content from the Struts 2 JAR when using the Ajax theme (Dojo) or the Calendar tag
     

 

  • Create a freemarker.properties file in your WEB-INF/classesdirectory
     

 

  • Copy the /template directory from the Struts 2 JAR into your web application’s root
     

 

  • When overriding a theme, copy all necessary templates to the theme directory
  • Do not create sessions unless you need them
     

 

  • When using FreemarkerResult, try to use the Freemarker equivalents rather than the JSP tags
     

For the nitty-gritty, visit the latest copy of the page.

Kudos to Philip Luppens for starting the tuning page. If you have any tuning tips of your own, feel free to post comments directly to the page. (Gotta love Confluence!)

Incremental Refactoring

Recently, someone asked on the Ext list:

> Is Diagraming your classes/code segments
> the best way to keep yourself
> organized during the programming stage?
> Or is there some more efficient
> and easier way to do it?

I thought the advice of the Ext lead developer, Jack Slocum, beared repeating.
The approach I have found to be most effective is “incremental refactoring”. This means starting out with a basic idea of how your object model should look. It will probably be raw and imperfect, but you know that and knowing that is the key to what makes it work.

Start out small and make pieces of it work. While it’s small (and not a big object model with all kinds of pieces to develop before you have anything working) you should be able to find various imperfections with your initial design (like browser problems!) and you can refactor while it’s still cheap. As soon as you have something working, it’s time to refactor to look for ways to make things more generic, cut code duplication, improve interfaces and efficiency. Then start on the next piece in the same way.

The most important thing is you have to think OO, think efficiency and know your patterns. Once this is in place, the rest is kind of automatic.
IMHO, one of the best books on “incremental refactoring” (or successive refinement) is “Test Driven Development: By Example by Kent Beck. While it doesn’t mean to be about successive refinement per se, that’s exactly what Beck is doing in the book. At 240 pages, it also has the virtue of being relatively brief.

As he codes, Beck keeps a running TODO list of the next baby-steps needed to finish a larger task. Beck says he keeps his on paper, but I use a text file. I even post the running list to the issue tracker, like a mini-progress report.

Successive refinement works well with an issue tracker that supports roadmaps (like JIRA). We can then organize the major features into iterations or milestones and ship one iteration at a time. Ideally, each milestone should be a working, if incomplete, version of the target application.

At work, we follow the usual Extreme Programming model, except that we prefer formal use cases to XP stories. (See Cockburn’s “Writing Effective Use Cases“. It weighs in at 270 pages, but the first 20 pages tell you everything you actually need to know.)

Essentially, XP interations are successive refinements, which is an approach Nicholas Wirth was advocating decades ago, when he designed Pascal. The key is to organize your work so that there is some kind of working application at every step of the way – even if you have to fake some of the resources. :)

In working with Ajax and JSON, one pleasant surprise is how easy it can be to fake resources. For example, the YUI connection manager can accept a JSON object, but it doesn’t care if the object came from a XHR request or static data. We can switch between a set of test data and the live stream with one line of code.

LISTER.init = function (data)  {
PhoneBook.rpc.entry_list(LISTER.load).call(ANVIL.channel); // live database
// LISTER.load(LISTER.localData); // static data
};
LISTER.localData = {
"result" : [['c5b6bbb1-66d6-49cb-9db6-743af6627828', 'Clinton', 'William',
'555-743-7828', 'bubba', '08/19/1992', 37.5, '0'],
['7c424227-8e19-4fb5-b089-423cfca723e1', 'Roosevelt', 'Theodore',
'555-743-8942', 'bull', '09/14/2002', 37.5, '0'],
['9320ea40-0c01-43e8-9cec-8fb9b3928c2c', 'Kennedy', 'John F.',
'555-743-3928', 'fitz', '05/29/1987', 37.5, '0'],
['3b27c933-c1dc-4d85-9744-c7d9debae196', 'Pierce', 'Franklin',
'555-743-7919', 'benji', '11/18/1984', 35, '0'],
['554ff9e7-a6f5-478a-b76b-a666f5c54e40', 'Jefferson', 'Thomas',
'555-743-5440', 'monty', '07/04/1976', 37.5, '0']]
};

Now that’s how you spell MVC!

GoogleCode: What's the diff?

Good news! GoogleCode Hosting already offered alert emails on a Subversion commit, but, strangely, the diffs were omitted from the alerts. Now, we get both logs and diffs on every commit!

This is especially great news for me. I was actually posting daily commit summaries by running svn diff to a text file and posting the output to our mailing list (Google Group). But, that was a poor replacement for per-commit logs and diffs, all in one handy-dandy email feed.

Author: ted.husted
Date: Fri Mar  9 09:46:00 2007
New Revision: 182

Modified:
trunk/cs/Apps/PhoneBook/Web/PhoneBook-Editor.js
trunk/cs/Apps/PhoneBook/Web/PhoneBook-Lister.js
trunk/cs/Apps/PhoneBook/Web/PhoneBook-Menu.js
trunk/cs/Apps/PhoneBook/Web/PhoneBook-Profile.js

Log:
Issue 11 - Add events for all menu buttons. Setup “init guards” so that menu
buttons are not created more than once. Include logic to disable exting buttons
if user’s status changes from editor.

Modified: trunk/cs/Apps/PhoneBook/Web/PhoneBook-Editor.js

— trunk/cs/Apps/PhoneBook/Web/PhoneBook-Editor.js (original)
+++ trunk/cs/Apps/PhoneBook/Web/PhoneBook-Editor.js Fri Mar 9 09:46:00 2007
@@ -98,8 +98,13 @@

EDITOR.onDelete_load = function (data) {
// ISSUE: This will fail if list is out of sync and data is null

  • ANVIL.setMessage(“Deleted: “ + data.result.user_name);
  • PhoneBook.rpc.entry_list(LISTER.onDeleteRefresh_load).call(ANVIL.channel);
  • if (data.result.user_name) {
  • ANVIL.setMessage(“Deleted: “ + data.result.user_name);
  • PhoneBook.rpc.entry_list(LISTER.onDeleteRefresh_load).call(ANVIL.channel);
  • }
  • else {
  • ANVIL.setMessage(“Workflow error. Select row and try again.”)
  • };
    };

Why all the noise over diffs? Simple: Peer review and non-redundant team communication. My team is accustom to reviewing each others commits as an extended form of pair-programming. Following the example of many successful open source projects, we also use the commit logs to describe what we are doing, step by step. The alerts become part of an implicit unit development folder, saving us an extra post or conversation later. And, unlike a random post to the mailing list, the commit log is directly linked to that code revision.

To help tie it all together, many projects apply “issue-driven development” to the commit logs. Under IDD, a team adopts a policy that every commit must reference one or more tickets from the issue tracker. If a commit doesn’t relate to an open issue, then we have to create one first.

Like test-driven design, IDD encourages developers to do the right thing as soon as possible. If we are going to write the test anyway, we might as well write it first. If we are going to create the issue anyway, we might as well create it first. And, if the issue tracker is tied to the mailing list, when we create the issue, we put the team on notice of our short-term plan, just in case anyone has a suggestion.

Issue driven development works best when the issue tracker can scan the repository logs and link commits with issues. Apache Struts uses IDD with JIRA and Subversion. For odd jobs, we create an “omnibus” issue for each milestone, which we use (judiciously) as a catch-all.

Vincent Massol (JUnit in Action) has also blogged about IDD.

GoogleCode doesn’t link issues with Subversion commits yet. In the meantime, we’ve been faking it by prefixing our commits with the issue number. There’s not a live link to the revision yet, but at least we will be in the habit should that feature come online.

Perhaps Devo said it best: Duty now for the future! :)