Scenes From an Interview

|

"Obviously the job requires some pretty serious math skills. As the first-line screener, my job is basically to do a sanity check and make sure that you meet the baseline we're looking for, so that we don't waste our time and your time with further interviews that aren't going anywhere. I see you've got an impressive resume and a lengthy career, so please don't be offended if my questions seem simple; it's not ajudgementon you, but a reflection of the goal here. Any questions? No? Good."

"So here's my first questions: What's one plus one?"

Loser answer number 1:

"Geez… I don't think anybody's asked me to add one and one since elementary school. Is that really something you do? I've been working in this field for twenty years now, and I don't think I've had to know one plus one even once… any competent professional has Excel, or a calculator, or somethingthat will take care of details like that for them. I'd go so far as to say that anybody who's manually adding single digit integers like that probably should be fired."

Loser answer number 2:

"Oh, I remember this one! I haven't actually done one plus one since kindergarten, but I studied up on the basics before this interview, and I remember that the answer is two. Here, let me write a two for you… It's kind of curvy around the top, I think, like this… no, more like… here we are, that's a two."

Loser answer number 3:

"Eleven. Yes, I'm sure. No, there are no problems with my answer. You put the two ones next to each other, and it's eleven. What the hell is wrong with you?"


The humor here's pretty obvious, right? No reasonable person misses the fundamental problem with these answers, I hope. Any yet if you shift the field to computer science, suddenly people think these sorts of shenanigans are reasonable.

Of course nobody would implement ELEMENTARY_DATA_STRUCTURE_1 by hand in this day and age; it's in the standard library on any platform worth dealing with (well… maybe not Cocoa…) and the folks writing the library probably spent a lot more time debugging and optimizing than you'll ever be able to devote. You don't get asked to implement these things because the interviewer's going to steal your code and check it in to source control.

And you also don't get asked because, gosh darn it, we totally need an idiot with an eidetic memory who can vomit code snippets he doesn't understand. We have Google for that! We're not testing your memory, but your ability to understand basic computer science principles and - gasp - write code! If you don't have the code paged into memory right now, from our perspective that's a HUGE WIN. We want to watch you re-derive things from fundamentals, not regurgitate all over Collabedit.

I hate seeing both sides of a thing.

Air conditioning feels to me like more than a modern convenience. It's the sort of thing that I expect every freestanding structure to have, and the lack of AC is to me as disconcerting as the lack of electricity must have seemed in the near-recent past, when 'everyone' had it but literally everyone didn't yet have it.

AC is about more than cooling; it's about your air being cleaned and circulated. Your air is, for lack of a better word, conditioned. It gives me a feeling of protection to know that a building is relatively air-tight and that the oxygen supply is being regulated. There's a wild, untamed outside, where the insects and arthropods and germs and smoke and pollution and other anarchist elements can have their day, and there's the nice, soothing, controlled inside where I can have my books and WiFi and TiVo and peace and quiet. It's a wall.

A largely illusory and highly ineffective wall, to be sure. But it's making a stand; drawing a line. Out there: chaos; in here: the homey disordered order that defines my comfort zone.

And of course in asserting all this, I know full well that I'm being silly. I sound like a science fiction cliché — one of Asimov's bubble-dwellers who refuse to believe the world outside is even habitable, of perhaps someone out of Brave New World. And while I can recognize intellectually that I am — on this point at least, and possibly on many others — stark raving mad, that doesn't in any way negate the underlying impulse. Knowing I'm crazy doesn't make me sane, it just makes me annoyed at the insufferably buggy firmware with which God or evolution or the Engineers has saddled me.

Quick background info, or 'what the hell is a Stylunk?'

I play Clan Lord, a multiplayer online RPG. Clan Lord provides a lot of ways for players to customize their characters' appearance, including a system for changing shirt and pants colors with an algorithmic dye and bleach system. Experimenting with dyes and bleaches in-game can be prohibitive — each application consumes in-game currency and (often rare) materials. As a result, there's a long tradition of external dye-simulation tools; the earliest was Stylus (named in the 'function-us' pattern of many Clan Lord NPCs), followed by Stylos, the OS X re-imagining of Stylus. Stylos didn't work well on Mac OS X 10.4 Tiger, so in 2005 I built the first version of Stylunk as a replacement.

Since then the number one Stylunk-related request has been for a Windows version, and the number two request is 'hey, add this new shirt color!'. Both of which were difficult enough to fill that they happened never (Windows version) and only intermittently. So I've decided to simplify cross-platform concerns and centralize updating by turning Stylunk into a web app. The beta is right here.

Stylunk Screenshot

Palettized recoloring in JavaScript or 'the actual non-background stuff about which I plan to write'

I started playing Clan Lord in 1998 and it had already been in development for a while at that point, so it shouldn't be a surprise that the tech isn't exactly modern. Images in Clan Lord are an run-length-encoded list of indices into a per-image color map, which itself contains indices into the 'Mac standard' 256 color map. That's all pretty integral to Clan Lord, because character customization is implemented as a set of 20 color overrides for the per-image colormap: indices zero and one contain the highlight and shadow colors for the character's hair, for instance.

Images for a particular icon are arranged into a single 16x3 sprite sheet, comprising the 32 standing/walking/running sprites in eight cardinal directions as well as a 'dead' sprite and fifteen 'poses' that players can activate to emote. Here's what the 'Ghorak Zo' sprite sheet looks like:

Ghorak Zo Sprite Sheet

My first stab at implementing web Stylunk was about what you'd expect: I converted each of the sprite sheets into PNG files and wrote code that draws the selected sprite into a canvas, iterates across the pixels, and replaces the 'default' colors with the mapped values calculated from the current UI selection. Then I created a smaller canvas, copied the frame I needed from the large canvas to the small canvas, and used toDataURL() to extract something that I could stick into the background-image of my buttons.

It all worked fairly well, at least at first. On my main machine (a Core i7 Mac Mini) everything was peachy. On my MacBook Air, it was sluggish. On my iPad... well, the less said the better.

My immediate response was to try some very aggressive caching, leading to the creation of a reusable JavaScript least-recently-used cache. That helped, but not as much as I'd hoped.

My next thought was: I'm doing more work than I need to: there's no point colorizing the entire sprite sheet and then only displaying a single frame of it. So I swapped things around; first extract a small canvas from the larger, then recolor only the smaller canvas. That helped too, but it was still pretty logey on the iPad.

Unfortunately there's no way to profile JavaScript in MobileSafari. But desktop Safari does have a profiler, and it showed something interesting: the slowest part of the process was reading the pixels out of the initial canvas. So I took a cue from Clan Lord and took a step back in time: instead of storing the images as PNG sprite sheets, I wrote a tool that converts each frame of the sheet into a JavaScript data structure containing a run-length encoded bunch of pixel indices. That way I can skip the 'reading from canvas' step, and jump straight to writing them. I also took the step of storing each frame as a separate JavaScript file which the main app loads on-demand via XMLHttpRequest, which simplifies the caching a lot by letting the browser do the work.

If you're curious, you can take a look at the code for a sprite here. That's my JS-encoded version of the male Ghorak Zo facing east — the top-left sprite in the image above. Yup! — despite being larger than a PNG representation or the same image, and despite needing to be parsed by the JavaScript engine, it still ends up being faster than reading data back from a canvas.

The end result is that Stylunk runs at a usable speed on my iPad (first-gen) and on my iPhone 4, which is good enough for me. There are still some minor inefficiencies as a result of the tortured path to the current architecture — if I were doing this from scratch there would also be JavaScript representations of the character color maps, which would simplify the color mapping process and also allow me to easily draw characters using the color map data from the XML data feed powering the Clan Lord Informer and iClan.

I'm actually half-tempted to do that, because it would provide a starting point for building a Socket.IO- and Node.js-powered HTML5 Clan Lord client. But that's a headache for another day.

In the course of a recent quick JavaScript side-project — post forthcoming — I needed a simple cache. Then I needed another cache within the cached objects. Then I needed another cache. It was at that point that I realized I should probably factor things out into a reusable component, and built JSLRU.

Of course then I refactored things dramatically and it's barely used at all. But if you need a JavaScript least-recently-used cache, check it out.

Generic Accumulators in C#, Redux

|

It turns out one of the most-trafficked pages on this site is my discussion of generic accumulators in C#. It occurs to me that it could use a bit of an update, as some newer features like lambdas and the predefined Func<> family simplifies things quite a bit:

class Program
{
    public static Func<T, T> MakeAccumulator<T>(T start, Func<T, T, T> addFunction)
    {
        return inc => start = addFunction(start, inc);
    }

    static void Main(string[] args)
    {
        var intAccumulator = MakeAccumulator(0, (i, j) => i + j);

        Debug.Assert(0 == intAccumulator(0));
        Debug.Assert(1 == intAccumulator(1));
        Debug.Assert(11 == intAccumulator(10));
        Debug.Assert(55 == intAccumulator(44));

        var floatAccumulator = MakeAccumulator(0.0, (i, j) => i + j);

        Debug.Assert(0 == floatAccumulator(0.0));
        Debug.Assert(0.1 == floatAccumulator(0.1));
        Debug.Assert(1.1 == floatAccumulator(1.0));
        Debug.Assert(5.5 == floatAccumulator(4.4));

        var stringAccumulator = MakeAccumulator("", (i, j) => i + j);

        Debug.Assert("" == stringAccumulator(""));
        Debug.Assert("ZYZ" == stringAccumulator("ZYZ"));
        Debug.Assert("ZYZZY" == stringAccumulator("ZY"));
        Debug.Assert("ZYZZYVA" == stringAccumulator("VA"));

        Console.WriteLine("Success!");
        Console.ReadLine();
    }
}

So there's that. Still not terribly useful, but I do like shortening code.

“A good start.”

Bad, old jokes aside:

I've said it before, and I'll say it again: the Bush War on Terror was never about hunting down bin Laden. To view it in that light is to characterize it as a campaign of retribution rather than one of pre-emptive self defense. It is a simplistic and reductionist misrepresentation favored primarily by those who opposed Bush in every fashion, and it's a straw man that we would all do well to stop stuffing.

Some people make the world better through their existence, some make it worse, and the vast majority of us largely break even. Osama bin Laden was clearly in the 'worse' column, and in that sense the world is a better place with him a corpse. But to claim that his death in any measurable way makes us safer or surer or more just is folly.

Should've Bought an Xbox

|

I bought a Playstation 3 a few years back (when I got my HDTV, as I recall) primarily to use as a blu-ray player (at the time it was actually cheaper than a standalone player). As Sony doubtless expected, it entered my home as a shiny black Trojan horse, and I've bought a handful of games since then.

Including, fatefully one from the Playstation Network (link goes to a Flash-only site, because Sony's just in full-on pissing-me-off mode at the moment).

If you're reading this there's roughly a 99% probability that you already know that the PSN has been 'out' for nearly a week, and the latest news from Sony is that it ain't comin' back anytime soon, and oh, by the way, some hackers probably have your credit card numbers.

I know this the same way you do, through the magical collaborative power of the Internet. Not, say, from an email sent to me by Sony warning me that my credit card number had been stolen. Strike one, Sony. You assholes.

But as annoying — and probably actionable — as their failure to proactively warn their customers may be, that's not what really pisses me off.

No, what's really bugging me is that I can't use Netflix on my PS3.

Why? Because Netflix on the PS3 — despite being tied to my totally independent non-Sony Netflix account — requires a PSN login to function. For no reason at all except that Sony are a bunch of goddamned morons.

Thank God for the Apple TV.

Change I Can Believe In

|

I Still Hate Regions

|

Potemkin Unit Testing

|

After the Russian Empire annexed the Crimean peninsula in 1783, Tsarina Catherine II (motto: “I'm greeeeat!”) took a tour of the area, guided by her trusted advisor and alleged-favored-non-equine-paramour Gregory Potempkin (or if you're not into the whole Anglicization thing, Grigory Potyomkin... or if you're really not into Anglicization, Григо́рий Алекса́ндрович Потёмкин).

As the story goes, Catherine's inspection took the form of a leisurely cruise down the Dniper River. Potemkin, being aware that the Crimea was kind of a crummy area and fearful that the Tsarina would mislike the realization that her new territory kinda sucked, ordered the hasty construction of numerous fake village façades along the river bank. The illusion held; Catherine went home thinking the Crimea was a bustling hub of non-squalid not-mud, and our modern world gained a vivid new idiom: 'Potempkin Villages'.

Of course all the actual evidence is that the story is bunk — Potemkin may have instructed the peasants to clean up a bit and maybe paint some fences, but the idea that the whole area was an elaborate set was an extreme exaggeration spread by his political rivals. But it's one of those stories that's just too good to not tell, isn't it? It's 'truthy'.

Changing direction entirely: unit testing is the new hotness in software development. The basic idea is that you decompose your software into small, manageable units and create dedicated automated tests that verify the functionality of those units. And it is, in general, a really good idea.

The problem that crops up with unit tests is that some things are just really hard to test, particularly when your code interacts with something outside your control — such as a human user, a piece of hardware, or a third-party web service. In those cases you need to get tricky; you create new layers of abstraction that separate the interaction from the main work of your module, and then you create 'mock' version of those abstraction layers and substitute in a 'simulated user' for a real user, or a 'simulated serial port' for your hardware, or a 'simulated web service' for the third-party service.

In some cases that approach may make sense. For some pieces of hardware the range of possible states is limited; a button is up or down, and it's never both. If a user is given an extremely limited set of buttons to click, you can reasonably simulate every possible interaction model. But for anything more complex, you're kind of creating a Potemkin unit test. So you've extracted out an ITwitterApiProxy that your TwitterService talks to, and you can plug in your MockTwitterApiProxy and write a whole host of tests for your TwitterService. Every failure mode you can think of can be simulated by the MockTwitterApiProxy and you've coded the TwitterService to deal with all of them reasonably — and hurray, the unit tests mean you're safe!

Now you go to production, with the RealTwitterApiProxy, and stuff goes wrong. Twitter's failing in ways you never anticipated! So you add more switches and dials to your MockTwitterApiProxy, and add more code to your TwitterService to deal with them, and write tests to exercise them... and hurray, the unit tests mean you're safe! ...at least until Twitter fails in another new way you haven't seen.

Compare that to how you would have handled things without unit tests: You code up TwitterService, handle the error cases you anticipate, go to production and discover some more error cases, update TwitterService to handle them... lather, rinse, repeat. It's essentially the same workflow.

So what does the extra effort buy you? What's the benefit of building your API abstraction and unit tests?

Well the obvious answer is that it buys you protection against regression. You have an explicit test in place for handling error type A, so if in the course of implementing support for type G errors you accidentally break type A, the unit test will fail and you'll find out. There's that, certainly. Without unit tests it's basically down to trust: I trust myself (or my fellow developers) not to break this part of the code while working on that part of the code.

But on the other hand, your test for handling error type A isn't really testing your handling of error type A, it's testing your handling of your mock simulation of error type A. How can you be sure that in the course of adding code to simulate error G to your mock you didn't accidentally break the code that simulates error type A? Isn't that the same sort of "trust yourself" approach that the non-unit-testing approach is left to? Should you add unit tests for your mocks to ensure that they're properly simulating errors?

Ultimately a lot of this is down to personal judgement, like most of the interesting questions in software development. And I'm certainly not going to argue that unit tests aren't a good idea a lot of the time. But I do believe that there are certain situations where unit tests create a lot of extra code to maintain without really adding much in the way of protection, and that committing to building such Potemkin unit tests is a foolish consistency of precisely the sort that will prove a poor substitute for Norman Osborn.