Tuesday, February 26, 2008

Design and Implementation - Episode 3

Update: Part 2 is now available here. I've also updated the links below.


I just got done mixing the first part of the third episode of Design and Implementation, the occasional podcast that Tim and I do. This time, we interviewed John Lam, who is a Product Manager at Microsoft on the DLR team. John has been working on IronRuby, an implementation of the Ruby language on the .NET platform.


Tim has been big into Ruby lately, so we had a good time talking to John. So good, in fact, that we ran fairly long. So I've split the episode in two - the first part is now ready. When I get done mixing the second part, I'll put that up too. Sorry to be a tease. :)


Download episode 3, part 1 (MP3, 30.4 MB).


Previous episodes:

Thursday, February 14, 2008

Announcing F4Panel/KeyServer

Update: The term "KeyServer" is a registered trademark, so I had to rename mine. Details and an updated version here. The download link in this entry is no longer active.


I've been a fan of the F-16 combat flight simulator Falcon 4 for a long time. As with most flight simulators, situational awareness (SA) can be a bit of a challenge - flying a flight simulator where your only view is the computer screen has been described as like trying to drive while looking through a drinking straw. Well, when I finished FlexWiki, as a reward to myself I bought a TrackIr. It's a head-tracking device that lets me change the view by simply moving my head. It's very intuitive and freakin' awesome - it's hard to imagine flying without it anymore.


The problem with using TrackIr is that you start living in the 3D view. That's a problem because in Falcon 4: Allied Force (F4AF), many of the gauges don't work in the 3D view. The biggest problem, though, is that the cockpit isn't clickable. So you wind up bouncing back to the 2D view all the time to toggle this or that with the mouse, which is slightly annoying.


I thought about building some sort of USB device (this sort of activity is called "cockpit building", and people spend literally tens of thousands of dollars on it), or maybe buying something, but everything I could find was either a bit on the expensive side or was going to stretch my extremely rusty electronics skills. And was going to take a hell of a lot of time. But wait! I'm a pretty good programmer! I can solve this with software. Hence were born F4Panel and KeyServer.


The basic idea I had was to transform my ancient PDA (it runs Pocket PC 2002 to give you some idea) into a touchscreen device that would emulate the major instrument panels in the F-16. It's not an original idea - you can buy a much nicer-looking version of what I wrote for $30 at http://www.pocketmfp.com/default.htm. But it requires Pocket PC 2003, and my device is so old it doesn't support that.


To make a long story short, I wrote my own. Here are some pictures of it:


F4Panel MFD F4Panel ICP


It works great, and I thought other people might like to make use of it, so I've posted a zipfile here.


There are two parts: F4Panel runs on the PDA, and KeyServer runs on the PC. Install F4Panel on the PDA by copying the appropriate F4Panel.cab file to your PDA and clicking it. KeyServer doesn't need to be installed - just run KeyServer.exe. When KeyServer starts, it'll put a very boring icon in the system tray. Right click it and choose "Load Profile". I've included a profile for F4AF, but the syntax is pretty simple and you should be able to figure out how to change it. Once you've got the profile loaded, go to the PDA and run F4Panel. Click Tools->Connect and enter the name of the computer where KeyServer is running. You'll obviously need to the PDA to be connected to the same network as the PC somehow - I just keep mine in its USB docking station.


The two programs communicate by means of a very simple HTTP-like protocol: F4Panel sends something like "CLICK ICP1" and KeyServer looks in a profile file for a command called ICP1 to figure out what keys to send to the foreground application. If it sends them okay, it returns "200 OK". I mention this, because I intended KeyServer to be general enough to be used with other games (or whatever) - you'd just need to write the PDA bit that sends "CLICK <commandname>" and the appropriate profile file that maps <commandname> to some sort of key sequence. The socket code is extremely simple - you can look at the F4Panel source to see it.


Because this was a fun-time project, and because quite honestly I'm momentarily burned out on full-scale open source projects, the zipfile is just a dump of the source and binaries. I'm sure you can cope. :) Consider it MIT-licensed, so feel free to go forth and improve it.


Update: The term "KeyServer" is a registered trademark, so I had to rename mine. Details and an updated version here. The download link in this entry is no longer active.

Wednesday, February 13, 2008


Well, I warned you that we'd be updating the MTPS REST API (located at http://lab.msdn.microsoft.com/restapistubs/). And we did. A bunch of things have changed. Mostly, I've added new functionality. I did, however, change the way one thing works in a fairly significant way, but it just makes for a good opportunity to talk a bit about how the service works.


If you visit the content section of the service, you'll be given a list of all the content item IDs in the system. (A content item is an atom of information - for example the documentation for one of the overloads of System.Xml.XmlReader.Read.) Right now that list is very short, because we're still not hooked up to the live database, so the bits that I can't get from the MTPS SOAP service, I just make up. You can tell because they all have "fake" somewhere in the URL. Eventually, we'll list all the content items here. Not because I think that a list of all the content items is inherently useful in and of itself (although you never know), but rather because I believe that every URL in the system ought to be reachable by traversing links from the service root.


Clicking on the only non-fake content item ID takes you here. This is what we call the alternates list for the content item, which happens to be the System.Xml.XmlReader content item. "Alternates" because it lists all of the available versions/locales pairs. See, every content item can exist in multiple versions and in multiple languages. So you can click here to get the German, .NET 2.0 version of the System.Xml.XmlReader content item, or you can click here to get the US English, .NET 3.5 version of the same document.


Once you click one of those links, you arrive at the content item page. (You can always tell what type of page you're on by examining the class of the <body> tag.) Here, you get links to all the various pieces of information that make up the content item. One of the most interesting is the Mtps.Xhtml primary document. This document contains most (but not all) of the information you're used to seeing on the MSDN2 website when you look up a class or method. And here's where one of the changes came in.


In the first version of the service that I posted, if you were to look at an Mtps.Xhtml document (for example, this one), you'd find that clicking in the links it contains would jump you to the other Mtps.Xhtml documents. At first blush, this is a fairly natural thing to do, as it mirrors what happens on the MSDN2 website. However, there was a subtle problem lurking that came up, and now the service no longer behaves that way. Now, if one content item links to another in the Mtps.Xhtml document, that link takes you to the list of alternates for the target document.


This has a number of implications. First of all, it means that if you want to use the MTPS REST API as a (really ugly) documentation browser, you're going to do a lot more clicking. To navigate from one Mtps.Xhtml document to another, you're going to have to click once to get to the list of alternates, again to pick a particular version/locale combo, and then again to get to the Mtps.Xhtml primary document. Not optimal from a human standpoint it's worth mentioning that the REST API is not designd to be navigated by a human…except developers who want to get an idea of how it works.


No, there's a good reason for this change. You see, it turns out that the underlying MTPS database doesn't actually contain version or locale information. You can see this if you use the SOAP service - that document that comes back is linked solely via something called an asset ID, which is basically like the "b8a5e1s5" (we call that form a "short ID") part of the URL for a content item. In the initial release, I actually wound up just using the locale and version of the linking document to synthesize a link to the target document. Obviously, this would break if the target document happens to be of a different locale and/or version. And it did.


But that's not the reason we changed it. The real reason is that it's not clear that the service should be defining what the correct behavior should be. Should we always send links to the latest version? To the same version? If you think you know the answer for your scenario, let me assure you that someone else will have a different one. On the MSDN2 website, we can make assumptions about which way it should go because it's not an API, it's an application. But the REST interface is an API. So we have to leave it to the client, which means linking to the alternates page, so the client can implement whatever policy they want - pick the latest, pop up a dialog, whatever.


I mention this because to me, it's really characteristic of the RESTian nature of the interface in two ways. First, we leverage links, rather than expecting clients to synthesize URLs based on knowledge of how the system works. It emphasizes the view of the system as a directed graph of linked resources. That has more of the "of the web, not just on the web" flavor that (IMO) characterizes good REST interfaces.


The other thing that it brings home is that the REST API is not a website in the traditional sense. That is, it's not that I've just built a website and decided that all my .aspx pages now have .xml siblings or whatever: the system is fundamentally designed in a different way - to expose as much of the information available in the database as possible, not to present it for human consumption. Which goes part way towards explaining my decision not to include stylesheet links in the head, too. (A post for another day, perhaps.)


So this has turned into a somewhat long (and perhaps somewhat rambling) post about a service that - as far as I know - no one is using yet (tell me if you are). But as the first major REST system that I've implemented "for real", I've found the issues that come up to be enormously helpful towards my understanding of the advantages and limitations of REST. Hopefully some of you will, too.


I hope to occasionally post more information about the design and implementation of the MTPS REST API, and about the things I'm learning from it, as we move forward.