Monday
May292006

rewiring lamps

Tonight is going to end badly if I don't find some electrical tape, and fast!
I have a great ikea lamp with six halogen bulbs, but something went wrong with it: whenever I turned it on, with a little step-on switch, both of the cats immediately go stare at it. Noses less than an inch away, two large cats, staring intently at a motionless piece of black plastic. When this became repeatable, I decided the switch was bad, maybe emitting high-frequency noise or a smell I couldn't smell, and that the lamp would have to go. I really like the lamp, though. So this evening I got out my tools, snipped the cord before and after the switch, then opened up the switch. (Yes, dear parents, it was all unplugged.)
I discovered the switch was just a simple rocker, and a single cat hair was inside the mechanism, touching one of the contacts and the live side of the switch. Aha! The cat hair was conducting a tiny tiny bit of electricity, and it was heating up a tiny tiny bit, enough to make a tiny smell that only cats can smell.
This light actually plugs into an outlet with a switch of its own, so I don't need a switch; I just need to reconnect the two ends of the cord, where the switch used to be. No problem, just... oh no! where's the electrical tape?
I do not have any electrical tape in the apartment. I've got velcro and gorilla glue, but I left my electrical tape behind in Providence and haven't needed any since. My WRONG BAD DON'T TRY THIS AT HOME impulse is to make the splice without electrical tape. Thus the thought:
Tonight will end badly if I don't find some electrical tape, and fast!
I could drive to the all-night everything store and pick some up... but clearly what I really need is to hit the home depot and stock up on electrical tape and duct tape, and replace that utility knife I accidentally gorilla-glued closed last weekend. And, um, what other hardware tinkering stuff am I missing? Maybe this calls for a trip to Fry's!

Sunday
Apr302006

my addendum to Getting Real

When working evenings and weekends, do the fun stuff.
Your tool suite (applications, languages, processes) should vary in a punctuated equilibrium. Make the changes to your tools when you are in a relative lull. Resist the impulse to learn a new tool when your current project is nearing completion, or, worse, when it's nearing a deadline but not nearing completion.

TextMate really does have some fantastic XML indentation syntax highlighter, but will it really help get the project done any faster or better?

An urge to switch tools is often a signal to me that I'm bored or disappointed with my performance.
Try a non-work treat, like that new Flaming Lips cd you've been eyeing, or a few fresh strawberries

If the sun hasn't been out in a while, and it appears, go experience some sunshine. If the sun's out all the time, make some time to sit in the sun.
Sunblock is crucial; don't bring your laptop.

Reading academic research papers and textbooks require sustained, focused attention, which is impossible if you're within ten feet of your computer. Leave the laptop at home and get some work done for once.
Skim giant technical books so that you'll know where to look when you need particular information.
Don't try reading Unix Power Tools cover to cover, but do flip through it, or you might never know what sed can do.

If you're lucky, you work with people who are smarter than you, faster than you, write cleaner code, know more languages, have more experience, etc. Your tendency may be to compare yourself to them, and come off poorly in the comparison. Try this, instead: "Thank god I work with people who are smarter than me, because otherwise I'd be working with people who are stupider than me, and that would suck."
People who are literally geniuses are used to being geniuses. They probably don't think you're an idiot, because they're used to being smarter than everyone else.

Identify particular characteristics of your most effective teammates, and emulate that characteristic.
"Be like Pablo: refactor aggressively." "Be like Scott: keep the codebase tidy, but not obsessively so."

It is almost always a good idea to go for a little walk. (Thanks to Josh Carroll for this gem.)

Saturday
Mar252006

Flickr in Open Laszlo

Working on the Open Laszlo LZPIX multiple runtimes demo made me fall in love with data-binding in lzx. LZPIX is a flickr browser written in Open Laszlo, which can be compiled as a DHTML app or a Flash app. To share the data-binding joy, I wrote a little flickr browser (requires Flash Player 7 or later) and annotated the application code.

rubyonrails.org has a really cool screencast showing how they built a flickr viewer in five minutes with, of course, Ruby on Rails. That screencast inspired me to get a Rails environment set up on my mac, so I'm following suit with a similar Open Laszlo app in the hopes that I'll inspire more developers to give Open Laszlo a test run. I'm not trying to argue that Ruby on Rails is better or worse than Open Laszlo. Consider this article as "imitation as flattery" not "competitive analysis."

Open Laszlo is a great platform for mashups. (marketing-speak: Open Laszlo is a great platform for building rich internet applications using third-party REST web services.) OL has data binding and replication built in. The results of an xml query (a "dataset" in OL) can be mapped directly to elements in the OL scene graph (the "canvas" in OL). Attributes of elements in the OL scene graph can be mapped from attributes of the elements in the dataset. The data replication manager creates views to represent each result of a query to a REST api.

I've used a simple wrapper for the flickr api, written by Elliot Winard. For this article, I'll write from the perspective of an application developer using this existing api. libflickr defines a class, photo, which is a thumbnail view of an image in a result from a flickr query.

OL is tag-based and requires well-formed XML, so I start off my lzx document with a single root element, canvas, and include the flickr library:
<canvas title="Flickr on Open Laszlo">
<include href="incubator/libflickr.lzx" />

To access flickr, we need an api key. I define a global attribute with the value of my api key. Get your own from flickr
<attribute name="myapikey" value="xxxx_GET_YOUR_OWN_xxxx" type="string"/>

At first I just want to view some flickr data without worrying about how I got it, so I'll just use this little stub that kicks off a simple query when the canvas initializes. I call the method "getRecent" on the gFlickr node, which is global. I pass in my api key as an argument to the request.
<method event="oninit">
gFlickr.getRecent(canvas.myapikey);
</method>

Add a view for the search results, containing its own layout:

<view name="results"
x="10"
width="${parent.height-20}" >
<!-- The wrapping layout arranges the search results in a grid, and
starts a new row ("wraps" the contents) when the contents fill each row.
This gives grid-like behavior without scaling the subviews.
-->
<wrappinglayout axis="x" spacing="5" />

<!-- Data binding is so cool. This element says, "make an instance
of class coolphoto for the first ten nodes in the dataset "photods" with
"rsp" as grandparent and "photos" as parent.
-->
<photo datapath="photods:/rsp/photos/photo[1-24]" />
</view>

That's all it takes. The app now displays see a grid of photos recently added to flickr. (Here's the code so far)

Now let's enhance it. I want some more interesting searches, so I'll add a few buttons to control the search:
<view
x="10">
<!-- Within this view, put the subviews in a row. -->
<simplelayout axis="x" spacing="5" />

<!-- Label the search field -->
<text y="5">Search Flickr:</text>
<edittext name="tagQuery" text="lzpix">
<method event="onkeyup" args="kc">
if (kc == 13) gFlickr.searchWithTags(this.getValue(), canvas.myapikey);
</method>
</edittext>

<button onclick="gFlickr.searchWithTags(parent.tagQuery.getValue(), canvas.myapikey)">
go
</button>
<button onclick="gFlickr.getRecent(canvas.myapikey)">recent</button>
<button onclick="gFlickr.getInteresting(canvas.myapikey)">interesting</button>
</view>


I want to show a larger image when I click on a thumbnail, so I'll create a view for the larger image:
<view id="gPhotoDetails"
x="10" y="${parent.results.y + parent.results.height + 10}">
</view>

Nothing goes in that view yet, though, so I'll subclass the photo class, yielding the coolphoto class, and add an onclick handler. In the onclick handler, I'll set the source of the details view to the url to the medium sized image.

<handler name="onclick">
var s = this.getImageURL("_m");
gPhotoDetails.largeview.setSource( s );
</handler>

Now the app now has some search ui, and shows a larger image when you click on a thumbnail.(Here's the code so far)
Let's add some tasty effects. I'll add an animator to the coolphoto class, which fades in the photo from transparent to fully opaque.

<!-- This animator fades the image in by animating its opacity. -->
<animator name="appear_animator"
attribute="opacity"
to="1"
start="false"
duration="800"/>

We want that animator to start as soon as we've got the data for this photo, so we add an init handler:

<handler name="ondata" args="d">
<![CDATA[
// Start the fade-in animation
appear_animator.doStart();
]]></handler>

I want to show some information about the thumbnails when I mouse over them. I'll create a tiny view called gFloater to float in front of the photos, and animate the floater to just below the photo being mouse-over'd. To get the photos title and owner, I just run an XPath query on my data.

<view id="gFloater" width="160" bgcolor="#333333" 
options="ignorelayout"
x="1000"> <!-- start off offscreen -->
<simplelayout axis="y" spacing="1" />
<text name="titlelabel" fgcolor="white" width="150">title</text>
<text name="ownerlabel" fgcolor="white" width="150">owner</text>
</view>
<method event="onmouseover">
gFloater.animate("x", this.x + 10, 500);
gFloater.animate("y", this.y + parent.y + this.height - 10, 500);
gFloater.titlelabel.setText( "t: " + this.datapath.xpathQuery('@title'));
gFloater.ownerlabel.setText( "o: " + this.datapath.xpathQuery('@ownername'));
</method>

the complete code and the finished application.

Tuesday
Mar212006

podcasts: good as a media delivery mechanism, bad as a standalone media

Diggnation and This Week in Tech are moderately entertaining but not more so than the standard friday afternoon gather around somebody's computer and show off some cool stuff. The guys of Diggnation and TWiT don't seem to have any special information to tell me; I maybe get a nice "in the know" glow from hearing similiar tidbits of useless information emerge in a disconnected context. (Can it be a context if it's disconnected?) Patrick Norton and John Dvorak and Leo Laporte each have interesting personalities, but I think they're interesting like, if this guy is sitting in the break room, i'd be willing to sit down and hear about what he's up to, but I wouldn't sit in rapt attention while he goofs off with a few other moderately entertaining curmudgeons. Podcast qua Podcast: no.
But! Podcast as a way to deliver actual valuable news and entertainment and analysis -- that's just right. I use my ipod (thank you, Marshall, so much) as a time shifter. NPR and BBC and Jim Lehrer and Weekend America and Slate all deliver bits to my device, and I just keep a casual queue going, with some smart filters. Most days I have a few hours of NPR content available, and a few audiobooks I get through slowly... The content is what's important. A bunch of guys chatting about tech, or, worse, just one guy talking about tech: blech. But if you've got some actual journalists composing stories and pieces and reporting on the news, and you make that content available to me to put in my pocket and listen to anytime -- now you've got my attention. Which is the new new new economy.

Tuesday
Mar212006

"It's the FED, you idiot!"

George W. Bush cannot summon the words "the Fed" when asked in a press conference what he thinks about rising interest rates. Check this out:
Q: For the first time in years, interest rates are rising in the U.S., Europe and Japan at the same time. Is this a concern for you? And how much strain are higher interest rates placing on consumers and companies?
THE PRESIDENT: First of all, interest rates are set by an independent organization, which --
Q -- still, are you concerned about that?
THE PRESIDENT: Well, I'm not quite through with my answer yet.
Q I'm sorry.
THE PRESIDENT: I'm kind of stalling for time here. (Laughter.) Interest rates are set by the independent organization. I can only tell you that the economy of the United States looks very strong.
from whitehouse.gov's transcript of today's press conference
It's the FED, you idiot! The Federal Reserve Board. Remember, you just appointed Ben Bernanke to be the Chairman of the Fed six weeks ago? Arrrrg. It's hopeless. Can we impeach him for gross incompetence?