An icon can offend my aesthetic sensibilites

Using Mac OS X is, generally speaking, a visually pleasing experience. People (including, on several occasions, me) can go on and quibble about inconsistent use of brushed metal, or unpredictable applicability of click-through, but by and large the visuals (even for 3rd-party apps) are nice, consistent, unsurprising.

I've just realized how little it takes for the whole feeling of polish and friendliness to come crashing down.

Something is amiss

There's something jarring in the above image. Can you spot it? Here, let me zoom in:

Visually Offensive Icon

Oh my. 

They just had to put an ® symbol RIGHT IN THE GODDAMN ICON? Think of how heartbroken the designer who drew the short straw had to be feeling after being forced to do this. So much work, so many iterations of the design, only to have it ruined at the last second when a lawyer reminded him that it wasn't enough to point out that the Adobe Reader logo was a registered trademark in the About screens and the documentation, you should remind people whenever they look at the icon too! Outstanding.


Caught one!

As an apartment dweller on the top floor of a triplex, I have no upstairs neighbours, only an unfinished attic above me. Since outdoor temperatures started dropping with the arrival of Winter, I've had a few uninvited houseguests making a ruckus up there.

After a few (unsuccessful) attempts to look around with flashlights to see what was up there, my landlord and I eventually set a trap with some almonds and peanut butter.

Today we caught ourselves our first attic-dwelling squirrel! I know what I'm eating for dinner*!
Got the little bugger!

*: Actually the squirrel is being driven away from the house and gently released into a park.



has earned the unfortunate honour of being nothing more than a physical, browsable storefront for amazon.ca.

I was in recently to wander amongst the stacks, when I picked this up:
Book from Chapters

Looks tasty, but 55$? Out comes the iPhone...
Amazon.ca mobile

You can order straight from the iPhone-optimized website; my stuff should be delivered to the office by Friday. The sad thing for Chapters is that I really don't see how they can effectively compete here. Amazon, with no physical locations (that Chapters location at the corner of Rideau and Sussex has got to be pricy) and massive economies of scale, will always have lower overhead and be able to compete on price, so only shipping costs and delays can hurt them here, and I'm willing to wait 5 days for cookbooks.

I suppose the sensible thing for the brick-and-mortar player in this race is to attempt to provide a better experience, but if you're selling books, I don't really see how you could do that... Ideas?


Thankful for the Executor Framework

It is commonly said that a good framework makes common tasks easy to do, while keeping hard things possible. Today, I'm reminded that a good related property is to prevent common errors.


My friend and fellow developer Jason posts today a chunk of hard-learned wisdom about spinning off worker threads to perform asynchronous tasks in an ASP.NET application. It seems that if an exception bubbles up to the top of the call stack, not only does the thread die (which is expected), but it takes down the entire ASP.NET application, forcing it to restart, leading to a loss of in-memory session state. OUCH, yes, and it's an easy bug to introduce.

Making easy errors hard to make

This is why I'm thankful for the general design Java's Executor Framework imposes on the developer, as it renders this sort of bug a bit harder to make.

Using an executor service with the Callable interface is pretty simple and it's generally easy to work with:

  • You create a task to offload, as an instance of a Callable, with a call() method that's allowed to throw any Exception it wants.

  • You submit your Callable to an executor service, which spins off a thread for it if required, and immediately returns you a Future instance, while the worker thread does its thing.

  • Later, using the handle of that Future instance, you can query the result of the computation from your main thread by calling get() on it. If the task you spun off threw an exception from call(), you get the exception only then (wrapped in an ExecutionException), on the main thread, where you're actually able to (and forced to) deal with it, since Future.get() declares itself as throwing ExecutionException.


Postal codes on an iPhone

Canadian postal codes satisfy this regex: "[A-Z][0-9][A-Z] [0-9][A-Z][0-9]". Do you have any idea how annoying that is to type on an iPhone?

Secret Santa Protocols

Some friends and I are kicking off the holiday season early this year! Along with Jason Kealey and Etienne Tremblay of LavaBlast Software, as well as their better halves, I've arranged to rent a rather nice cottage in mid-December. We decided to hold a Secret Santa gift exchange over there, which brings us to this post.


How do you arrange a randomly-assigned Secret Santa event when the participants are geographically distributed?

Assignment of giver/recipient pairs is usually handled by drawing strips of paper from a hat, an approach that obviously won't work here, when planning over email. So I started to think about how one could do this without relying on a trusted third-party. Is it possible for a group of peers, communicating only through email, to each choose a random recipient and guarantee uniqueness of picks, while ensuring picks are not revealed to others, and no one ends up picking themselves? [My father, over dinner the other day, helpfully pointed out that this is known as a derangement problem.]

The real-world pragmatic approach

We ended up going with the very pragmatic approach of relying on a trusted third-party (in this case a simple computer program). I wrote a Java program that took the list (L) of 5 email addresses, shuffled it (using Collections.shuffle()), then sent an email to address L[i] containing address L[(i+1) % 5], all without printing to the screen what it was doing, or logging anything. Once the program exited, there was no way for anyone to recover who got what address, and it guarantees that the final assignment is a derangement: no person in the initial list gets themselves.

Now, this is all well and good, but it's a boring solution because of its reliance on software. Is this doable with only five people talking over email? (Yes, it's a mostly academic exercise.) I've had some ideas that go in the right direction, but haven't solved the problem of ensuring the final mapping is a derangement, other than running the process for multiple rounds, until no one declares they received themselves as an assignment.

Primitive: mapping IDs to gift recipients

The first primitive our protocol needs is a method of mapping an abstract identifier (say, a number) to an actual name. This is because since participants need to pick one of the 5 identifiers unsupervised, they must not know in advance which person this identifier will represent.

This is the easy part: have everyone pick a unique value i from the pool of identifiers [0-4] (randomly or not) and remember it without disclosing it. Your assigned name is then L[(i+d) % 5], where d is the integer part of the TSX composite index at market close the following day. The offset value d is the same for everyone, is not known in advance, and when we all exchange gifts we can audit that no one cheated and changed their chosen ID after knowing d.

Independently choosing IDs

The above relies on everyone having independently picked a unique value for i, and this is where things get interesting.

  • There are 3125 [5^5] sets of picks when done independently with no knowledge of the others.
  • Of those, only 120 [5!] contain unique, unduplicated, choices, or 3.84%.
  • Of those, only 44 are derangements, where no one ends up with themselves (1.408% of the total)

First approach: anonymous broadcast

If a means of anonymously broadcasting a message to the whole list is available, we can rapidly constrain picks to the 120 cases where there are no duplicates. We'll then have a 36.7% chance [44/120] of having a derangement in each round, so we should be able to settle on a solution in very few rounds.

  • We declare the round started, and the pool of legal choices to be {0, 1, 2, 3, 4}.
  • Everyone picks a random delay d in [0; 3599] (with 5 participants, collisions are unlikely).
  • After d seconds, pick a value in the pool of legal choices, and anonymously broadcast "n has been picked", everyone removes n from the pool. (You can also just always choose the first available number, that works equally well.)

Second approach: no anonymous broadcast

OK, so you don't have an anonymous remailer. No problem!

I've devised a method to ensure the picks are independent, but it can take many rounds to work, as the expected success rate is only 120/3125. (And after that you still have the problem of restarting if you don't have a derangement.)

I think the following should work, but YMMV, I haven't proven it:

  • We publish the list of 5 participants. Their order is unimportant.

  • We publish 5 IDs. Let's use 5 prime numbers {3, 5, 7, 11, 13}. I don't think they need to be prime, but they must be picked to ensure that their product, known by all (in this case, P=15015) can only be achieved if you pick EXACTLY one of each number, and this is easy to ensure if you take primes [I think].

  • Everyone independently picks an ID i from the list, keeping it secret.

  • I'm first on the list. I choose a random large integer s. I compute P' = i * s * P.

  • I hand off this product (P') to the second person on the list. The number she receives from me is evenly divisible by 3, 5, 7, 11, 13 and P, so she has no way of knowing what my chosen i is, or what value of s I picked (there are 5 equiprobable possible values for s, which tells her nothing).

  • She multiplies P' by her own chosen i, and gives that to the third person on the list, and so on.

  • The list wraps around and I'm sent a value from the 5th person on the list. If everyone picked a unique value for i, I get s * i0 * i1 * i2 * i3 * i4 * P or, succinctly, s * P2. If I get anything else, then I know there's a duplicate.

  • I announce whether or not there was a duplicate. (I, or anyone else, can always lie, but then when gifts are exchanged we'd know someone lied - in the spirit of the holidays, the participants in this protocol are honest.)

Phew. Each round has a 1.408% chance of working, so it could take a while. I have yet to find a much better approach, so I think our little 30-line Java program was appropriate in this situation.


This Week in Food

Will Ron Eade wake up with a head of lettuce in his bed?

First up is Ron Eade's column from Ottawa Citizen blogs, where he heaps some well-deserved praise on Kevin Mathieson (of Art-Is-In Bakery) for his bread. Eade says it's better than ACE bread (n.d.a.: no shit), and I for one am glad to note that the supply problems I was hurting from a year ago seem to be a thing of the past: whereas last year, getting your hands on Art-Is-In bread required much haste in returning home from the office, this year I find that retailers aren't consistently running out by late afternoon.

Eade calls New York Times' Mark Bittman's bread recipe a good replica of Art-Is-In's, which I have to humbly disagree with. Bittman's recipe is good, it's my go-to recipe for homemade bread, but I hardly think it's close to equal to Mathieson's.

I think it's awesome that he can get away with saying:

I'm not kidding when I say you need a six- to eight-quart heavy cast-iron Dutch oven with lid. Every kitchen should have one.

Yes, every kitchen should have one - but when I say anything like that, people roll their eyes at me. If you're a newspaper columnist though...


Amate in Wellington Village

Got around to trying Amate (link goes to ottawafoodies.com) for some quick Mexican take-out. I came in a few minutes before they decided to shut down for the night, and ordered a tostada with some puerco pibil. Unfortunately, I only got a tiny spoonful, maybe 40g, of pork but hey, what I tasted was good. I think they're still going through opening pains and are a bit disorganized, so it's not fair to say more at this time - let's give them a few more months.

I'll probably try my hand at making puerco pibil myself (in more generous quantities) when I get a free afternoon.

Malak Pastry

Tasty Baclava

I've lived in Westboro for over a year and had never tried Malak Pastry, despite it being right at Carling/Broadview - shame! It's a bakery offering up a range of baklawa (which I'll admit I know little about). I asked for the shopkeeper's recommendations and got a few samples to try before buying, and was incredibly impressed. Delicious! They weren't yet listed on OttawaFoodies, so I'm adding them presently.


Finally, I've tried sauerkraut (at a corporate event at the office, no less), bringing my 100 Food countdown (previously blogged about) to 57% completion. Moving up 1% in two months is a rather pathetic pace, so I'm going to make a bigger effort.


Sure, but what year?

Sure, but what year?

That's what I call optimistic.

I really, really, wish I could afford one of those condos, the artist's renderings I've seen look pretty sweet. Also, expensive.


Coffee Shop Technology

I'm sitting in the Westboro Bridgehead, working on a presentation on my MacBook Pro.
Observations from the coffee shop:
  • A 50 year-old looking woman is texting. She's typing pretty fast, too.
  • No one is wearing iPod headphones. Everyone is here to enjoy the atmosphere, I like that.
  • Among the people typing away on laptops, the Mac market share is 100%. ONE HUNDRED. Way to go Apple.


A bit of free money from ING Direct

ING Direct is trying to beat the fray of banks that will be offering TFSAs in January 2009. Even though, to the best of my knowledge, the federal government hasn't yet published the full TFSA rules and details, based on the details available now, banks are starting to jump in.

Here's the announcement they made on October 7th:

Earn special Bonus Interest between October 4th, 2008 and December 31st, 2008 and get saving tax-free earlier!

Because we just couldn’t wait until January 1, 2009 – we’ll cover your taxes!

Bonus Interest!

While we can’t help you avoid taxes in 2008, we can pay you more than enough bonus interest to cover those taxes! Effective January 1, 2009, funds deposited in the promotional Tax-Free Investment Savings Account opened between October 4 and December 31 will be transferred to a new Tax-Free Savings Account so you won’t miss a minute of Tax-Free interest.

Open an ING DIRECT promotional tax-free Investment Savings Account today and on December 31st we will double your interest payment. This should be enough to cover any tax you’ll need to pay on interest earned and will help you get a head start for tax-free saving in January.


With the new Tax-Free Savings Account, any interest earned in an ING DIRECT Tax-Free Savings Account will not be taxed.

It seems this account is identical to their regular savings account, except it automatically gets registered as a TFSA on 1 January 2009, and on 31 December 2008, it gets a bonus interest payment equal to all the interest paid in the last 11 weeks of the year (from now until 31 December). They're marketing the bonus payment as a way to offset taxes paid on the regular portion of the interest in 2008, since TFSAs don't yet exist.

I'm not normally a fan of trivial quarter-point rate chasing between banks, but assuming you've got a savings account at ING Direct already (I keep my emergency cash at ING), I see absolutely no downside to getting in on this.

It took me about 2 minutes to login, create an anticipated TFSA, and transfer 5000$ from regular savings to the new account. At the current 3% rate, with monthly compounding, the expected interest on 5000$ between now and December 31st is around 35$, so they're giving away 35$ for two minutes of work.


Dealing With a Cold

Holy crap, what a crummy week. Caught a cold, saw productivity go down a bit, but was able to pull through without missing any work thanks in part to reading Eric Rescorla's blog post about "Managing the Common Cold". The guy is an engineer / security guru but he happens to post frequently about statistics and health, and in this case he's really on to something as he goes much further than the classic advice: "Oh just take a Tylenol Cold and stop whining":

  • Nasal sprays and pseudoephedrine for congestion: He recommends Flonase, which requires a prescription, but I've had luck this week with an OTC decongestant spray once a day (mindful of widely-reported acclimatation effects) and Advil Cold & Sinus. I feel kind of stupid for buying Advil, as it's just ibuprofen and pseudoephedrine, but it was recommended by a colleague; next time I'll go generic.

  • diphenhydramine hydrochloride, an antihistamine with sedative effects to help fall asleep: costs practically nothing in generic form. Quite effective.


The Absolutely Essential Software List for Mac Newbies

This is for my friend Jason Kealey, who finally got a MacBook Pro today. Welcome to the awesomeness of OSX :)

Newbies, here's the absolutely essential, grab-this-software-today stuff you want to go install:
I still haven't found a perfect image editor. I'm thinking of dropping the cash for Pixelmator, but even on a new MBP it feels a bit sluggish... I'm still wrestling with the decision while my trial period ticks down.

The fact that this list is actually pretty small for me means OSX is, really, quite a bit more functional out of the box than Windows. Bundling of software with an operating system can be a bit contentious, but I think OSX generally gets at least this correct.


Ask TUAW - Finding which processes own which network connections - Here, I'll Save You 30 Bucks

A good question popped up on Ask TUAW today:

Richard asks
I have recently noticed that I have a fairly constant upload of 14-16 KB/s going on in the background (I'm using iSlayer's iStat menus), even though I haven't initiated any upload. I'm not now running any online backup apps. I've checked in Activity Monitor, and can't see anything very out of the ordinary there, although evidently I've missed something. Is there an easy way to see which applications/processes are using the network connection? Or should I get Little Snitch? It's quite annoying to see that the network connection is being used, and being unsure about what is using it. It's potentially disastrous when I'm using metered connections!

Here's the answer TUAW gave:

Little Snitch ($29.95) is probably the easiest way to go. There's also another recently released net monitoring application called ProteMac Meter ($29.95) which might be worth checking out. I don't recommend Glowworm FW as I've had serious problems with it under Leopard and have found others reporting similar difficulties. It may be that the demos of one of these application will be enough to find the source of your unknown network traffic.

Ummm, let me save you 30 bucks and a download, dude, OS X has everything you need built in:

lsof -i

Lists open sockets. Output looks like this, presto!

Quicksilv 784 jpdaigle 253u IPv4 0x4baba68 0t0 TCP>host44.hrwebservices.net:http (CLOSE_WAIT)
SystemUIS 13716 jpdaigle 10u IPv4 0x431a880 0t0 UDP *:*
Mail 23859 jpdaigle 17u IPv4 0x51cb270 0t0 TCP>webaccess.hostedmail.net:imaps (ESTABLISHED)
Mail 23859 jpdaigle 18u IPv4 0x6d7d270 0t0 TCP>webaccess.hostedmail.net:imaps (ESTABLISHED)
Mail 23859 jpdaigle 23u IPv4 0x8587e64 0t0 TCP>webaccess.hostedmail.net:imaps (ESTABLISHED)
Mail 23859 jpdaigle 26u IPv4 0x58f8e64 0t0 TCP>webaccess.hostedmail.net:imaps (ESTABLISHED)
firefox-b 25763 jpdaigle 31u IPv4 0x703266c 0t0 TCP> (ESTABLISHED)
firefox-b 25763 jpdaigle 36u IPv4 0x9779270 0t0 TCP> (ESTABLISHED)


Upgrading a Pay-as-You-Go Fido Account to an iPhone 3-Year Contract: Nontrivial

There's probably nothing too original at this point about someone blogging about problems buying a new phone from Fido, but, well, this particular problem, I haven't seen mentioned yet.

Walked up to a Fido booth tonight thinking I'd buy a new phone (not important which one for this story, but gee, I think you can take a guess). "In and out in 15 minutes", thought I. Ha. I've got to say though, the employees there, for all their trouble in getting things done, tried really hard and were so patient on the phone with the mothership (yes, the employees get put on hold for an hour too) that I really can't blame them at all.

I'm with Fido on a Pay-as-You-Go plan (prepaid airtime), and since I've been a customer for a while I have a bunch of rebate dollars (called FidoDollars) usable as credit towards new phones. Problem is, you can't walk into a Fido store and get your prepaid account converted to a 3-year contract while keeping the same phone number and already accumulated airtime credit. Can't be done, no matter how long the poor salespeople stay on hold with the customer service center trying to make it happen.

There are two main options available if you're already a Fido customer on Pay-as-You-Go, neither of them particularly appealing:

  • Buy the JesusPhone(TM) from the Fido store, have them activate it on a new phone number with a new account on a 3-year contract. You lose your existing phone number (well, it actually stays active on your old phone, but what use is that?) and get a new one. You can't use FidoDollars credit to help pay for the new phone, and you'll lose all your prepaid airtime when it expires. They have absolutely no way to use your FidoDollars or transfer your prepaid airtime credit.

  • Have the Fido store order a JesusPhone(TM) (by phone, which takes over 30 minutes for some reason) for you from the customer service center. You can keep your phone number and use your FidoDollars to help pay for the new phone, and also any unused prepaid airtime will be credited to your monthly bill. Perfect, except they'll start billing you your monthly contract BEFORE you receive the new phone, and as the sales girl explained, you'll then have to call customer service when you do get the new phone up and running and get them to credit a pro-rated portion of the month. Also, it takes ~10-12 days and you have to pay the 250$ charge cash on delivery when you receive the new phone. Finally, to pour MORE salt on that wound, it won't even work out of the box because you must then drive back to the Fido store and have them transfer the phone number from your old SIM to your new SIM. But the cherry on the sundae is reserved for the Fido employees: as I learned, they don't make any commission on this sale even after working for an hour and a half trying to sort it out and spending an hour on the phone, because it's ultimately completed as a phone order.

How nice. I went with the second option. I'm expecting a package, for which I have no tracking number, to show up in around 10 days, with cash-on-delivery. Sweet.

For the record, the Fido employees agreed this was completely ridiculous, they're just powerless to do anything about it.

I leave you with this piece of news, however: the voice plan I signed up for is a new plan just introduced this week (not yet advertised on their site), and it's fantastic: 17.50$ a month for 200 daytime minutes + unlimited evenings and weekends. I think this is the cheapest voice plan I've ever seen - add 30$ for 6GB of data and you're paying only 47.50$ + fees per month, which is actually really decent. Looking on their website, there's no plan anywhere even close to that cheap that offers unlimited evenings and weekends, so this is a really great deal, I suppose it's a time-limited promotional offer, but I've got it locked in for 3 years now.


Wake-up Call for the Foodie

Or: I fail at omnivorism, apparently.

I know how much everyone hates blog memes that rely on propagating lists, but this one has merit as a device to instill humility in this foodie's psyche and renew my drive for exploration and experimentation. I'm talking, of course, about the Very Good Taste Omnivore's Hundred, a list of 100 foods that's making the rounds right now, billed as a collection of meals any self-respecting omnivore must have tried at least once.

Why am I calling this a wake-up call? Because I just went through the exercise and scored a rather pathetic 56%, forcing me to realize just how little I've really experienced. Try it yourself.

Here are the instructions from the original post:
* Copy this list into your blog or journal, including these instructions.
* Bold all the items you've eaten.
* Cross out any items that you would never consider eating.
* Optional extra: Post a comment here at www.verygoodtaste.co.uk linking to your results.

I'm crossing out Whole insects, Fugu, and Roadkill, so I'm really aiming for a score out of 97. Oh, and the insects thing is probably negotiable after a couple of drinks. I did my counting on Google Spreadsheets, so the following should get automatically updated whenever I check off something new.

Update: ah of course, the iframe won't show up in RSS readers. You have to click to go to the real page.


I just want to post a pointer to Ron Eade's recent blog entry about making kimchi at home. A quick perusal of the instructions reveal it's a fairly involved multi-step process, but overall it still seems simpler than I'd ever imagined.

I buy my kimchi at 168 Market on Somerset, but they seem to only have a single variety and it's not quite as good as what they serve at, say, Seoul House. I've asked around and people seem to only be aware of 168 Market as a source, so perhaps I should try making my own someday - I'd just have to massively scale down the quantities from Mr Eade's typical batch size!


What exactly are Dell and Costco selling here?

Just got a weird little something in the mailbox: a Costco marketing email drew my attention with a rather unusual-looking picture of some Dell machines. I clicked on to the website:

What's Costco Selling?

Hmm, that desktop image sure seems familiar, doesn't it?


Perfect match! Who wants a Dell XPS with OSX? Maybe this is the Creative-Commons-licensed version of Apple's famous desktop image? ;-)



Visa Desjardins' fraud detection

Visa Desjardins has, for the second time in as many months, deemed some of my account activity suspicious. Since they're on the hook, financially, for unauthorized transactions I can understand them having a certain bias towards prudence, but in both cases when I spoke to a CSR, the reason stated was quite vague ("this activity doesn't fit your account's pattern").

I would love to learn (out of personal interest, really, I'm not complaining!) about the decision rules or heuristics that apply here considering the two suspicious charges that were delayed this weekend.

The first is a 25$ renewal of my Flickr Pro account, charged by Yahoo. The CSR said that getting a charge from an online service provider was flagged. Never mind that I've got monthly credit-card charges from my ISP for Internet access, and from rsync.net for storage space, and that my account has, in the past, seen charges from a large gaggle of other online sellers.

The second is even more comical: it's a charge from a gas station in Kanata.

The green placemark is the Esso station where I always fill up, it's at the corner of Solandt and March in Kanata, right next to the office. It was closed this week, so I went to the Shell station instead (the red placemark) 1200 meters away. That got me flagged. Really.


Good Sentences

From The Fishbowl:

In the news this morning, US Department of Homeland Security regulations allow them to confiscate laptops at the border, or duplicate any data, without any suspicion of wrongdoing on the part of the laptop’s owner.

It’s a very timely move by the DHS. You never know when someone might invent a global, unregulated data network that could allow evildoers to entirely bypass such checkpoints, making them nothing more than a sham way for border police to rake through people’s private data and copy their mp3 collections.

The scary thing is I don't really see a way to defend against this. Even if you take the nuclear option and wipe everything, putting it online, and cross the border with a squeaky-clean laptop, there's still a chance your hardware gets confiscated. I wonder if travel insurance would cover seizure of hardware by foreign customs?


I Think Spolsky Missed a Detail About Starbucks Queueing

This week saw the publication of another Inc.com article by the inimitable Joel Spolsky, and as usual it's a fun, geeky read. His ranting analysis of the queueing and order taking procedures at Starbucks supplement a section about an instance of unfriendliness on the part of the staff, which I'll ignore in favour of concentrating on the (more interesting and less Godin-esque) part of the article on queueing procedures and order taking.

Read the original article [http://www.inc.com/magazine/20080801/how-hard-could-it-be-good-system-bad-system.html]; I'm only reproducing a small, relevant portion here:

"Her main job was to go down the line of people waiting to order and ask them what they wanted in advance of their arriving at the cash register. There, they would be asked to repeat their order before paying and finally joining the line of customers waiting for their drinks to appear.

This premature order taking did not appear to improve the store's productivity. The cashiers still had to take the same number of orders, wait for the customers to fiddle with their purses for the correct change, and so forth. The coffee producers -- known theatrically in the trade as baristas -- still had to make the same number of drinks. The biggest benefit of the procedure, I thought, was that the barista got started on a drink a few seconds earlier, so people got their orders filled a little bit faster, even though the overall rate of output for the store was the same.

A network engineer would say this was a situation of 'same bandwidth, lower latency' [...]"

I disagree!

Armchair Psychology

Firstly, I might have a bit of an issue with the claim of lowering perceived latency by reducing the gap between paying at the register and receiving your drink, because I believe I'd start measuring latency when first giving the order, not when paying. Let's ignore that though; Spolsky correctly assumes the early order-taking is useful in preventing customers from giving up and leaving when faced with a long line. This should be no surprise to anyone who's read Robert Cialdini's Influence: The Psychology of Persuasion [http://www.amazon.com/Influence-Psychology-Persuasion-Robert-Cialdini/dp/0688128165] Once we've expressed a choice, painted a mental picture of ourselves as buying a cup of Starbucks coffee this morning, our internal need for self-consistency will force us to rationalize staying, even in the face of long lines. Seriously, read this book, it's an eye opener.

The Benefit of Longer Queues

Ahem, sorry for the digression - back to queueing. Joel states:

"[...] while not even increasing the total number of Frappuccino Blended Coffees that could be produced per unit of time?"

Aha, that's the thing! What's missing here is that the goal isn't to increase the Frappuccino throughput, it's to increase the total throughput across all drinks, and it's absolutely crucial to realize that the drinks are different, and have different preparation times. I think the point of the pre-order taking is to increase the job queue length, and that increasing total throughput by doing this is actually an achievable goal.

Your typical Starbucks counter layout looks something like this in Canada (simplified):


Section A: 2 Espresso machines, steam wands for frothing milk, grinders.
Section B: 3 Thermos canisters of brewed drip coffee: light, medium, dark roast.
Section C: Cash registers, in front of which customers line up.
Job Queue: {DripDarkRoast, DripDarkRoast, Cappuccino, Latte, Cappuccino}

There is no need to view the job queue as FIFO, in fact, it's intuitively obvious that reordering jobs depending on what's available at any moment (out of steamed milk - need to make more, out of ground coffee - need to grind more, etc) should improve the throughput somewhat. Now, assuming you have enough baristas, you can make 2 espresso-based drinks and 1 brewed coffee simultaneously. Maximum throughput will be achieved when all 3 execution units are kept fully busy, which means your drink pipeline should have at least two espresso drinks and one brewed coffee in it to guarantee full utilization after popping the next job off the queue, AND your staff must be allowed to reorder as they see fit. Practically speaking, since pouring a cup of drip coffee takes less time than paying for it, you should have much more than a single drip coffee job in the queue.

So the expediter can indeed cause the throughput to rise - It's clear to me that the job of the expediter is to increase the pipeline length to maximize the chance that all execution units are kept busy. One might argue that this can be done without an expediter, by having the cashiers simply take more orders and queueing them up, but that seems like it would be too much of a cognitive load: in addition to payment processing, they'd be forced to be perfectly aware of what's in the queue, who's busy, which machines are free, etc. The constant context-switching between smiling to customers, counting change, and checking the state of the queue would slow them down, which is why I think it makes sense to offload all of this decision-making to the expediter, who's then free to apply whatever algorithm she chooses in deciding whether to take more orders or pause.

The Smugness Corner

I frequently buy my morning coffee from Bridgehead Coffee in Ottawa, where the barista often sees me standing in line and starts making my usual drink before I get to the cashier to place my order, which results in incredibly low perceived latency. Go Bridgehead.


Performance investigation of Java's select() in Windows

Java has had select()-based I/O since (I believe) 1.4, through java.nio.channels.Selector and the supporting API. While network I/O over non-blocking SocketChannels has been working fine in one of our [Solace Systems'] messaging software platforms for a long time, and at a more than acceptable throughput, I had never really attempted to precisely measure typical timings of Selector.select() and SocketChannel.write(). That is, until this week, when a coworker coding against Winsock2 wanted to compare his timings against what we got doing similar work in Java. What I found was quite surprising...

Test Design

To get an idea of timings, I quickly bashed out your basic "Hello World" of non-blocking-SocketChannel-using applications (which we'll call the client side), that simply streams data as fast as possible to a netcat (nc) instance in listen mode (the server side). In a Java program, we connect to a remote listening port that was created like so:

nc -kl $PORT > /dev/null

Then we register an interest set of OP_WRITE on that channel, log the time offset (System.nanoTime), and select(). Whenever this returns, we log the time and attempt to write an X kilobyte buffer to the socket, then select again, etc. We also log timings for time spent in write() and the number of bytes written in each call to write(). We'll retry this test for several values of X, getting a sense of how much data is copied from our input buffer to the socket's output buffer on each call to write(), and how long it takes select() to return, indicating space in the socket's send buffer.


First, here's the average time (over ~200 or so writes) spent in select():

1K 396011
2K 654
5K 846
10K 1271
100K 9332

First surprising result: The distribution is pretty much what you'd expect for a 100 mbit network, except for the 1K datapoint, which should just have made you spray coffee on your monitor. The 1K writes start off very fast for the first few samples (~500us), then hit a wall and only get woken up every 500000us, yielding a very, very slow transfer rate (2 KB/s). I initially thought this was due to Nagle preventing a small buffer to be sent before a timeout expired, but setting TCP_NODELAY on the socket had no effect on this behaviour. I can confirm using a packet dump that the server end immediately acks every packet we send to it, so it's not a question of the local TCP send window getting full.

The second weird result is that on Windows, whenever you call SocketChannel.write(ByteBuffer), THE ENTIRE BUFFER GETS COPIED OFF AND REPORTED AS WRITTEN. You'd expect it to write only as many bytes as it can until filling up the local TCP send buffer (sized at SO_SNDBUF, which defaults at 8 KB, as we all know), then return that number, leaving the rest of your input buffer to be copied out on the next call to write(). In fact, that's my understanding of the Sun documentation (emphasis mine):

Writes a sequence of bytes to this channel from the given buffer.

An attempt is made to write up to r bytes to the channel, where r is the number of bytes remaining in the buffer, that is, dst.remaining(), at the moment this method is invoked.

Suppose that a byte sequence of length n is written, where 0 <= n <= r. This byte sequence will be transferred from the buffer starting at index p, where p is the buffer's position at the moment this method is invoked; the index of the last byte written will be p + n - 1. Upon return the buffer's position will be equal to p + n; its limit will not have changed.

Unless otherwise specified, a write operation will return only after writing all of the r requested bytes. Some types of channels, depending upon their state, may write only some of the bytes or possibly none at all. A socket channel in non-blocking mode, for example, cannot write any more bytes than are free in the socket's output buffer.

Open Questions (Mystery!)

So, I'm left with two big questions:

1. What's going on with the 1K writes? I tried TCP_NODELAY on that socket (Nagle's algorithm being the obvious culprit when small writes have huge latency), with no change: select() only wakes up once per 500ms. Also, it happens consistently on every single select. Since the local SO_SNDBUF is 8K, even if there was something fishy going on around that 500ms pause in select(), shouldn't you only get blocked for the full 500ms once per 8 writes? I've never seen this happen in a real-world production app though, so I'm willing to chalk it up to a quirk in my simplistic test code.

2. Isn't it a bit strange that write() returns immediately and always reports writing the full buffer under Windows, even if you pass in a 100MB ByteBuffer to be output with an SO_SNDBUF of only 8K? On 2 UNIX systems I tried it on, it still wrote much, much more than the value of SO_SNDBUF, but the results were all over the place, they didn't always match the size of the input array (as I'd expect).


Pimpin' thread dump utility class

When you're looking at your source and wondering "how the hell did I get here? Am I on the Swing worker thread, or...", there's a few things you can do to make finding the answer easier.

You've already looked at the call hierarchy with Ctrl+Alt+H, and you can't figure it out. One approach is to just slap down a breakpoint and restart under the Eclipse debugger, but if you put the breakpoint in a method that's called commonly, and you're instead looking for the uncommon hit, it's going to be really annoying to have the debugger jump up every three seconds and click "nope, nope, next, etc" while looking at the call stack.


So here's the second option: good old printf debugging. Now there's no one-liner (that I know of) in Java to just dump the current stack (You could instantiate a Throwable and tell it to print its stack in like 2 lines, but how ugly is that?), so here's a little utility class (ThreadUtil.java) you can grab:

import java.io.PrintStream;

* Debugging utility class for printing current thread's stack trace.
* To print to STDOUT, just call {@link #printMyStackTrace()}. If using a
* logging framework, instead call {@link #getMyStackTrace()} and log the
* result.
* @author Jean-Philippe Daigle
public class ThreadUtil {

private ThreadUtil() {

* Prints current stack to System.out.
public static void printMyStackTrace() {

* Prints current stack to the specified PrintStream.
public static void printMyStackTrace(final PrintStream out) {

* Gets current stack trace as a String.
public static String getMyStackTrace() {
StackTraceElement[] ste_arr = dumpFilteredStack();
StringBuilder sb = new StringBuilder();
for (StackTraceElement stackTraceElement : ste_arr) {
sb.append("\t" + stackTraceElement + "\n");
return sb.toString();

private static StackTraceElement[] dumpFilteredStack() {
StackTraceElement[] ste = Thread.currentThread().getStackTrace();

* The first few elements in the stack will be in Thread.dumpThreads,
* and in the current class, so we need to skip that noise.
int i = 0;
for (i = 0; i < ste.length; i++) {
String cc = ste[i].getClassName();
if (!(cc.equals("java.lang.Thread")
|| cc.equals(ThreadUtil.class.getCanonicalName())))

StackTraceElement[] ste2 = new StackTraceElement[ste.length - i];
System.arraycopy(ste, i, ste2, 0, ste2.length);
return ste2;

private static String getHeader() {
final Thread ct = Thread.currentThread();
return String.format("Thread: \"%s\" %s id=%s, prio=%s:",
ct.isDaemon() ? "daemon " : "",


How to steal a car

I dropped off my car at the Honda dealership this morning to have them investigate the mysterious Check Engine light that came on yesterday. This post was inspired by what happened tonight when I swung by after work to pick up the car - I'm not chastising them for the security flaw, I mostly just find it charming and cute.

I was there about two minutes, and this is the conversation as I remember it, see if you can spot the tiny flaw:

[I enter the service area of the dealership and walk over to the clerk, then sit down in front of him. A car key is lying on the desk, sporting a little tag with my last name scrawled on it in big block letters: DAIGLE.]

- Clerk: Hi!

- JP: Hi, picking up my car...

- Name?

- Daigle

- Oh yeah, just closing that file now, here's your key.

- So what was wrong with it?

- Coolant temperature sensor failed.

- Huh.

- Yeah, it was under warranty, so you're good to go!

- Thanks, good night!

[I exit the dealership, key in hand, and drive off.]

Human beings are usually the weakest link in any security system :)



This contains a few spoilers, but nothing that would completely ruin the movie for you if you haven't already seen it.

I saw WALL-E this weekend, and overall I thought it was pretty good. I'm a bit mystified by the torrent of comments up on Twitter and in the blogosphere saying it's perfect in every way, the best movie of the year, it's fantastic, etc. It's certainly a great movie, but I wouldn't put it in genius territory quite yet (maybe I need to watch it another time?). I thought The Incredibles and Ratatouille were a bit better overall - we'll get to the big reason why in a second.


I have to admit I really liked the undoubtedly intentional homage to Johnny 5's design (from Short Circuit, which was my favourite movie for a long time as a kid - you could tell even back then I'd become an engineer!). Also loved the Mac startup sound when WALL-E boots up, but that's been covered to death already.


1) The passengers on the ship are referred to as "shoppers", which begs the question of how a population of 8-th generation travelers who don't seem to actually do any useful work can accumulate any assets to spend, and how those assets would have any value when the only trading partner is BNL. There appears to be a completely uniform distribution of "stuff" among the population, so there can be no interpersonal trade or bartering. How is the shipboard economy sustained? I would have loved to see a few hints on what their economy is like; as it is, I think we can just speculate and wait for the DVD with director's commentary. As an aside, I'm trying to think of examples in sci-fi literature of self-contained shipboard economies, and I'm coming up blank. I loved the ideas in Charles Stross' Accelerando, where the ship of (virtualized) explorers has no economy itself (the explorers and their physical environment being nothing more than a simulation), but the characters set up a kingdom which acts as a trust back in the originating solar system, tasked with making enough money to continue powering the ship remotely over decades.

2) Why are they throwing garbage out into space? It seems clear the Axiom ship, which has been out there for 700 years, is intended to function as a self-sustaining system, but if that's the case, they certainly can't afford to be throwing out materials at the rate at which we see them doing so during the movie. The movie does establish that the ship itself commands automated probes like the one that carried EVE, so perhaps we're meant to assume these probes also handle mining for raw materials.

3) The ship lands at the end of the movie, and in scale, it's clear it's much smaller than a large city (it looks like it might be a few kilometers long, if even that). So where is the rest of humanity? My assumption today is that somehow, the lifestyle that led to the extreme consumerism of the race and the destruction of the environment also caused a gradual contraction of humanity's numbers down to a couple thousand, who finally decided to evacuate when BNL provided the opportunity. Again, maybe I missed some key hints, but I didn't see this addressed.

4) How is it that even after seven centuries, atmospheric pollution hasn't died down? Part of the explanation could be that there's no vegetation to absorb any of it, but you'd think even then, over that length of time, the cycle of rain and evaporation would push it all down as water, and everything would end up in the oceans sooner or later, clearing the air. (But hey, what do I know about ecology, I'm a software guy. I'm sure over the coming days we'll get analysis by people who know how to answer this.)

WALL-E after the other Pixar masterpieces

My final gripe (all the above are just fun openings for speculation) is that the moralizing message in this one is quite a bit more blunt and in-your-face than it was in previous Pixar films. This is part of what made them charming, they weren't too blatant with their moralizing. Off the top of my head, I can think of a few 'lessons' imparted on the viewer by each movie, and there's always an obvious unoriginal one, as well as a less cliché secondary lesson. (Remember, this is just my opinion, and I certainly wasn't acing the literature and film analysis courses I took back when I was in school.)

Finding Nemo had the tired, obvious lesson of "you can do great things no matter who you are, accept yourself along with the small imperfections" (the whole misshaped fin thing). It had more interesting, less obvious lessons about the treatment of animals, their natural habitat, and the value of sticking together as a family.

The Incredibles had the best one: "When everyone's special, no one is". This one theme, with Syndrome's jealousy, is a terrific teardown of the stupid, broken, touchy-feely politically correct "everyone's a winner" style of educating kids where somehow, everyone ends up with a prize at the end. Life isn't like that. Your precious little snowflakes aren't all winners. I love that the writers had the guts to put in that line about everyone being special. Its secondary topic, I think, was an examination of what it means to have an unfulfilling life, and though I adored this movie as it is, I've always thought a slightly darker ending, where Bob Parr ends up forced to go back to just surviving in the shadows, would have been more fitting.

Ratatouille? A bit harder to analyze, actually, and it seems the harder the Pixar movies make it to identify their central themes, the better the movie ends up being. Ratatouille was, arguably, firstly about following your dream despite an unsupportive peer group (a bit similar to Nemo in that respect), and secondly about the art and enjoyment of food, and the evilness of commoditizing and commercializing food preparation. Mmmm, tasty. I'm still not sure how the critic fits in.

Finally, we get to WALL-E which is the one I'm most likely to get wrong, because although I've seen The Incredibles something like 8 times, I've seen WALL-E but once. WALL-E hits you over the head with an unsubtle full-throated shout of "stop consuming / wasting so much", etc, etc. I thought showing the indoctrination of newborns in the school/nursery was quite nice ("B is for BNL, your very best friend"), but it was so brief it may whizz right by the youngest children in the audience [this isn't really a criticism, given my opinion about the film's lack of subtlety].

The deception and poor planning on the part of the BNL CEO ("stay the course!") were likewise enjoyable, but not particularly clever or restrained. Showing the human race as lazy, unthinking pleasure-seekers is also in many respects apt, but at this point it's a smidgen tired and overused. (Though WALL-E did it better than Idiocracy, I must say.) The other part of the story worth talking about is the (extremely cutely done) love between WALL-E and EVE, which has the novel property of unfolding between robots, but once more it's a familiar archetype: the dumpy, ugly guy falls in love with the hopelessly beautiful and refined female character who has no interest in him. He persists and eventually gets the girl - big surprise.

It's certainly worth the 10$. Go see it, then come back and comment. I'm looking forward to seeing it another time, and hoping to go "OH! Of course! How stupid I've been!", and changing my opinion about all the above.


A Few Snapshots From Westfest 5

Last weekend was Westfest 2008 (Westboro's annual music festival, in Ottawa), and due to a craaaaazy week at work I didn't really have time to post any snapshots until tonight (although they were on my Flickr feed, if you're following that). Here, enjoy!

It pretty much rained the whole weekend (and every single day this week - ugh!), so I only managed a few pics during a rare moment of sunshine:

^^^ A few concertgoers hanging out

^^^ A hip-hop band out of Manitoba called Grand Analog. They were actually pretty great!

^^^ Their lead singer, trying to rev up the crowd (not completely successful, but oh well)

^^^ I like this couple, they have the same weird hairdo and fit together so well

^^^ The Candy Store, a new shop that just opened up on Richmond Rd. Haven't shopped there yet. (I'm not really a sweets and candy kind of guy - I'm sipping a blended nectarine/tofu shake as I write this.)

^^^ This kid was hilarious, more on him in a second

So here's the story: the boy was in the American Apparel boutique, and being rather small and questionably behaved, he managed to sneak right into the display case. He then - and I am not making this up - started caressing the legs of the female mannequins. Then, he started pulling on clothes, on both the male and female mannequins.

The depressing part of the story (for me) is that in a five-minute span, two different women asked me if he was my son. Ouch. To think that I'd have a kid already - that's a huge, depressing, dose of "you're not getting any younger". Maybe my youthful good looks* are increasingly a thing of the past.


*: Just "youthful looks" might be a bit more truthful, but who's counting ;)

Java Devs: Gear Up! (a Shout Out to adaptj and tda)

Found an awesome tool today that I never knew existed, and it blew my mind. It's called StackTrace, from adaptj. There's a free version you can launch using Java Webstart (JNLP). This thing is awesome at solving one small, but all too common problem: being unable to get a thread dump in a running JVM because you don't have the console that launched the java process. (Imagine someone on your QA team calls you up, and says that his nightly build of your app locked up - you ask him three questions: Did you start it with remote debugging enabled? no? Then did you enable log4j logging? no? Did you keep around the console that launched it? Ah, no again, of course. At this point you're usually screwed. But not anymore!)

It looks like this:


When you start up StackTrace, click the little gear icon or go to Process > Select... and you get a list of all the java processes on your system. Select the desired one, click OK, then back on the main screen hit the "Thread dump" button.

Boom. Instant thread dump of everything in that JVM instance. THIS. IS. HUGE.

Second little discovery of the day is called tda. It's a thread dump analyzer that will open up a saved stack trace and show you exactly which threads own which monitors, and speed up a bit your task of slogging through pages and pages of stack traces. Give it a try:



Is Bell's Torrent Throttling Sucking Less?

n.d.a.: My ISP is 295.ca, which is a DSL reseller affected by Bell's torrent throttling.

Screenshot taken at 16:30 today from a terminal window, late afternoon being in the time period where torrents are normally getting throttled down to around 25 k/s:


185.9 kB/s! (Sure, not great, but for a throttled connection during peak hours this is acceptable.)


A Lifesaver for Multi-Monitor Users

If, like me, you're used to spending a lot of time in KDE on Linux, trying to move windows around on a large desktop (such as in a multi-monitor setup) on WinXP can be pretty frustrating because there's no native support for KDE's ALT+DRAG method of moving windows.

KDE supporting this is a very Good Thing. Fitts' Law predicts the time required to move a cursor to a target area as a function of the target's size and distance from the current cursor position. It implies that a very large target, close to the mouse pointer, will be much faster to access than a small one, especially if it's further away.


This explains why it's comparatively hard to move a window under Windows: the cursor has to move from its current position all the way to the top of the window to be moved, which is a wide but not very tall target. KDE's usability improvement is to allow the user to hold the ALT key, and click anywhere within the window, then drag it to a new location. [Which can even be to another virtual desktop, but lack of support for that in WinXP is another stupid annoyance that we'll complain about another time.] This makes the target area as large as the window, so you don't really need any fine motor skills, and the distance to target is often zero, because your pointer is already there.

So here's what I came online to post about: howtogeek.com posted an AutoHotKey script to enable this functionality in Windows. I've been running it for 3 days now without issues, so I'm giving it the thumbs up. Get it now.


The Economics of Consumer Photo Printers: Only Good for Homemade Porn?

I just remembered that I meant to print out something at work today, and it's 11PM and I don't own a printer, so it's not happening today. But it got me thinking about laser printers, so I looked up a few on costco.ca and bestbuy.ca.


Checking out the laser printers, I saw a bunch of those little home photo printers, like the Canon Pixma series, and I got curious: how did the total operating cost of those things, once you factor in ink and photo paper, compare to my current solution: photolab.ca?

Are my Intuitions any Good?

Intuitively, I figured that buying your own printer and consumables would be expensive up front, but pictures would have a lower marginal cost, so once you amortized the cost over hundreds of prints, you'd eventually reach a break-even point after which owning the photo printer was the cheaper option. I did a bit of investigative work to try and locate this break-even point. Foreshadowing: my intuitions can be waaay off the mark.

Photolab's up First

First, the photolab.ca approach. The cost is exactly 0.19$ per 4x6 print (it drops to 0.15$ if you order >100 at once, but let's ignore that and assume we're printing small batches every week). You then pick it up at a Loblaws or Superstore and pay on reception. I've used them and found the quality to be great [if you're in the Solace offices, all the pics you see in my cube are from there].

Buying a Pixma MP620

Next, let's choose a Canon photo printer to compare against. Best Buy has a few cheaper Pixma units, but they're all end-of-lifed and the Canon website doesn't sell ink anymore. Cheapest current-ish one I found is the Pixma MP610, which looks like something I'd buy, and goes for 129.99$.

Canon sells the 3-colour CMY cartridge pack for 64.99$ (site is not linkable, it's called "CLI-8 Colour Combo w./ PP-101 4x6 50 SH PK"), rated for 280 pages of letter paper at 5% coverage. In terms of surface area, a 4x6 print is equal to 0.2567 pages of letter paper, but since you're printing border-to-border instead of sparse text, you'll need 100% ink coverage. We can thus estimate that the cartridges will give us 54.542 4x6 prints, which is handy because coincidentally, the box includes 50 pages of 4x6 photo paper, so let's round that 54.542 down to 50 to account for the waste from cleaning the heads. This makes our cost per page 1.30$ per 4x6 print. On top of the cost of the printer. That's not a typo.

Comparative Results

Now you know where this is going, but I thought it would be extra fun to graph these costs (assumes the cost-per-photo is evenly amortized, in reality the blue line would be a staircase curve):


And here's what it looks like if a sales guy were to walk over and GIVE YOU THE PRINTER FOR FREE:


I think the conclusion we can draw from this is that the premium for home printing is huge, so I suppose it would only be worth it if:

  1. You regularly have a very pressing need for printouts and can't wait 24 hours for the lab to process your order, or
  2. You wish to get your printouts without an anonymous technician seeing them - wink wink nudge nudge.


Random Notes from DemoCampOttawa9

All right, I want to jot down a few comments about DemoCampOttawa9 before I go off to bed. Now, I'm a software developer. I'm not a startup entrepreneur, nor an investor, nor someone in any way qualified to comment about how insanely great or ridiculously and laughably stupid a business idea is, so I'll just stick to talking a tiny bit about what I saw tonight. Oh yeah, the pics are up on flickr right here if you're interested, the license is Creative-Commons, and sorry about the wacky colours, it was your typical low-light restaurant / bar room.

DemoCampOttawa is a semi-regular series of meetings where members of the Ottawa high-tech community can go up on stage and show off hardware, software, services they're working on.

First, a big congrats to Alec Saunders for being a smooth and lively host. A nice thing about this evening is that no one that presented was a slick, practiced, PR person - every single presenter was a techy, and that made for an accessible, informal feel.

First up was a presenter from SIMtone. From the demo, they basically seem to rent you a WinXP virtual machine running in a datacenter. You don't just connect over RDP however, they provide a light Java client that runs on very modest hardware that can give you access to your VM instance. The presenter didn't have time to explain how they balanced the hosted VMs across physical boxes, or how much CPU and bandwidth you're allowed to use, etc, but he was accessing it over WiMax and it seemed to work OK. [note: we have WiMax service in Ottawa???]


We got an engineer who implemented a GPU on a Xilinx FPGA. He had it running live on a demo board, but didn't go into much detail about whether he was generating the video signal himself too or if he had much extra hardware on there to do that, etc.

This is Richard Mayer from Protecode. He demo'ed an interesting Eclipse plugin and associated web service that fingerprints external code added to your development projects and tracks the licenses under which it's distributed. It seems the big value here is in the massive database of publicly-distributed code they've built up. Their software can identify not only third-party libraries and source files added to a project, but small chunks of code pasted in as well.


Martin demoing Stockify, a web app for evaluating value stocks. The app looks at historical P/E ratios and earnings growth of public companies.

And finally, Joel and Pascal from picsphere, which makes workflow-management software for event photographers. We've seen plenty of photo-workflow management apps before, but this one seemed to have novel ways of importing the pictures, keeping them tagged by subject, and allowing instant sales at the point of capture (from what I could see in the demo). They were pretty cool because they really didn't project the condescending elitism you usually get from everyone in the photography industry, they felt more like purveyors of software for a more regular-guy, amateurish market (and probably a much larger one, IMHO).

Phew, that's it. I'll surely attend the next meetup, this was overall an interesting night.


Does Google Desktop Search Have Selective Memory?

For frequently used applications, I have shortcuts (that get indexed by Launchy) and/or aliases set up in SlickRun, which are both fantastic little productivity enhancers.

When it comes to infrequently-used programs, however, I don't have shortcuts to them so I prefer to just use Google Desktop to search for the filename and click the first hit [essentially, I want to use Google Desktop as the 'locate' command under unix]. Sometimes though, it doesn't find what I'm looking for, even though IT'S RIGHT FRACKING THERE ON THE DRIVE:



You might start thinking: "Aha, it just doesn't index filenames in .exe" (even though that would be awfully inconvenient), but that wouldn't be true either:



My tech isn't working the way I want it to tonight. When will I start winning?



This coming Monday (May 26th), there are two events in Ottawa, both starting at 19:00 :
  • A showing and then discussion panel on "The Story of Stuff", presented by the Sierra Club Ottawa. The panelists include Tracey Clark, who's the managing director of Bridgehead coffee shops. I'd really like to sit in on this.
  • DemoCampOttawa9, the tech event of the month for the Ottawa tech community.
Hmmm. I think I'll probably end up going with the nerds instead of the hippies, but this is one of those nights I really wish I could be in two places at once.


Non-Reciprocal Recognition

Confession: I see people. They recognize me. I don't recognize them.
They'll remember me, I won't.
sucks to be me


A snack-sized bite of Java for tonight

With Java autoboxing, always pay attention to what your primitives get boxed into.

Here's an easy little bug to introduce if you don't pay attention: consider these methods of the Map<K, V> interface:

V put(K key, V value)
V remove(Object key)

So you put a value into a map, and remove it. Easy enough.

Pop Quiz

So what does the following return?

public static String test() {
HashMap<Long, String> map = new HashMap<Long, String>();
final long some_key = 1;
map.put(some_key, "foo");
return map.remove(1);





Answer: null.

This is why it's important to remember the definition of the put, get and remove methods. While the generified [nda - yes that's a word, according to the Sun docs] flavour of put(K, V) ensures the key is an instance of K, for whatever K you declared for this generic map, the get and remove methods weren't generified and simply take an Object. This can bite you, as in the above function, where autoboxing essentially caused the following calls to happen, though it probably wasn't the programmer's intent:

    map.put(new Long(1), "foo");
map.remove(new Integer(1));

Even though Integer(1) and Long(1) have the same hashCode() value, they fail the equals() test, so key lookups when using the wrong wrapper class will always fail. The fix, of course, is to declare your keys as the right type when calling get() or remove(), and be careful, as the method signature will allow anything to be passed in, so you'll never know at compile-time you got it wrong.


Happy coding!


Rogers vs Bell

So I was hanging out with a friend (who will remain nameless for reasons you'll see very soon) a while back, and I saw his new BlackBerry Pearl:

- So, you got a BlackBerry, huh?

- Yeah man, it's great!

- How do you find the Bell network?

- Actually I'm with Rogers. Cheaper.

- ...

- ...

- Dude, YOU WORK FOR BELL, don't you get service for free or something?

- Nope, it's still cheaper with Rogers


I was floored! If this isn't a great endorsement of Rogers Wireless, I don't know what is. (Yes, I know their data plans still suck, but it seems they "suck less" than the alternatives.) I can't imagine what it must be like working for a company that would treat its employees so poorly they'd sign a service contract with their biggest competitor.


Argh! Missed it!

Totally non-techie post today for food geeks: it seems that La Bottega in Ottawa received a single Spanish jamón ibérico last Friday. I missed my chance to buy a few slices, reading about it only after the fact on Ron Eade's (the Citizen's food editor) blog, which I was only recently made aware of. Damn.

It is easy to underestimate the significance of this news item, but thankfully, in his video post, Eade reminds us that this is quite notable, as it is the first time jamón ibérico (made from pasture-fed black pigs of certified race) is available in Ottawa. In fact, until 2005, it was illegal to export it to North America, and since the ham must cure for three years before being ready to sell, it's only now starting to appear on our shores, and is a tad expensive (La Bottega was moving it at 200$ per kilogram).


[sure, I paid 30$ CAD for the plate above last month but look at that marbling!]

Ottawa food enthusiasts have no doubt noticed that much cheaper (but still delicious) jamón serrano has been available in local food shops for a while now, which is made from white pigs with less restrictions on feeding.


Is Deploying a Wireless Network More Secure Than Not Deploying One?

Yes, I think it is. Long-winded explanation follows.

Me: I'm a guy who loves to work on a laptop. I've owned my little Thinkpad since 2004. I have dragged it between Ottawa and Montreal dozens of times, hauled it through Spain and the United States while vacationing, it's been through several coffee shops in Ottawa, and even tonight, with three other computers in my apartment much faster than this one, I'm in the living room, writing this post on the faithful machine. If you call me up and need help with a build script or a complicated subversion operation, I'll run over to your cube with it and we can hack on the problem together, each on our own screen. Or anyway, I would if there were wireless network access points at the office.

Which there aren't.

(Yes, I'm well aware of the irony of working for a company that makes network equipment. No need to point it out.)

The subject came up on Friday evening, as a bunch of us engineers were sitting around having a beer before leaving for the weekend. Someone (I swear it wasn't me this time) wondered out loud why in this day and age, we didn't have wireless APs at the office. Asked our CTO: "Why don't we just drive to Futureshop and spend the fifty bucks?"

I suppose it's always been a "nice to have" feature of the office, never a true requirement, and commercial-grade WAPs are more expensive than the consumer versions from Linksys. I've also heard mentions that there might be concerns about the security of the setup, given that we lease a floor on a building housing a bunch of other companies. I realized after the discussion, however, that the security argument was bunk, and having no WLAN could actually put us at much greater risk than having one.

It is an oft-repeated saying in security discussions that humans are often the weakest part of a security system. In his book Secrets and Lies, security guru Bruce Schneier again reminds us, as he has before, that an inconvenient security system is self-defeating because humans will simply end up not using it. In Chapter 17, he relates this story:

It has been said that the most insecure system is the one that isn't used. And more often than not, a security system isn't used because it's just too irritating.

Recently I did some work for the security group in a major multinational corporation. They were concerned that their senior management was doing business on insecure phones - land lines and cellular - sometimes in a foreign country. Could I help? There were several secure-voice products, and we talked about them and how they worked. The voice quality was not as good as normal phones. There was a several-second delay at the start of the call while the encryption algorithm was initialized. The phones were a little larger than the smallest and sexiest cellular phones. But their conversations would be encrypted.

Not good enough, said the senior executives. They wanted a secure phone, but they were unwilling to live with inferior voice quality, or longer call setup time. And in the end, they continued talking over insecure phones.

This is exactly the risk that an office takes by not deploying secure, properly configured WAPs managed by the IT team. Wireless networks are a convenience for many. There are some (albeit still rare) laptops appearing that don't even have a network jack anymore; and this is just the beginning of that design trend. Sooner or later, someone will get fed up and install a rogue access point, connected to the corporate LAN, and quite possibly insecurely configured and allowing routing to every resource on the network. It may already have happened. Wishfully thinking otherwise is simply ignoring the human part of the equation, hardly good practice of security.


A Firefox Search Plugin for the Ottawa Public Library

The Ottawa Public Library has a very neat service where you can look up a book online, request it to be delivered to whichever branch is closest to you, and be notified by email when your the chosen tome is available for pickup. If a book is already checked out, you can simply request the next available copy to be delivered.


Seeing how I do quite a bit of reading these days, I set about creating a Firefox search plugin to easily search their catalog. In truth, I just wanted a quick way of looking up a book in the library catalog when I'm on Amazon.ca or I read a book recommendation on a blog.

Installing this search plugin

  1. Navigate to your Firefox profile directory (%APPDATA%\Mozilla\Firefox\Profiles\whatever).
  2. If it's not already created, create a new folder called "searchplugins" (without the quotes).
  3. Copy this file (ottawa_public_library.xml) to the searchplugins folder, then restart Firefox.


It's dead simple. Open the search engines drop down menu and choose the new "Ottawa Public Library" option:


Now type in keywords from the book's title and hit enter:


This plugin does a search using the "Keywords in TITLE" option, as I thought that was the most useful. Hope you find this useful! Tell your geeky friends!

Edit: ah yes, I forgot to say, the XML file includes a copy of the library's logo, taken from their favicon.ico file. I haven't asked the city of Ottawa for permission to redistribute the icon, but I'm quasi-certain it wouldn't cause a problem. If I get complaints I'll put a new icon in there.

Another update: There's been some interest in this, so here's an easier way to install: Click here to install the Firefox search plugin for the Ottawa Public Library


Resolved: Boingo Refunds Their Double-Charge

A couple co-workers have been asking me for an update, so here...

Last weekend, I wrote a post (link) about how after logging on to the Boingo wireless service from two different airports on the same day, I was charged twice despite having purchased a 24-hour pass. At that time, I contacted their phone service, where a customer rep explained it was normal, and advised me to read the user agreement next time.

Luckily, I didn't have to do a credit card chargeback; as a result of my blog post, I was contacted by Boingo's PR firm, and apparently the phone rep I talked to was incorrect: what happened was simply a software glitch. They've refunded the second (erroneous) charge, so it looks like this was just a one-off problem, and not the shady business practice I initially suspected. Phew! All is now well.


Read Jason's post about Stat(CVS|SVN) if you care about repository analysis

My good friend Jason, one of the two talented developers that form micro-ISV LavaBlast Software, just put up a post about exciting happenings in the StatCVS and StatSVN world. Although I'm no longer really involved with those projects, I'm happy to see these developments, and want to give a kudos to guys like Jason Kealey and Benoit Xhenseval and all their collaborators for all the great effort they've put in.

As for myself, I'll be involved in more SVN-related tooling projects in the coming months, but I can't talk about that just now... :)

I need to reply to Jason's conclusion about coming back to Java development, though, especially the note about explicitly creating Integer objects:

"Personally, I enjoy loading up a recent version of Eclipse and working in Java once in a while because it helps me observe the best in both worlds. I much prefer coding in C# because of the easier string manipulation and the fact that everything is an object so you don't have to explicitly create an Integer object from your int to insert it into a collection. However, when working in VS.NET, I dearly miss the automatic incremental compilation feature that Eclipse runs when you save a file."

If it's been a little while since you've looked at Java, know that J2SE 1.5 brought a lot of great improvements especially in the Concurrent and Collections namespaces, as well as new language features. One such usability improvement is known as autoboxing, which means basic numeric types like int or float are automatically "boxed" into their object containers (Integer, Float, etc.) when required, like when adding an element to a collection, and "unboxed" when the native type is required. Just thought you'd like to know, Jason ;)

[It goes without saying that you should always be mindful of the performance impact of creating a bunch of temporary objects like this! Operations on Integers are always going to be slow-ish because they're immutable, and new objects are created for every value you use.]