Tuesday, January 05, 2010

Township Jitney Schedule: Software Development History

This past weekend I wrote an app for my local town: it displays a route, and schedule information, for the town's jitney. (In local terms, a jitney is a township-sponsored shuttle service for resident commuters to and from the train station.) You can see it at http://myjitney.appspot.com.

I'd like to discuss the short development history of this web application.

The Original Plan


The original plan was to write a public, custom Google Map to be shared with the other residents using My Maps, a tool that allows users to create customized maps.

The problem with My Maps is that each marker had be placed individually, and that's tedious: at least to me. What I needed was a programmatic way to feed a set of addresses, determine each address' coordinates (you know, latitude, longitude) and place markers in a custom map.

For that I wanted the Google Maps API in Javascript, and if I had to use the Javascript API for determining coordinates, I might as well use it to build the map from scratch.

The Prototype

The prototype was written in pure Javascript, using the Google Maps API. It was really basic; routes were stored in JSON (natch), and the whole app lived inside a Google Maps widget.

To get started with the API I found an excellent Google Maps API Tutorial written by Mike Williams. The relevant entries were the entries on Markers and info windows,  Polylines from XML and Geocoding Multiple Addresses.

In fact, I hacked a version of the geocoding example by adding all the jitney stop addresses, and from that I got the coordinates of most of the map markers. For those addresses that the API couldn't parse, I used a tedious trial and error process.

The prototype took five hours to write: one hour to parse and codify the data, one hour for figuring out how to get reasonable coordinates for each address, and three hours to get my head around Javascript. For me, writing Javascript is like this: trial, error, trial, error, google, trial, trial, error, trial, error, google, but by the end, I got a map that showed all the jitney stops and their paths.

Two issues with writing the app in Javascript were my basic lack of comfort with Javascript, and also, the app didn't render on my Android phone. I dreaded debugging a web app on an Android phone.

The Rewrite


So I needed to rewrite the app, and by need, I mean want. 24 hours earlier I could have just manually built a damn custom map with My Maps, but now I was committed to code and more code. For the rewrite, I chose GWT. The Google Web Toolkit is a terrific piece of technology; you can write web applications using Java in Eclipse, my preferred IDE, and with a debugger. Since Google provides a GWT implementation of the Google Maps API, it was reasonable to port the existing prototype to GWT. The Google Plugin for Eclipse, a fabulous tool that combined GWT, AppEngine, and Eclipse, made it dead simple to deploy the app to to appspot.com which meant a permanent home to the app, along with a back-end infrastructure in case there was ever a need for servlets or a back-end data store.

(This is a great time to point out that I think that GWT is magic, and the GWT team are a bunch of magicians.)

It took four hours to write a feature-equivalent version of the application using GWT. Most of that time was spent familiarizing myself with the various APIs and getting reacquainted with GWT.


I didn't want to go through the effort of learning how to work with the AppEngine database, so the rewrite still shipped the route data as java source turned into javascript. One of the great benefits of this turned out to be that the map loaded super-quick. So I moved the CSS to the HTML <style> tag, removing yet another server request.

Thanks to GWT the app ran perfectly fine on Android. But more important, thanks to GWT I could write code in a more familiar style, and easily manipulate the DOM outside the web page's map object.

So I did.

Spit and Polish


I spent two more days adding features and polish: a pretty display of the schedule. A list of the routes so each could be viewed independent of the others. A visual indicator of when a jitney will next stop at a certain route.

One of the features was to replace the straight lines from stop to stop with paths along the street. The township had a map that laid out the supposed bus paths, so the trick was finding the coordinates where the paths turn. That turned out to be surprisingly easy with this small piece of Java:

map.addMapClickHandler(new MapClickHandler()
  @Override
  public void onClick(MapClickEvent event) {
    System.out.println(event.getLatLng());
  }
});


Then it was just a matter of running the web application and clicking each spot along the path, feeding the console output back to the web application as intermediate points.






Before

After

Besides adding features, I spent a ton of time dealing with things like positioning and formatting. I spent 30 minutes building a general purpose route building API. I spent 15 minutes on a general purpose algorithm for calculating the center of a group of points. 30 minutes went into making a widget that looks like, but isn't quite, an anchor tag. I spent endless time playing with different types of GWT panels, setting widths, heights and spans. I played with CSS. I failed at CSS, and then I played with it some more. It seems I have the same development cycle for CSS that I do with Javascript: trial, error, trial, error, google.

Done.

By Sunday night the app was done, and so was I. But it's still not done. Even with such a small one-off project, there so many features that could be added. For instance, while the app runs on Android (and reportedly the iPhone) it's not really built for small phones. The individual links are too small to be useful.

But also, I'd like to use Street View to show each stop. Unfortunately, while a Street View API exists in the Javascript API, there's no equivalent in the GWT API. I probably spent about two hours before I recognized that it would involve another painful, endless cycle of trial, error, trial, error, google. Too bad.

Done?

Damn. While writing this post, someone provided feedback, requesting a feature that made too much sense not to implement. So instead of cleaning up this post I'm reading about geocoding again. I love writing software.

6 comments:

.NET Application Development said...

Nice post, Thanks for sharing. I got good info from this post and wants to read more post on this topic

----------

.NET application Development

David Plass said...

You can call native JS from GWT code so you can implement street view after all.

konberg said...

@.net guy, awesome!

@David, the problem is that the GWT API uses a version of the Javascript API that doesn't have street view code. Running two copies of the API by downloading two versions just wasn't looking like it would work.

Jacek Pospychala said...

your application looks really cool, thanks for sharing.

btw. we don't live in stone age any more. there are javascript debuggers out there :-)

konberg said...

@Jacek, yeah, and Firebug is pretty good. But I can't help but love my Java and Eclipse.

Web Developers Chennai said...
This comment has been removed by a blog administrator.