jQuery.live("click") Gotcha

If you're using the new jQuery.live("type", fn) handlers in jQuery 1.3, be careful with the "click" event type.  Unlike jQuery.bind("click", fn) and jQuery.click(fn), jQuery.live("click", fn) doesn't distinguish between mouse buttons.  So while the "normal" handlers will only trigger when the left button is used, the live handler will trigger on any button.

The workaround is pretty simple, though kind of kludgey: add the stuff in bold to your handler.

jQuery("#selector").live("click", function(event) {
  if (event.button != 0) {
    // wasn't the left button - ignore
    return true;
  }
  // do some stuff
  return false; // "capture" the click
});

Hopefully this will be addressed in the future, but for right now you have to pick between manual button detection and sticking with the "normal" handlers.

CSS Naked Day

It's CSS Naked Day again, at least on the East edge of Earth, but we'll soon catch up.  Strip your <BODY> for the world!  After doing it manually the last couple years, this time I'm using the excellent CSS Naked Day WordPress Plugin by Aja Lorenzo Lapus.

Ben Nadel – At It Again

Ben Nadel posted another interesting code snippet this moring.  I think Ben and I stand in agreement on the technique: NEVER EVER USE IT.  It leverages a horrible bug in ColdFusion's implementation of struct literals that I've blogged about previously.

Here's the snippet:

<cfset objConfig = {
  root = getDirectoryFromPath(getCurrentTemplatePath()),
  tags = objConfig.root & "tags/",
  com = objConfig.root & "com/"
} />

Yes, that actually works.  Let me repeat, NEVER EVER USE IT.  It is the devil incarnate, and only works because of a horrible implementation error in Adobe ColdFusion.  Note this is a ColdFusion bug, not a CFML language issue.  Railo implements struct literals correctly (as well as treating them as expressions instead of statements).  I don't know about OBD – the last time I used it there wasn't struct literal support at all, but it's been a while.

Show Me Your Tool

If you read my blog regularly, chances are you write software and therefore can't, because your tools don't exist in the visual world.  They're just magic strings of minuscule magnets on a rapidly spinning chunk of plastic…

I took my chef's knife to the sharpener a few days ago.  Cost a whopping $4 to have him put a wicked edge on it, and I watched it happen.  I saw him carefully run the blade along a belt sander (for lack of a better term) a few times to give it the rough shape, then he used a bench grinder to finish the edge, a steel to hone it, and finally a jeweler's wheel to polish it.  Not five minutes elapsed before he handed it back to me, wrapped in butcher's paper for the journey home.

If he let me loose in his shop, there's no way I could have achieved the same result.  But given ten knives, I bet I could get a pretty good edge on the last few (after undoubtedly destroying the first couple).  Nothing like his result, to be sure, but significantly sharper than the initial state.

Sharpening a knife is a pretty simple task, because a knife is an inherently simple item, but it's just one example.  Consider a master furniture maker.  He can take the same wood you and I buy at Home Depot or Lowe's and with his tools and expertise turn it into a beautiful bureau or armiore.  Turn me loose in his shop and I'd probably be able to make a functional dresser in twice the time it'd take him to make an exquisite one.  With some more experience, both using the tools and in furniture construction overall, I've no doubt I could make something I'd be proud to have in my home.  It wouldn't be the same quality as something the master craftsman created, no question, but better than the prefab stuff you might otherwise buy.

So what's special about these tasks?  Nothing, really.  Most things are of a similar nature: cooking, playing music, grooming dogs, surfing, etc.  Attaining mastery of a given profession requires certain in-born characteristics, but attaining laudable proficiency is pretty much available to anyone willing to put in the time (barring physical disabilities and such).

Every chest of drawers provides a way to organize and store clothes.  People spend a lot of money on well made dressers that are made of pretty woods, appeal to their personal tastes (mission, contemporary, etc.), or are simply of a higher quality of manufacture.  None of which has the least to do with holding clothes.  Every dresser I've ever seen holds clothes with about equal proficiency, but even though the drawers are a bit sticky, I still use the one I had as a child.

Now consider software development.  The tools are invisible.  The process is invisible.  The result is intangible.  As far as a profession for a craftsman goes, programmers are fucked.  Sure, we get paid because people are willing to pay for the benefits of our software, but it's 100% functional.  No one buys software because it's well made or "pretty".  They might pick between two vendors because one is less error-prone, but that's still functional.

Every database application provides a way to organize and store data.  No one spends extra money on a database system because it was made with snazzy buttons, appeals to their sense of style, or was produced by a higher quality process.  Every database system I've used is inconvenient in one way or another (no OFFSET, no CTEs, etc.), and every one is built using some completely opaque process by unknown automatons in some office building somewhere.

It has occurred to me that the reason for this could simply be that programming is so damned hard it can't be automated.  As a result, there's no way to produce the gradations of craftsmanship that you see in dressers (from the mass-produced pressboard affairs to the hand-crafted hardwood masterpieces).  With software all you get are the hand-crafted versions.  Sure, some of them are simply horrible, but they're all hand-crafted.

Which brings me back to the point: programming is opaque for everyone that isn't also a programmer.  There's absolutely no way you can take your average Joe, sit him next to you while you write something, and then give him your workstation and have him do the same.  Unlike the furniture maker where a simple demo is enough to get the gist of what is happening, with software it's all abstract and divorced from anything tangible.  My mom (who is fairly technically adept) doesn't have any idea what the hell Subversion is, and even if I sufficiently explained it, there's no way she would understand how massively beneficial vendor branches are.  Heck, a lot of programmers don't understand vendor branches.  And yet a one-year old can run her fingers over a piece of wood and tell you if you need to keep sanding (if not run it through the planer again).

Further, there's absolutely no way Joe (or my mom) can look at two pieces of software and compare their "quality" on any meaningful level.  He can make distinctions like "this one crashes more", or "that one has confusing icons", but that's it.   Even a competent programmer looking at a piece of software has the internals almost completely hidden from them.  Very careful observation can provide certain clues (the query optimizer must be making decision X based on inputs A, B and C), but by and large, everything is opaque.  Again, contrast this with a fine bureau where you can see the carefully planed wood, the perfectly matched dovetail joints on the drawers, and the complete lack of any visible fasteners.

I certainly consider myself a craftsman.  I hope to justify calling myself a master someday, but today is not that day.  And yet every evening, as I'm walking out the front door to head home, I think to myself at how completely impossible my work is to appreciate.  My kids ask what I did today, and I have no meaningful answer to give.  The best I can do is "fixed some bugs", or "had an architecture meeting".  I can't explain to my non-programmer friends what I do, or why it has such appeal.  I live a dual life: a "normal" one and a programmer one.  They are as compatible as fire and ice.  I greatly enjoy the praise and criticism I receive from my peers regarding stuff I share, especially when it helps make others' lives easier, but I'd trade it all to bring something home from work one day, show it to Lindsay and Emery, and have them say "Wow, Daddy, that's amazing."

Firefox Spellcheck for Programmers

No, it doesn't exist, but shouldn't it?  I've found that when I write prose in Firefox, I almost invariably ignore the redlines.  Why?  Too many false positives.  Technical prose, which is usually what I'm writing,  is littered with domain-specific terms that no spellchecker will ever consider valid.  Obviously you can help your specific spellchecker by adding words to the dictionary, but that can be a lot of work, and seems like it could easily be automated.  Why doesn't someone do this?

And no, this isn't a Firefox-specific issue.  But probably 85% of my prose is drafted in Firefox, and most of that remaining 15% is drafted somewhere that doesn't have redlining (iPhone, Outlook, etc.).

TurboTax For the Win

Every year I'm blown away by TurboTax's web version.  It's one of the few applications that is really a pleasure to use, and while I can't say doing taxes is any sort of enjoyable, the sting is greatly removed.  So once again, cheers Intuit.   Keep it up, we appreciate it.

No More AdSense

Tonight I removed my Google AdSense ads from my blog.  I installed it last April as an experiment, intending to leave the ads up for one month.  After a month I never took them down, but the results were about what I expected: virtually zero income.  Now, a year later, I just canceled my AdSense account with a total earnings of … wait for it …  nearly thirty dollars!  Goodbye ads!

I'll be at cf.objective()

In addition to speaking at CFUNITED later this summer, I just registered for cf.objective() this afternoon as an attendee.  This will be the first time I've gone to that conference, but I've heard very good things about it.  CFUNITED has grown into a bit of a behemoth, and while that carries a number of advantages, it'll be nice to go to a smaller conference with a more advanced focus, especially without the pressures of speaking.

xkcd Stuff

I just ordered some goodies from xkcd which should arive in a week or two: a couple t-shirts and a signed print of the Discovery Channel comic.  Unfortunately the store doesn't accept code (my favorite way to pay for zero-cost items), but I'll happily shell out a few bucks for all the entertainment if that's my only option.

Remember, just because it's free doesn't mean it's devoid of value.  Pay for stuff!  Be creative!

Mathematic Constraint Deduction

I did  Project Euler's problem 63 last night, and it was a good one:

The 5-digit number, 16807 = 7^5, is also a fifth power. Similarly, the 9-digit number, 134217728 = 8^9, is a ninth power.

How many n-digit positive integers exist which are also an nth power?

I love this sort of problem.  The algorithm for a brute force solution should be quite obvious: loop over bases and exponents, do the exponentiation, and see how many results' lengths match the exponent in question.  But the question is what the loop constraints are.  For this particular problem you can just write the loops, have them spit out answers, and then hit CTRL-C to terminate when the search stops finding results.  But that's cheating.

Once you get the constraints, writing the code is trivial.  What I couldn't figure out is how to compute the answer without the loops, though it seemed like that would be possible.  After getting the right answer with the scan/check method I read down the forum thread and someone had done it.  The proper loop constraints get you about 50% of the way, and I'd gotten another 30% of the way there, but couldn't quite get all the way.  I still have trouble applying logarithms correctly when stuff gets complicated.