I’ve become a somewhat avid twitter user over the last several months. It’s helped me to stay in contact with existing friends and to get to know a few people from Refresh Phoenix, a local web design/development club. For those who don’t know what it is, it’s like LiveJournal, except each blog entry is limited to 140 characters, the friends feature works slightly differently, and it has good integration with SMS.

A couple of things I really like about it:

  • The 140 character limit. Twitter has a strict 140-character limit on all blog posts (tweets in twitter lingo). I’ve found this to be a very useful constraint. It reduces the amount of reading I have to do to keep tabs on friends. It also reduces the amount of time spent writing. As long as I don’t follow too many people, and don’t follow those that post too much, I can avoid spending too much time on twitter.

    I think it is also helping me to be a better writer and conversationalist. Trying to tell a story in 140 characters can be an interesting exercise. Inevitably, some details need to be dropped. Sometimes the story is not as good because it’s missing some interesting details, but often what’s left out is uninteresting. I had one such moment today.

    Yesterday, I was hanging out with some friends and told them a story. About half of the people found it interesting, but most thought it was long-winded and the half who weren’t interested were bored by it. If I had been thinking like I am when I write a twitter post, it might have been better received.

    I think the 140-character limit is a constraint people ought to embrace. There are a couple of ways to get around it — posting multiple tweets or dropping vowels and using lots of abbreviations and text-messaging-speak. I have a couple of rules of thumb. I try not to make a post that would make absolutely no sense to someone who didn’t read the other post. I also avoid shortening more than two or three words to make my post fit in 140 characters.

  • Easy come, easy go. On Twitter, if someone follows you it sends you a friendly notice with the username of the person who follows you. If someone stops following you, it sends you no such notice. So, unless you’re constantly checking the list of people who follow you, you can’t give them a hard time about not following you anymore.

    It might annoy some people, but it’s for the greater good. It encourages people not to break twitter etiquette, or else people might stop following them. It also makes twitter fun to use, because if one user is being annoying, you can quit following them instantly and not face immediate blowback, unless that person is a real jerk.

  • Best Wishes. On twitter, the notification e-mails you receive when a person follows you end with the following signature:

    Best,
    Twitter

    A few times, that’s been just the thing to help me to have a better day. The people at twitter are wishing everyone using their service the best. It’s the best closing salutation ever, IMHO. Thanks, folks!

After I talk to someone I meet at a coffee shop or while traveling and help them with a small technical issue like getting photos transferred or getting on a wireless network, I’m sometimes asked for advice on becoming tech savvy. My advice for someone struggling with their PC who I won’t see again and won’t be able to help in the future is to get a mac. I point out that it really is totally different from a PC, and once they get a mac they should be able to figure out how to do a lot of stuff by themselves, instead of asking for help like they do now.

There is one thing, besides not wanting to pay extra money for a mac, that keeps people from empowering themselves by getting a windows-free computer that they can actually learn to use and maintain themselves — either they or someone they know has had hardware problems with a mac.

In my opinion, even if a mac breaks several times, it’s still worth it to get a mac (and an extended warranty) if you can’t figure out windows and need a computer for your career. I’m reminded of this by a comment by an editor on The Consumerist, an extremely popular and successful blog. He says that he’s had issues with three different macs and an iPod, but it’s still worth it to him to have a mac. Of course it is. He built a successful career with macs.

I just wrote my first GreaseMonkey user script. It’s a script that puts a random Benjamin Franklin quote above the stories on reddit to remind me to be dutiful and not spend too much time looking at online news. I found the quotes through (you guessed it) reddit.

Here’s what it looks like:

reddit_franklin.jpg

And here’s the code:

// ==UserScript==
// @name           Reddit Quotes
// @namespace      com.benatkin
// @description    Shows Quotes in front of Reddit
// @include        http://reddit.com/
// ==/UserScript==

function franklinQuote() {
  var quotes = [
    'Early to bed, and early to rise, makes a man healthy, wealthy and wise',
    'Diligence is the mother of good luck',
    'God helps them that help themselves',
    'Sloth, like rust, consumes faster than labor wears, while the used key is always bright',
    'Dost thou love life, then do not squander time, for that’s the stuff life is made of',
    'Lost time is never found again',
    'He that riseth late, must trot all day, and shall scarce overtake his business at night',
    'Drive thy business, let not that drive thee',
    'Industry need not wish',
    'He that lives upon hope will die fasting',
    'There are no gains, without pains',
    'Plough deep, while sluggards sleep, and you shall have corn to sell and to keep',
    'One today is worth two tomorrows',
    'Have you somewhat to do tomorrow, do it today',
    'Be ashamed to catch yourself idle',
    'Let not the sun look down and say, inglorious here he lies',
    'He that hath a trade hath an estate',
    'He that hath a calling hath an office of profit and honor',
    'At the working man’s house hunger looks in, but dares not enter',
    'For industry pays debts, while despair encreaseth them',
    'Constant dropping wears away stones',
    'By diligence and patience the mouse ate in two the cable',
    'Little strokes fell great oaks',
    'Employ thy time well if thou meanest to gain leisure',
    'Since thou art not sure of a minute, throw not away an hour',
    'A life of leisure and a life of laziness are two things. Do you imagine that sloth will afford you more comfort than labor?',
    'Trouble springs from idleness, and grievous toil from needless ease.',
    'Many without labor would live by their wits only, but they break for want of stock',
    'Industry gives comfort, and plenty, and respect: fly pleasures, and they’ll follow you',
    'Keep the shop, and thy shop will keep thee',
    'If you would have your business done, go; if not, send',
    'He that by the plough would thrive, Himself must either hold or drive.',
    'The eye of a master will do more work than both his hands',
    'Want of care does us more damage than want of knowledge',
    'Not to oversee workmen is to leave them your purse open',
    'In the affairs of this world men are saved not by faith, but by the want of it',
    'Learning is to the studious, and riches to the careful, as well as power to the bold, and Heaven to the virtuous',
    'If you would have a faithful servant, and one that you like, serve yourself',
    'For want of a nail the shoe was lost; for want of a shoe the horse was lost, and for want of a horse the rider was lost'
  ];
  return quotes[Math.floor(Math.random()*(quotes.length))];
}

function addFranklinQuote() {
  var tbl = document.getElementById('siteTable');
  if (tbl) {
    var quoteBox = document.createElement('div');
    quoteBox.innerHTML = franklinQuote();
    quoteBox.style.fontSize = "16pt";
    quoteBox.style.backgroundColor = "#f9f7ed";
    quoteBox.style.padding = "1.5em";
    quoteBox.style.position = "relative";
    quoteBox.style.width = '500pt';
    tbl.parentNode.insertBefore(quoteBox, tbl);

    var quoteName = document.createElement('div');
    quoteName.innerHTML = "-- Benjamin Franklin";
    quoteName.style.fontSize = "10pt";
    quoteName.style.position = "absolute";
    quoteName.style.bottom = "0";
    quoteName.style.right = "0";
    quoteBox.appendChild(quoteName);
  }
}

addFranklinQuote();

Greasemonkey really is as simple to use as it sounds. You give it a script and the URL’s to which it applies. When you browse to a page that matches the URL, the script is executed. For this one, it was a simple matter of adding a DOM element in the right place.

Some scripts are meant to be loaded on all pages, such as a script that makes it possible to use shift to quickly check or uncheck a bunch of checkboxes. If you’ve heard people complain about the Greasemonkey overhead, it’s probably because they’ve run a bunch of these utility scripts that run on all pages. A script or two that are browser-wide, with the rest of the scripts only running on a single site shouldn’t slow things down much.

To install, first install greasemonkey. Then, find the greasemonkey folder (gm_scripts) in your profile directory and save the above code into a file called “redditquotes.user.js”.

UPDATE (2007-07-17): After searching for ‘sliding doors css “dead space”‘ I found that someone already solved the problem without using JavaScript.

About a year ago I read Sliding Doors of CSS on A List Apart. While I admired the elegance of the design, I found the dead space on the left side of the tabs to be annoying.

The problem comes down to not being able to wrap an individual anchor tag around a list item tag and have it work. The anchor tag had to be put inside the list item tag, and try as I and the author might, it couldn’t be made to include the entire tab. The left side of the tabs were unclickable, as can be seen in the example.

The other day, I got the idea to fix the problem with JavaScript. I could make the list item trigger an onclick event. I could also make it show a hand cursor when hovering over the list item. The hand cursor thing could be done with CSS, but I like doing it in the JavaScript better, because if somehow the JavaScript code doesn’t execute properly, it won’t show a hand cursor in an area that’s not actually clickable.

I use the following JavaScript code, which relies on the JQuery library, to make the dead space clickable. On the first try I had the whole page flicker in Firefox when part of the anchor was clicked (the part that wasn’t dead space before). I tested it on the old page and it didn’t have the whole page flicker issue. So I figured out that it was probably a result of both the link and the javascript being triggered, and I added an event for the anchor to tell it not to trigger the dead-space event if the user clicked on the anchor.

clickedAnchor = false;

function fixDeadSpace(headerDiv) {
  var items = $('li', headerDiv);
  items.css('cursor', 'pointer');
  items.click(function(arg) {
    if (! clickedAnchor) {
      window.location.href = $('a', arg.target).attr('href');
    }
  });
  $('a', headerDiv).click(function() { clickedAnchor = true; });
}

$(function() {
  fixDeadSpace($('#header'));
});

To use, make sure the JQuery library is available, and add the above in a script tag. Here is the example with my code added, and different query strings in the links.

It behaves just about the same as if the left part of the tab were part of the link. The only difference that might be noticeable to a very small number of users is that when you hover over the area outside the anchor tag, the location isn’t shown in the status bar.

Recently I was hanging out at a coffee shop when a European tourist approached me and asked, “Excuse me, is there a wireless signal here?” I said “Yes.” After a little hesitation, due to her lack of fluency in English, she asked, “Free?”, and I said “Yes” again.

It occurred to me that she might not be that fluent in English, but knew how to ask if there was a wireless signal. It’s an important thing to learn, because an Internet connection is one of the most important tools for travelers (for me it comes only behind clothing, money, and identification).

My, how the world changes.

There has been no shortage of great writing on Microsoft’s patent strategy announced by Steve Ballmer on Monday. It’s a little hard to find, but it’s there. An interesting comment I found today (emphasis mine):

MY CHALLENGE TO MICROSOFT is that, if you’re just enforcing the law, go ahead and sue all your closest partners first. Start with Mainsoft, then find a list of all your gold partners and just work your way down. Maybe look up all the MVPs and find out who they work for, and make sure their companies get hit as well.

Also, find all the startups you’ve purchased over the years (e.g. Hotmail) and find the original owners and sue them retroactively. I don’t know if that’s possible to sue the Hotmail founder for using linux way back–but if it can be done, it SHOULD BE.

After that’s all cleared up, then you can go after the rest of the industry, like IBM, Red Hat, Sun, Oracle, etc. Fair’s fair, after all.

Posted by Peter {faa780ce-0f0a-4c28-81d2-3667b71287fd} on Tuesday, May 15, 2007 to the Joel On Software forum

One of my favorite web apps for finding news is TailRank. TailRank indexes thousands of blogs, and shows news that is that is being discussed by lots of legitimate bloggers. On their page, there are a bunch of stories, each with one main blog and a sampling of other blogs that reference the story. If you click on a link, it shows all of the articles that were grouped with that story. Usually, on pages that make the front page, there’s somewhere between 5 and 50 links to blog entries per story. Things that lots of bloggers comment on tend to be interesting. For example, today I found the following articles:

Each of these has links to a bunch of blog entries where different bloggers weigh in about the stories. Some of the stories attract blog posts where arguments are made. Others attract blog posts where people uncover different tidbits of information. Most are a little of both.

There are other things to like about TailRank — it has a great UI and is based on great technology. There’s a lot of information to be had on the front page. This is made possible because TailRank is well-cached. It’s very smart about which posts it lets into the system, and it keeps out many poorly-written and spammy blog posts. The UI is beautiful, from an aesthetic standpoint. The colors are great and it’s uncluttered. There are visual snapshots of each post. All around it’s an amazingly neat product. For what it does, it does a great job.

The founder has done a very good job of setting up infrastructure and putting together a programming team with a minimal investment. At first, according to him in a podcast he did (which also contains information on the caching), it was just him and he did some outsourcing. Now, according to an article linked to on the TailRank blog, he’s got one developer working with him in person in San Francisco. They’ve just released an API for using their blog search engine (short article).

Since I’ve been spending too much time on reddit, I have started using TailRank more, because a higher percentage of its articles are interesting. I think this is because reddit lets people frivolously increase the ranking of stories that they agree with, even if they aren’t interesting. To write a decent blog post about a subject takes time.

Another nice thing from a productivity standpoint is that it lacks comments in the reddit/Digg sense. It is in itself, focused on comments, though. It is a bit more difficult to write comments. You have to have a blog with interesting content and get it recognized by the search engines.

In my opinion it’s the best way to write comments, though. The person on whose site you’re commenting can’t delete your comment, since it’s on your on blog. They can delete a trackback, but they can’t delete it on TailRank. It also makes it easy for other people to find what you’ve written. And, of course, it’s better for marketing, since it brings people to your website.

I just read an article calling for a way to get an AST for Ruby code from within Ruby. I think it’s a great idea, and I think static analysis, code manipulation/refactoring are great reasons to support such a thing. Another consequence would be macros, which are a more controversial feature. The only downside I can think of is that it could be misused, and to leave out a feature for that reason would go against the Ruby philosophy, in my opinion. One of the regulars at the Phoenix Ruby Users’ Group argued against using a dumbed-down “teaching language”, saying that when you suggest using a language you don’t want to use yourself, you’re talking down to the learner. I agree. I think the best way to keep people from misusing features is not to remove the features, but to educate them. People in the Ruby community have always done a good job of making sure there’s lots of good example code out there, and giving constructive criticism when someone posts a bad example.

While the reasons in the article are enough, I can think of another good reason for having AST support — having the ability to constrain code to a certain set of features. There would be two different uses for this:

  • Running code from an untrusted source – This could include web template designers, or even users. Ning is an example of a site that lets users run their own code — but there is a huge overhead to facilitate this and to sandbox everything. If it could be verified that code doesn’t do anything dangerous, I think a new type of Web app plug-ins would emerge. Instead of having to set up an app on a separate site and use REST or SOAP to communicate, people could just throw together a little script in a domain-specific language. One idea I have for this sort of technology would be a Flickr for html and image generators (like ajaxload.info).
  • Enforcing decoupling – When managing a large software project, I think it would nice to specify which classes do what, and have it enforced. Maybe there is some class that’s supposed to be all about math, but that goes in an application that gives output to users. To keep math programmers from putting presentation logic in mathematical code, you could constrain them to a DSL that doesn’t have strings. Or, you could keep template programmers from doing networking code. The check could be done at runtime, or commit time, with plug-ins to the version control system.

There is a Perl library that parses Perl, but it would be nice to have one for Ruby that’s written in C and optimized for speed, and that with certainty matches up to what the interpreter understands.

I think that once an AST implementation was built, something like RSpec could be created which does compile-time or commit-time analysis. That would be cool.


Watch Dexter, Anybots, Inc.‘s self-balancing robot. Then watch the video of Honda’s Asimo robot walking and then falling down while attempting to climb stairs (I know they’ve had successful stair-climbing demonstrations since). Quite a contrast, isn’t it? Dexter’s walk looks like a human walk, a pretty feeble human, but a human walk. The Asimo robot’s walk looks like a souped up robot’s walk.

Both robots have their advantages. I’d like to see Dexter get the ability run off battery power. It would also be interesting to see other combinations of the two types of robots. But I will always remember Dexter as he is right now when I think back to the day that I first saw a self-balancing biped robot.

Valentine’s Day was fairly uneventful for me this year, but humankind made significant progress that day. Trevor Blackwell, a very smart man and a friend of Paul Graham, got his robot, Dexter, to walk with dynamic balancing.

The video is one of the most amazing things I’ve watched in my life. It was like the first time I saw a video of Apollo 11 lifting off. Its heroic effort to walk like a human walks, and to stay up on two feet, is amazing to see. I can see Trevor Blackwell’s effort in the robot’s movement. It looks like the robot is feeling the moment.

It’s a must-see.

Trevor’s creation is at Anybots, Inc., a company he founded that develops robot software. They have a website, and they’re hiring. A requirement in the “Join Our Team” page is hubris — one of the three great virtues of programming.