How to Beat an Old Man at Squash

You are a young, fit squash player and you come across an opponent who looks to be older than 60 and about to croak. You have probably been building a solid, controlled squash game. Your game probably emphasizes pressure shots that move your opponent around the court when you are in good position and emphasizes higher, softer shots when you're in bad position when you're under pressure so that you have more time to get back in good position. These habits are all good things.

But if there's and older gentleman who is apparently at your skill level you need to ignore all of those carefully learned tactics. This older gentleman is not playing at your skill level because he's super fit. He's playing at your skill level because he can probably put that darned ball exactly where he wants to with accuracy that borders on the silly. He will hit soft shots as much as he can, slowing the game down so your vastly superior fitness doesn't really matter. While this may sound mean, overpower the old fart.

You don't have to worry as much about accuracy anymore at this point, because he will beat you at a game that relies on accuracy. Odds are he's been playing and practicing those shots for longer than you've been alive. Make the sucker run, and run hard. Beat the squash ball around the court. Punish the little black orb with serious pace again and again and again and again and again and again and again and again and again. He will respond by trying to take the speed off the ball with lobs and drops. Run them down and power it down the wall or cross-court. Make the game a fitness contest. You'll lose a racket skills context, but you can win a fitness contest.




If you don't know all this before your match and are only told it afterwards by a pro that was observing your defeat, here's what you do: Realize that the tournament you were playing in is at a luxurious private club. For at least an hour after your match make extensive use of the jacuzzi, steam room, sauna, bountiful bath products, and plush leather chairs in the locker room.

Locked in by Your Friends

Any asocial web app (e.g. Yahoo Search) lives in an entirely different market than the social kind. This market, where users can leave for greener pastures without any cost to themselves, is a breeding ground for healthy competition. When google started returning better results people could just leave Yahoo. They didn't have to convince their friends to come with them (even though they did). But if orkut, hi5, friendster, or any other fledgling social network makes a better experience nobody will really care. Are any of your friends on hi5? Had you ever heard of hi5 before?

If you wanted to move could you get all your friends to move with you? Do you want to upload all your photos again? This is why you still only hear about myspace and facebook, and will continue to only hear about myspace and facebook. It's nothing more than a two-player oligopoly which has accurately surmised this fact and split up the market along demographics. From this portioning of the demographics you, the individual, really has zero choice.

The lack of choice in social networks is probably not news to any of you, but what you might not be aware of* is that the Current Big Thing in social networks are social apps. It's web 2.0 built on top of your social grid. Play scrabble and compare scores with your friends. Adopt a pet and show it off. There are thousands of these apps being used by millions of people. For the most part they all suck, but not because the developers suck. You can generally blame the ineffeciences of an oligopoly. You can blame Facebook and Myspace.

Myspace and Facebook both have development environments, they both suck, and neither of the companies really have any need to change. If you want to make a social web app you have one of two choices. The social networks aren't just locking in end-users, they're locking in the content providers.

Web 1.0 was a quality-based free-for-all. Web 2.0 was a land-grab.



* People I know aren't the kind of people that use social networking apps, it turns out.

Abstract Yourself

In a recent essay Paul Graham came up with a powerful idea about how certain topics never seem to lead to clear debates.
I think what religion and politics have in common is that they become part of people's identity, and people can never have a fruitful argument about something that's part of their identity. By definition they're partisan.
...
In general identity gives you strength while making you stupid.
This is true of far more than just religion and politics. There are loads of different topics and situations where having vested a part of your identity leads to powerful mistakes. Here are just a few off the top of my head.
  • If you purchase a stick of deodorant because you're a Micthum Man then identity decided where to spend your money.
  • If you never hung out with people outside your own clique in High School then identity kept you from making more friends.
  • If you spent several hours arguing on the internet in some flamewar then identity just wasted your evening.

As Paul said in his essay, however, identity does give you strength.
  • The strength to sacrifice your life for your child because your family is that self-sacrificing.
  • The strength to stay late at sports practice because your team works hard.
  • The strength to stick with abstinence-only education because people of your faith don't have premarital sex.
That last item in the list should deliberately set off alarm bells. What makes it different from the first two is that the strength you gain from the added identity is vastly outweighed by the stupid. This is because the first two espouse virtues (work hard, self-sacrifice) while the third espouses merely a perceived instance of a virtue (purity). Very often prescribed actions that are meant to make people virtuous (e.g. "don't combine pork and dairy") turn out to be misguided. Stick with groups that hint you towards virtues, not specific actions.


The second aspect of identity that makes people stupid is the whole "us vs. them" mentality. It's not hard to find -- just do a google search for "sports fans arrested". People stop caring about virtue at all and start only caring about what side you're on. Tell your teammate you support them but if you catch them deliberately taking a fall again they will have hell to pay. Make your group have an identity that espouses virtues.


So whence the title of this post? Abstract your identity away from specific actions that any part of your identity prescribes. Build your identity out of virtues and general ideas. Gravitate towards groups that do the same. Something that makes you stupid makes you weak, not strong.

Closing the Loop

I'm not the first person to talk about how sweet closures are. I'm assuming you know about them already. Javascript, the rinky-dink language most people associate with toggling web page elements, has them. Recall that Javascript also lets you modify the DOM. This means that you can do all the totally awesome stuff that closures get you with objects in your web page.

I'll give an example of some of this sweetness where I'll be using the prototype.js framework. You don't need to know anything about it other than it facilitates OOP in javascript*.

Here's the basic idea of my demo: You've got this really complex web app and you want to build a twitter-like service on top of it. Let's call it Tweeter (don't sue me!). Lets say it's an enterprise web app and you want your company to be able to tweet with their coworkers. Lets also pretend that a mashup with twitter isn't an option -- maybe this is the NSA or something. Just pretend.

Product decided that Tweeter will suck unless lots of people use it, and that nobody will use it unless they can tweet all over the existing app. They want to tweet anytime anywhere. This is a web app, remember, so this means building divs and spans in like 50 places or something, right?

Of course not! You scoff at such silliness! You're a smart web developer -- you know that if you write a function called makeTweeterInput() that prints the divs and spans on your web server you can just call makeTweeterInput() instead of writing out the divs and spans in all 50 places. You're so smart!

But you start using makeTweeterInput() and you run into a problem when you have more than one on the page: You gave those divs and spans ID's so javascript could access the divs and spans correctly, but now you have multiple divs and spans. If only there was some environment where variables could be looked up by name! If only there was some way those divs and spans knew where they came from.

In my previous post I talked about how you could use closures to make sure you were referring to the right this. Now I'm gonna show you how nice it is using closures to make sure you refer to the right DOM objects. (note: this relies on prototype.js's handy Class.create())



var Tweeter = Class.create({
wrapperDiv: null,

initialize: function() {
this.wrapperDiv = new Element('div');

this.tweeterText= new Element('textarea');
this.wrapperDiv.insert(this.tweeterText);

this.submitButton = new Element('input', {
'type': 'button',
'value': 'tweet this'
});
this.submitButton.observe('click', this.submitTweet.bind(this));
this.wrapperDiv.insert(this.submitButton);
},

submitTweet: function() {
this.wrapperDiv.update('submitting...');
someAJAXCall(this.afterSubmit.bind(this));
},

afterSubmit: function() {
this.wrapperDiv.update('tweet totally submitted');
}
});


Now, all I have to do to put this into a web page is create one and drop it in.
var tweeter = new Tweeter();
var someDiv = document.getElementById('someID');
someDiv.insert(tweeter.wrapperDiv);


Each object created will know precisely which object it is on the page because closures have literally bridged the gap between the javascript variable environment and the DOM.

See this in action. (edit: this web server has since been killed)







PS: You might cringe at the idea of creating DOM objects in JS. The performance really isn't an issue**. I know of at least one app on a prominent social network that has an active user base in the millions that uses this method.


* If you regularly write in javascript, you probably should get to know it.


** Technically, I think that if you don't ever reload a webpage and just keep adding objects with closures via javascript you will leak a little memory, but at a pretty slow rate. Closing the browser, web page, or refreshing the page will take care of it. In short this pretty much isn't an issue.

For My Non-Technical Readers

I've joined in on a little experiment with some of my geeky friends wherein we all made a pact to blog once per day for a month. Each post must stand alone as something interesting and worth reading.

Mom, Dad, these posts probably aren't for you. Sorry. I'll get back to posting the tasty things Erin and I are cooking around mid-March.

What's This?

If you've ever tried to write heavily-interactive web pages you've probably come across the special javascript variable this. People usually make the mistake of thinking this is the same thing as self in other languages (wrong), and in fact you might come across code like this:

var Foo = {
message: 'hi there!',

bar: function() {
var self = this;
var div = document.getElementById('some_id');
div.onclick = function() { alert(self.message); };
}
};


If in that onclick function you instead wrote this.message you'd alert a null value instead of 'hi there!'. "What the hell?", you ask, wondering how that onclick that clearly is within the scope of Foo (after all you can refer to self, defined outside the function body), all of a sudden have a different this? What the hell is this, anyway? The answer, as with a lot of nerdy questions, is "It depends".

  • In an object method ( Foo.bar(...) ): this is a reference to the object (i.e. Foo).
  • In an independent function call ( doStuff(...) ): this is a reference to the global scope (generally the window object).
  • In an event handler ( <div onclick='alert(this);'>): this is a reference to the DOM element that fired off the event (event.srcElement).
So in our case this starts off referring to Foo, but once the code in that onclick function is run it will be in the scope of an event handler, so this will refer to the div that was clicked. Javascript does have closures, however, so you can refer to any variables defined in the same closure that the function was (in our case this means referring to self).

This can be a total pain to work with since you have a variable that silently changes based on execution scope. Furthermore, this is in a language with functions as first-class objects, letting you apply these functions anywhere. Don't you wish you paid more attention during that Lisp course?

The best solution I've come across is to (1) grokk Scope and Lambdas and then (2) use prototype.js's Function.bind(). Calling bind on a function in javascript will wrap the function in another, locking its execution scope to an object specified by the argument. So we can now write the original code like this:
var Foo = {
message: 'hi there!',

bar: function() {
var div = document.getElementById('some_id');
div.onclick = function() {
alert(this.message);
}.bind(this);
}
}
There doesn't appear to be a huge gain here over the original code. Today is just a teaser. This method, however, opens up some much more powerful things to get some really nice OOP behaviour with DOM objects that I'll be writing about tomorrow (and hopefully demo'ing a little bit).

Fish Tacos!

Erin sent me on a small errand to pick up ingredients to make some fish tacos tonight, and I decided to go to eleven. Specifically, we had never actually made them with a proper crema sauce before and I decided to fix that. After a quick search online of possible recipes, I came up with the following bit of experimental cooking.

White Cream Sauce for Fish Tacos:
  • 3/4 cup sour cream
  • 1/2 cup mayonnaise
  • 2 tbsp lime juice
  • 1 tbsp ground cumin
  • 2 whole red jalapeno peppers.
  1. puree the jalapeno peppers with a dash of vegetable oil and lime juice
  2. mix the pureed peppers with the remaining ingredients.

Keep in mind that I did it all to taste so those amounts are vague approximations.
  • To balance the sour cream and mayonnaise: when it's complete you should only barely be able to taste any mayonnaise.
  • To get the viscosity right just keep adding lime juice until the mixture is about 1/3rd as thick as mayonnaise.
  • Add cumin to taste, but you shouldn't taste too much cumin in the finished product.

They were so freakin' delicious I had 8. I guess playing 3 hours of squash on both Saturday and Sunday made me huuuuuuungry.

I'm a Lazy Bum and it's My Greatest Strength

From this rant.

I believe that computers are meant to serve people and not the other way around. That means that if something inherently simple is difficult to do, it's wrong.

Not everyone agrees with this. A surprising number of people like things to be difficult. I have never understood this, but it is a fact. Some people revel in the intellectual studliness of mastering, say, C++ template programming or x86 assembler. I don't. I think C++ is a pain in the ass. Life is short, and I would rather spend my allotted time skiing or making love to my wife than worrying about whether or not I need to define a virtual destructor in my base class in order to avoid memory leaks. And that means that when I want, say, for something to appear centered on the screen, I want to be able to do it by typing "
center" rather than "margin:auto". If I can't tell a computer to center something by saying "center", then as far as I'm concerned the computer is wrong, not me.

Like I said, not everyone buys in to this worldview. I don't get it, but it is surprisingly common. I think it might have something to do with job security. I first encountered the complicated-is-beautiful mindset when I was working for NASA. I had an idea for how to simplify spacecraft sequencing and make it less error prone. I figured everyone would love it. To the contrary, the establishment fought the idea tooth-and-nail (and still does to this day). And this attitude is 
everywhere. It's the reason the tax code is so fucked up. It's the reason the law is so byzantine. It's the reason that languages like C++ and Perl thrive.

I like simplicity. I think the computer should have to conform to my brain and not the other way around. 

Different people have different ideas of what it means to "work". For me, the ratio of effort expended to the quality of the [finished product] is paramount. I want to put forth as little effort as possible to get something that looks decent. (
Yes, I'm a lazy bum. It's my greatest strength. Laziness is a powerful motivator for finding more effective ways of doing things, and it has served me quite well.) Everything else is secondary.
(emphasis mine)
I agree with everything the original author said except for the part where he muses that some people love complex computer issues because of job security. I think it's instead because they like feeling smart, and mastering something complex is certainly something that can make you feel smart. Inventing complexity where there is none, however, is not smart and the amount of wasted effort therein could probably fuel an economic recovery.