Sunday, May 31, 2009

Ignite I/O - Growing Up Geek: My Dad, The Computer Scientist

"Ignite" is a style of presentation: 5 minutes, 20 slides, 15 seconds each, auto-advance. It's probably the most challenging style of presentation out there (lightning talks are a breeze in comparison), which is why it intrigues me. I did my first Ignite in Sydney a few months ago, with a talk entitled "HTML 5 versus Flex for RIAs". It went well, as I was able to remember all of my lines, and I managed to squeeze quite a bit of content into those 5 minutes. But I discovered that the best Ignite talks there weren't the informational ones, like mine - they were the narratives ones, the ones that told stories and left the audience feeling moved in some way.

So when I was asked by Brady Forrest to give an Ignite talk at Google I/O, I decided that I would find a story to tell, and hopefully one with a geeky twist. Thinking of how much my JAOO Brisbane audience loved the slide in my App Engine talk about my dad not giving me allowance unless I'd programmed Java that week, I formulated my talk: "Growing up Geek: My Dad, The Computer Scientist". I didn't have an exact outline for the talk when I proposed it, but I figured I had enough entertaining anecdotes about life with geeky parents (my mum ultimately became a computer scientist as well) that I could fill up 20 slides.

Creating the slides took ages, since my search for authentic pictures for the slides meant digging through our old archive of 5000 digitized family photos to find evidence of our myriad PCs, and using the Wayback Machine to capture screenshots of my original websites and Perl programs — and man, nolstalgia is a bitch of a distractor. Soon, a real story began to emerge amongst the slides: the story of me wanting to do many things — including programming, my dad disapproving of these non-programming activities, and me perservering on with my renaissance approach to scholarism and finally gaining his approval. The point I want to make with the talk is this: you should always encourage your kids to explore everything that interests them. Yes, this may mean that they don't become a specialist, or that they don't become the particular profession you've set out in your heart for them — but it means that they're doing what makes them happy, and people always excel the most at what makes them happiest.

The final slides are embedded below, with my pre-scripted lines pasted in the slides (it's impossible not to script them, trust me). I've also entered the slides in a "Tell a Story" contest that Slideshare is running now, since they happen to tell a story; you can vote it up on Slideshare if you like. The video is now up on Youtube. Enjoy!

Sunday, May 17, 2009

Google Spreadsheets + APIs = Interactive Flash Cards

Update: Google is deprecating Google Spreadsheets gadgets, as they announced in this post, so I am no longer updating or supporting them. If you're a developer, you can try Apps Script or the Spreadsheets Data API to see if you can accomplish the same thing. If you're a user, sorry, sometimes Google shuts down little used features.

For about 6 months in the Mountain View Google office, I went to a once-weekly hour-long German language class. Since I didn't have much time to really do homework outside of class, I looked for excuses to use Google APIs to give me different ways of learning German. My first attempt was a gadget that combined image search with a spreadsheet-stored German vocabulary wordlist. I liked the idea of using computer-generated hints for the words and wanted to make a more general solution for any topic/language.

So, I made the interactive flash cards gadget. Each flash card has a hint and a form of guessing, with different options for hint generation and guessing strategy. The hints can come from the spreadsheet (e.g. user-entered definitions), Google translate (any supported language pair), Google image search, or Wikipedia (*currently down). The guesses can be entered in a simple text input, selected from multiple choices, or solved in a word jumble. Hopefully, these options are diverse enough for all types of learners.

Here are steps for using the gadget:

  1. Create a new spreadsheet, put a list of words in the first column, and put hints in the second column if you'd like to use that option. My sample spreadsheet has an animals wordlist:

  2. Click on the "Insert" menu and then select "Gadget..." This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in the URL to the gadget:

  3. The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select whatever columns you've created (either just words, or words and hints), and you should see the Range text field update with the range. If it doesn't work, you can manually type it in. Click "Apply".

  4. The flash cards gadget is designed to take up a bit more space, so it's best to move it into its own sheet. Click the menu in the upper left of the gadget and select "Move to own sheet".

  5. You can now play with the different hint/guess options to find your favorite. Several combinations are shown below.

    Image Search + Word Jumble


    Second Column + Multiple Choice


    Translation + Type-in


You can play with my sample flash cards here. One day, I hope to add the ability to track your progress in learning the flash cards content... but if you're a developer, feel free to beat me to it!

If you're a developer and want to tweak this gadget further, you can grab the code from here. It's licensed under Apache 2.0, so feel free to tweak it and use it however you'd like. (And if you've got fixes, I'm happy to patch them back in).

Creating a Wordsearch using Google Spreadsheets

Update: Google is deprecating Google Spreadsheets gadgets, as they announced in this post, so I am no longer updating or supporting them. If you're a developer, you can try Apps Script or the Spreadsheets Data API to see if you can accomplish the same thing. If you're a user, sorry, sometimes Google shuts down little used features.

I'm a fan of alternative learning and testing techniques. Back when I was the teaching assistant for the "History of Video Games" class (yes, that's a real class), I gave the final exam as an illustrated crossword puzzle. It was surprisingly hard to find software for creating that crossword, so I hoped to make a Spreadsheets gadget to make it easier. Unfortunately, crossword-solving algorithms that run entirely in JavaScript are hard to find, and I gave up and went for second best: a wordsearch gadget. (A big thanks to Robert Klein for the wordsearch JavaScript library.)

Here are steps for using the gadget:

  1. Create a new spreadsheet, and put a list of words in the first column. (Or, alternatively, use an existing spreadsheet that has a column of words you're interested in). My sample spreadsheet has a simple animals wordlist:

  2. Click on the "Insert" menu and then select "Gadget..." This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in the URL to the gadget:

  3. The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select all the cells that contain the desired words, and you should see the Range text field update with the range. If it doesn't work, you can always manually type it in.
  4. You can now customize the number of rows and columns. The default is 10 by 10, but if you have more words, you likely want a larger wordsearch. Click "Apply", and see the generated output.
  5. You have a few options for how you use the wordsearch. You can play with it immediately, inside that gadget, or you can use the option on the gadget menu to move the gadget to its own sheet and use it there. Note that each time you reload the spreadsheet, the wordsearch will be randomly generated with a new layout - so don't rely on it staying the same.

  6. You can also publish your spreadsheet so that other people can play the wordsearch. Click "Share > Publish" and you'll see the published URL, which you can share with friends. You can also use options on the gadget menu to embed the gadget in your iGoogle page or inside a normal webpage.

You can play with my sample wordsearch here. Enjoy, and hopefully one day, I'll have a gadget that makes crosswords too.

How to Convert a Google Spreadsheet into JSON, XML, and MySQL

Update: Google is deprecating Google Spreadsheets gadgets, as they announced in this post, so I am no longer updating or supporting them. I've written a post on a new technique here.

As some people know, I have a huge fetish for Google Spreadsheets - maybe because I'm always dealing with small datasets, and Spreadsheets is perfect for tinkering with them. Often, I start with my data in Spreadsheets, and later want to move it into a different static format - like a JSON file, MySQL data, or XML file. I originally did migration by concatenating column values together (e.g. ="" & A1 & ""), but I decided to make the process easier by creating a generic converter gadget. Using my gadget, you can easily convert any spreadsheet into those formats.

Note: I could get JSON and XML using the Spreadsheets data API, but then I would have to deal with alot of ATOM cruft when I'm only interested in the bare data.

Here are the steps for using the gadget:

  1. Create a new spreadsheet, and put your data in columns. Give each column a name, and choose carefully. Since this name will be used for MySQL attribute names, JSON keys, and XML tag names, the best names are lowercase, whitespace-less, and descriptive. The image below shows a spreadsheet of geocoded pizza locations:

  2. Click on the "Insert" menu and then select "Gadget...":

  3. This presents you with various categories of gadgets to choose from (similar to the iGoogle directory). My gadget isn't yet in the gallery, so you'll need to select "Custom" and then type in the URL to the gadget:

  4. The gadget will appear embedded in the current worksheet, and it will prompt you to select a range of data to send to the gadget. Select all the rows for the column with your address data, and you should see the Range text field update with the range. If it doesn't work, you can always manually type it in.

  5. You can now select either "JSON", "XML", or "SQL" from the dropdown, click "Apply", and see the generated output. To get the output in your clipboard, just double-click inside the frame, select all and copy.



You can see the published example spreadsheet, and see the XML output of the gadget in the second sheet. I generally move gadgets to their own sheet to make my workspace cleaner.

Tuesday, May 5, 2009

How do you document an options Object?

In JavaScript APIs and libraries, you can make a constructor or function more flexible and easy to use by having developers pass in an object of additional options.

Here's an example of a badly designed constructor that doesn't take advantage of this feature - the final 5 arguments are all optional, but yet, location must be passed in if the developer wants to specify hobbies.

EvilPerson(name:String, location?:String, age?:Number, job?:String, hobbies?:String);

When used, it's hard to understand what this constructor is doing:

var evilPerson = new EvilPerson("Taz the Haz", null, null, "Annihilator", "Blowing stuff up");

Here's an example of a well designed constructor that makes developers specify the absolute core information, and then pass everything else via an options object:

GoodPerson(name:String, options:Object);

When used, it's very obvious what options we're setting:

var goodPerson = new GoodPerson("Snuggly Muggly", {job: "Cuddler", hobbies: "Spooning"});

So, most people are in agreement that this is a good technique, but there's one problem: there's no standard on how these options objects should be documented.

In the JavaScript Maps API, we give the objects a class name, link to the class reference from the constructor, and then list the keys there. The advantage is that we can refer to these objects in the developer's guide or forum by name, the disadvantage is that we list a class in our reference that developers cannot actually instantiate, and that can be confusing.

The screenshots below are from the GMarker and GMarkerOptions reference.

In the Maps API for Flash, we turned those name objects into actual classes that developers must instantiate. This is good for documentation, but does perhaps bloat our API and make constructors more verbose.

The screenshots below are from the Marker and MarkerOptions reference.

In jQuery UI, every widget gets its own single-page documentation, with "Options" being a section along with "Events" and "Methods". There is no actual reference for the widget constructor itself, presumably because every widget's constructor takes only an options object. This likely works for jQuery UI developers as they're accustomed to this convention, but I personally found it confusing that there was no constructor reference.

The screenshots below are from the Dialog reference and options section.

In Dojo API, the reference for many of the Dijits specify that they take an Object for additional parameters, but they don't actually make it clear what can be passed into that object. My best guess is that the fields listed in the "Properties" section can all be passed in. This is probably once again a convention that seasoned Dojo developers are accustomed to, but arguably pretty confusing for a new Dojo developer.

The screenshots below are from the Dialog reference and the properties section.

In the Gears API, none of the constructors take a options argument, but there is something somewhat analagous: objects passed into event callbacks. In this case, Gears documents the object entirely inline with the reference. This technique has the advantage that everything about the function and the object are in one place - and the disadvantage that there's not a great way of referring to that specific event callback object elsewhere (besides saying "the object that the onerror function passes back").

The screenshot below is from the WorkerPool reference.

All of these styles have their pros and cons - and there's no one technique that satisfy our goals, like being easy for newbies to understand easy to refer to elsewhere in the documentation. What do you think? Have you seen a documentation that does it better, or do you think one of these techniques is clearly superior?