Wednesday, September 10, 2008

How to be the most awesome Dad ever

To be the most awesome Dad ever, capable of carrying out feats of skill and mastery usually reserved for the likes of the AvatarJames Bond, or the Doctor, requires just a few common ingredients:
  1. The locked, most secret diary of a pre-adolescent daughter (who has lost the key),
  2. The knowledge that all such cheap locks are the same,
  3. A set of cheap luggage locks with keys,
  4. A frantic pre-adolescent daughter in possession of #1 but not #2 or #3, and
  5. A flair for the dramatic, with which one discloses that one knows how to pick locks, but it's a secret handed down from master spy to master spy, therefore the work must be done behind a locked door (which neatly conceals the fact that you're rummaging around in your bedroom drawer to find #3).

Tuesday, June 03, 2008

Fun with itertools

Sometimes it's hard to shake old habits, especially when you've burned them into your brain as the "standard" way to do things. For example, I've been doing network programming with C and C++ for a very long time. One of the standard pieces of code I've written again and again is the "connect with backoff" pattern.

If a program needs a continuous network connection, and that connection is lost, it should try to reconnect. On the one hand, you want to reconnect as quickly as possible; on the other hand, you don't want to keep retrying (and failing) in a tight loop. So you use a "backoff" timer: after each attempt, you wait longer (up to a maximum limit).

As a C programmer, I would implement an algorithm that resembles this Python-like pseudocode:

# After the first failure wait half a second before retrying;
# double this each time up to eight seconds.
backoff_times = [.5, 1, 2, 4, 8]
cur_backoff = None

while 1:
# Try to connect
except ConnectionError:
# Failed; update the backoff counter
if cur_backoff is None:
cur_backoff = 0
cur_backoff = min(len(backoff_times)-1, cur_backoff+1)
# Wait to retry
# Success; reset the backoff timer
cur_backoff = None

But in Python the code to manage the current backoff timer looks out of place.

In a high level language, when the ratio of "code that says what I want" to "code that tells the language how to do what I want" gets too low, you're doing it wrong. It means that you're spending too many mental cycles on the "how," and not enough on the "what".

In this case, Python gives me a better way to tell it just "what" I want it to do: use an iterator.

import itertools

def iter_pegged(seq):
"""Return an iterator that walks the sequence, and then 'pegs' on the last item."""
return itertools.chain(seq, itertools.repeat(seq[-1]))

backoff_times = [.5, 1, 2, 4, 8]
cur_backoff = iter_pegged(backoff_times)

while 1:
# Try to connect
except ConnectionError:
# Wait to retry
# Success; reset the backoff timer
cur_backoff = iter_pegged(backoff_times)

Other than the definition of iter_pegged, each line of code says what only what it wants to do, not how it wants to do it.

And that's what coding in a high level language is all about, no?

Monday, June 02, 2008

Git: what he said.

About three months ago, I started writing a blog post on why my (development) life has changed for the better since I started using git for version control. It's been stewing in my "Drafts" folder for lack of time and attention.

My main point was that git is optimized for messy reality, as opposed to an idealized view of software development that never really happened that way, but looks better when you draw it on a white board.

A few weeks ago, Ryan Tomayko said most of what I intended to say, in The Thing About Git.

So, "what he said". In particular:

  • Git means never having to say, “you should have
  • git --rebase interactive is “a bit like git commit --amend hopped up on acid and holding a chainsaw - completely insane and quite dangerous but capable of exposing entirely new states of mind.”

Friday, April 18, 2008

That Looks About Right

tlesher@badwolf:~$ history | awk '{print $2}' | sort | uniq -c | sort -rn | head
109 ls
107 cd
78 git
26 sudo
14 rm
12 ssh
11 source
11 more
10 wget
9 ipython

(via Chris and Tom)

Saturday, January 05, 2008

Oh, look! A startup!

This December, I took a deep breath and jumped. I left a great job at a great company, working on cool projects with fun people, and executed a perfect swan dive back into the tech startup blender.

Now why would a thirty-something refugee from the tech bubble with a wife, two young kids, and a mortgage give up a good salary and stable, interesting job for the stress, uncertainty, and heavier workload of a new startup?

For me, it's all about aligning outcomes with effort. In a very early stage startup, the link between "what is about to happen" and "what am I doing" is as close to direct as you can possibly get. The outcome for the company is directly tied to what you're doing and how well you're doing it: no excuses, and no wiggle room. Naturally, there are external risks (like being run over by a company so big they barely notice the bump), you see the results of your effort clearly.

Working for a BigCo, Inc. is very different. Expending effort in a large company is like pulling on a bungie cord attached to a rock. Pull moderately, and nothing happens. Pull a little more, and the the rock comes along, but it tends to wiggle around in directions you don't intend. Yank really hard, and the rock has an annoying tendency to fly up and smack you in the head.

Now replace the bungie cord with a stick attached to the weight. You pull a little, the weight moves a little. You pull a lot, the weight moves a lot. You push, and the weight moves the opposite direction. The outcome is directly tied to your effort.

To be fair, my last company wasn't quite to the "bungie cord" stage. But when a former colleague approached me about his idea for a startup, I was drawn back in again.

Of course, to (ahem) stretch the analogy, sticks do tend to break more easily, but hey: that's the risk you take.