Monday, June 29, 2009

Ode to IE, How I Hate Thee


Just got done spending wasting about 2 hours debugging something in IE.

I am using YUI's SimpleDialog and was getting complaints that the buttons weren't visible in IE browsers.

In the picture below is the code and the dialog displayed, incorrectly. There should be 3 buttons visible in the dialog, as you can see them defined in the code.


No errors, warnings, nothing. Of course it works in FF and Safari. So I tried figuring it out with the Web Developer Toolbar. No dice. I tried messing with widths and heights and a bunch of CSS to see if it was being hidden or something. NADA.

Then when I was browsing the DOM with the Web Developer Toolbar I noticed that there were only 2 input elements instead of the expected 3. I also noticed I had a trailing comma at the end of the third button definition. Could that be it?


Damn. C'mon IE, if you're gonna have a problem with my JS syntax, you could at least throw an error, is that so hard!

Sunday, June 21, 2009

President Obama: You're Doing it Wrong!

When Obama swept to victory in November, he did so because of a combination of a few simple things. He is charismatic, pragmatic and likeable; he talks about tricky issues in a nuanced and understanding way; and he has a long-term vision for solving problems.

Although his plans had very little substance behind them on the campaign trail, they did correctly identify the important aspects of all the major issues. As his critics often pointed out, supporters could project their own plans onto Obama's hopes. This could never last once he started governing.

Alas, now that he's running the country, the reality of how things get done is starting to scare off conservatives and independents, while the left thinks he's being too pragmatic.

As one of those independents, I am somewhat disappointed that he's generally taken a monolithic (big government) approach to solving issues. I think that he's done this because it's pragmatic - with a Democratic majority in Congress it would seem the easiest way to get things done is to do them in a way that the majority will vote for.

But most Obama supporters I know didn't vote for him to do things the way Congress wants to. We want him to be pragmatic in his solutions, not in the path he takes to get them passed. For that, we want the reformer in him; the side of him that leverages his charisma and mastery of nuance to go over Congress and not through it; to offer solutions that no one else ever has; to bridge the gap between Democrats, Republicans, and Independents, to rally the people to develop and deliver American solutions to American problems. In a word, we want change.

What we like about Obama is that he hints at a third way; not a Democratic way, not a Republican way, but a better way. He starts with the assumption that there exists a better solution to the problems at hand than either party pushes on their own. A way that leverages the ingenuity of the American people, that solves the problems at hand, and does so efficiently, fairly, and in a way that makes sense to a majority of the American people.

So what is this third way? It is a way that combines the power of the government with the ingenuity of free markets.

Government is a tool; I strongly believe that the government is the only player that can set and enfore appropriate regulations. But it is a tool that must be used appropriately. My general philosophy, and frankly one I think that the vast majority of Americans support, is that Government should be as small as possible, but no smaller. Government should create policy to acheive its goals with as little direct intervention as possible.

Free markets are a tool as well, if not the quintessential American tool. While they are extremely effective at getting individual players to compete to deliver the best solution, the best solution to the market is sometimes not the best solution for everyone. When such negative side-effects form, they need to be countered. Markets must be both fair and free of externalities that cause societical harm in any form. This is the American way. It must be the role of government to regulate markets so that the actions of the free market are based on fairness, and don't have negative side effects for market participants or society at large.

Unfortunately, on the domestic front President Obama has not pursued this third way as he has on foreign policy. I can see why; the President effectively runs foreign policy from behind his desk. For domestic policy, he must go through Congress.

My hope is that President Obama can find the courage to plot a new course as he works on Health Care and other domestic priorities that will result in the change we voted for.

Friday, June 19, 2009

git-svn workflow

I've been doing bi-directional git-svn sync for a few weeks now and have finally started to understand how to get the workflow working smoothly, so I wanted to write it down to share with everyone.

There are many git-svn tutorials out there, but unfortunately I found them lacking a little. They either didn't work, or didn't sufficiently explain what they were doing and thus I couldn't reproduce in my situation.

My svn repo is really simple; it's just a trunk/ folder. I had been deploying to production with "svn up". Every once in a while I'd make an urgent change on production and commit it back.

To get started with git, I just did a git-svn clone, then pushed that to a GitHub repo.

The "best practice" workflow seemed to be:

git checkout -b topic-branch
git commit -a -m "made some changes"
git dcommit

And then a

git svn rebase

To get the remote changes from svn into the local branch.

But then I started running into trouble when my git-svn rebase's would start having conflicts. I could tell by the code in the local git branch that I was already up-to-date with the svn repo, but I didn't know how to get "git" to understand this. It seemed to have lost track.

While I am still not exactly sure how this works, I was able to get around it by doing the "git rebase --skip" over and over again until the rebase was done. Then you can compare the files in the git vs svn and see that they're the same to feel confident you're sync'd and up-to-date.

What I've been doing now that seems to work is:

git checkout master
git svn rebase
==> Current branch master is up to date.
git checkout -b feature
git commit -a -m "finished new feature"
git merge master
git checkout master
git svn rebase
==> Current branch master is up to date.
git merge feature
git dcommit

This has been working well. The thing that's very important is that you should only ever "git svn rebase" from the same branch. Things get crazy when you start running that command in multiple branches. I do not claim to understand why (yet). But it is true.

If you're ever out of whack and a bit scared you're gonna hose things up, here are some helpful things I used to see what was up:

To see what dcommit will send to svn, do:
# git svn dcommit --dry-run
Committing to file:///Users/Shared/Development/svnroot/virtualtour/trunk ...
diff-tree 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57~1 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57

The above output shows the diff-tree arguments that will be used to generate the patches sent to svn. You can view the actual diffs with:

# git diff-tree 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57~1 4bbc56e05ecf379bcab2ae155d51fdb04a67bd57 -u

This makes it pretty easy to figure out what git-svn will do without doing it.

Hopefull this info will help someone else out of a jam.

Enjoy,
Alan

Thursday, June 04, 2009

Managing dotfiles with git [updated]

After a few more months of tweaking my git-based workflow for managing dotfiles across multiple machines with git, I have finally packaged up my git/dotfiles solution and open-sourced it via GitHub.

Over the last few months I've migrated all of my accounts across 6 boxes (2 mac & 4 linux) to this solution. It has worked remarkably well.

Setup
Once I have an account on a new box, all I have to do is:

cd ~
cd dotfiles
rake

That's it!

All of my setups for ssh-agent, screen, zsh, postgres, vim, git, svn, etc are available immediately on the new box.

When you improve your "stock" dotfiles on any machine, you can then commit and push or pull the changes to your other boxes.

Any configuration needed local to that box can be done in the .local version of the dotfile, for instance there's a ~/.zshrc.local for stuff that only makes sense on this box.

Besides having useful configs for a bunch of programs, these scripts also include:
I hope that you find this solution useful and look forward to your feedback.

Enjoy,
Alan

Wednesday, June 03, 2009

User Experience Testing in the Cloud

Every web entrepreneur knows that usability of the site has a huge impact on the viability and growth rate of your company. But making sure your web site is a pleasurable and effective experience for your users is complicated, involving design, functionality, and usability.

Historically achieving good user experience was done by:
  • Using user experience best-practices to design the site
  • Let "Mom" try it; let beta testers try it
  • Fixing reported bugs
  • Examining high-level web site statistics or maybe clickstream data
  • Guess about improvements
  • Try again
Some companies with more time might have done more extensive testing, but without a big budget it was difficult to get good results or even see first-hand the results of testing.

Most of us knew there should be a better way, there just wasn't.

Fortunately, technology has now advanced to the point where real usability data can be gathered quickly and cheaply. Nearly all computers now come with built-in video cameras, making it easy to record tester's expressions and thoughts during the test. Specialized software has been written specifically for recording screencasts of users testing your app with video of their face included. Combine this type of software with teams of usability experts available online or even services like Mechanical Turk and you can leverage the internet to recruit testers.

There are different kinds of testing that you can do, and which you should choose depends on your goal. The questions you need to ask yourself are:
  1. Who do I want to give me feedback? Usability experts, random people, or existing customers?
  2. What kind of feedback do I want? Simple text responses or video of the tester performing the usability test?
The following services will let you accomplish any combination of testing audience and feedback type:

  • Silverback App - a $50 Mac app that records a screencast + video of a user testing your site. Perfect for conducting your own usability tests with users you gather yourself in-person (maybe buy free coffee for people at the local coffee shop if they'll agree to a 5-10 minute testing session). Ideal results, but time-consuming.
  • Feeback Army - You post a URL and a list of usability questions, pay $10, and they get people on Mechanical Turk to try your site and provide text replies. Fast results, cheap.
  • UserTesting.com - Screencast with audio and a written summary performed by a random (but vetted) internet user for $29.
  • UsabilityTest.com - Screencast with audio of a self-proclaimed usability guru providing feedback on your site for $20+.
I haven't tried any of these yet myself, but I wanted to share my thoughts about the options available and easiest ways to get started.

I will probably end up using all of the above services for different needs.

Enjoy,
Alan



Monday, June 01, 2009

Intro to using launchctl with MacPorts

After a long and frustrating day of trying to get some services running (apache and postgres) on a new box, I finally understand the basics of launchctl and how MacPorts interacts with it.

launchd and launchctl
Launchd is Apple's open-source replacement for cron, xinetd, mach_init, and init. You manage launchd services with the launchctl utility.

This article explains how launchd communicates with daemons, which is useful to understand when using launchctl to stop/start services.

Launchd manages named jobs which are specified by having launchctl load a plist file with the launchd config for a task. So for instance, instead of installing a script file in /etc/init.d you would call launchctl load -w /path/to/myservice.plist.

Once loaded into launchd, you can manipulate your service with the start/stop subcommands. Start will start the service, and stop will stop it. Thus, you'd think that you need only load a service once ever and then use stop/start to manage the services. However, you will notice that a service stopped with launchctl stop joblabel often won't seem to have stopped - it's still listed in the process list. But in reality it has stopped, and then restarted! If you look at the PID's before and after you'll notice you have new PIDs after you "stop" the service.

So what's going on?

Launchctl services "ported" from init.d scripts are usually configured with OnDemand=false which causes them to launch automatically at boot time. However, it also signals launchctl to make sure the process is always running! Thus, when you issue the stop command to such a service, a SIGTERM is sent to the service, but launchd immediately notices that it's no longer running and immediately re-spawns the service!

If you want your service to really stop, you can run launchctl remove joblabel, which will unload the service description and stop the job immediately. The downside is that you can not issue a launchctl start joblabel to start the service back up, since it is no longer loaded. You must then reload the service with launchctl load -w /path/to/myservice.plist.

In summary, if you are managing a service that has OnDemand=false, and you want to stop/start your service, use:

[start] launchctl load -w /path/to/myservice.plist
[stop] launchctl remove joblabel

Launchctl and MacPorts
Fortunately, the awesome guys over at MacPorts have built in some convenience commands for managing services installed with MacPorts. Note that this was only recently added and widely adopted; some of the older ports don't support the newer integration points, so just be aware in case this doesn't work for you.

The port command has 2 subcommands for interacting with launchctl, load and unload.

If all you're looking to do is have a reliable way to stop and start services, for instance the apache2 port, simply use:

[start] port load apache2
[stop] port unload apache2

It's that simple!

I hope that this guide helps clear up confusion that I am sure lots of people have experienced; I know it's caused me to waste several hours on many occasions, which is what I decided to finally talk to the MacPorts guys on IRC and write it all down once I figured it out!

Enjoy,
Alan