Google has an experimental search page where you can test drive new search result layouts. My favorite is the Keyboard Shortcuts option. This lets you navigate and view search results using only the keyboard – no mouse required! It’s a huge benefit for Quicksilver fans.
Now that Yahoo! is my default search engine, I desperately didn’t want to give up the keyboard shortcuts feature. Thanks to jQuery and Greasemonkey I don’t have to.
Make sure you’re using Firefox and have the Greasemonkey plugin loaded. Then, click here to install.
I’ve chosen the same shortcut keys as Google. J and K move you up and down through the search results. Press return to view the selected link. You can even browse through multiple pages when you hit the end of the results. Pressing / will jump you to the search box if you’d like to run a new search. Hit escape to move back to the results.
Earlier today I was asked what I look for in a job. Specifically, what it would take to retain me past the typical “three year burnout” period tech workers often find themselves up against. The usual answers came to mind: a fun corporate environment, challenging assignments, working with people smarter than myself. Those are all important factors, but they’re also very vanilla. Who wouldn’t want to work in a fun workplace? Unless you have a serious ego, why wouldn’t you want to be around smart people?
The person I was talking to pressed on looking for a more concrete answer. I thought back to previous jobs and why I had left them. I know that burnout had been a significant factor in leaving one position. The job became stale – repetitive. I lost hope that things would ever change, and, more importantly, that I could even influence change. The result? I stopped caring. Is that a fault of management? Most definitely. Is it also a fault of my own personality and work ethic? Yep, that, too.
I’ve never quit a job out of malice. But I came close once. During a performance review with my immediate supervisor and the president of the company, I was asked what my “dream job” would be within the organization. I think everyone probably gets asked this at some point. It’s a standard interview question designed to uncover where you’ll fit in. Of course, the problem with this is that it only works if you answer honestly. And who is ever completely honest answering a question like this during an interview? But during a performance evaluation? This is a rare opportunity to get reassigned to a better project or tweak your job description. I’d be an idiot to pass it up.
In a rare moment of unrestrained what-the-fuck-it-cant-hurt-to-try I was totally honest. I said I’d scrap the entire corporate website and rebuild it using best practices – valid HTML and CSS, minimal use of Flash, and a heavy emphasis on making everything accessible. I explained that not only would this help our search engine rankings, but we’d be better people for ensuring that anyone willing to try would be able to access our website – whether it be through a cellphone, text browser, or screen reader.
There wasn’t much hesitation in the answer I got back. The COO said flatly “Who cares if our website is accessible? Blind people aren’t going to buy [our product name] anyway.”
I was a little shocked. Up until this point I had thought quite highly of him and the corporate ideals he and the other executives often spoke about. I had even gotten swept up in the company’s mantra (which I’ll refrain from repeating here) and genuinely believed we could have a positive impact on the world. But with that statement I realized that despite all the corporate good intentions, in the end he was just another MBA out to make a buck.
Like I said above, I didn’t leave out of malice. I left (in fact, two weeks later) out of disappointment.
So, what’s the point of this story? The point of this whole post? It’s that I don’t think there can be a real answer or set of answers to ensure employees stay with a company long term. No corporation can be everything to every employee. They shouldn’t even try. Instead, they should focus on fostering the ideals that they as a company hold dear. They should communicate those ideals strongly in the workplace. The result will be a natural sifting-out of employees who don’t match. The stronger those beliefs are held in the corporate culture, the faster the sifting, and the less time wasted on both sides. Employers don’t waste time and money trying to fit round employees into a square cubicle. And employees can quickly move on with their lives and to a job that fits who they are.
Anders Pearson posted an interesting programming puzzle today on Thraxil.org:
Take the names of two U.S. States, mix them all together, then rearrange the letters to form the names of two other U.S. States. What states are these?
He found out about it from Mark Nelson who, in turn, heard it on NPR. It’s not a terribly difficult riddle if you take a moment to think about it. But from a programmer’s perspective it smells like one of the many brain teasers we face in early Computer Science exams or job interviews. The puzzle isn’t so much about being the first person with the correct answer or even getting the right answer at all. These problems are designed to reveal how you approach them. They’re designed to show how you think.
That’s what intrigued me so much about Anders’ post. He used it as an opportunity to compare programming styles between low and high level languages (and, by extension, how low and high level programmers think). In this case, Nelson solved the problem in C++ using STL libraries. (Damn.) Anders wrote his solution in Python.
Both solutions are valid. Each arrives at the same answer. However the ease at which the solution is attained is radically different – not only in time spent writing the program but also in the readability of the code.
I see this dynamic every day in the code I write. My day job uses PHP, but at night I’m programming in Objective-C. I’m still a novice at ObjC and Cocoa (although I do have a strong C/C++ background), so perhaps inexperience is clouding my judgement, but there are so many times where I find myself longing for the flexibility of a high level, scripting language.
In any case, here’s my analogous solution to the 50 States problem using PHP. (For obvious reasons, my code is nearly line by line identical to Anders’ Python solution.)
I’ve seen a lot of visitors searching for information on enabling PHP5 in Mac OS X Leopard. It turns out to be quite easy. Leopard ships with Apache 2 and PHP 5 pre-installed. To enable PHP simply:
Open your favorite text editor and edit /private/etc/apache2/httpd.conf
Uncomment line number 114. It should read
LoadModule php5_module libexec/apache2/libphp5.so
Open System Preferences and go to Sharing
Stop and then restart Web Sharing
That’s it!
PS – If you want any easy way to setup and manage virtual hosts on your Mac, check out VirtualHostX.
Select a file in Finder and press ↩ to rename it. Finder now excludes the file extension from the initial text selection. This leaves you free to type a new name without overwriting over the extension.
If you squint your eyes and look to the side of your monitor, Leopard is actually quite attractive.
VirtualHostX is broken at the moment. That’ll be fixed as soon as I roll out Apache 2 support.
The new iCal is hot. I love that there is now a physical separation between local and subscribed calendars.
I just noticed all pop-up menus have rounded corners – feels very Web 2.0 inspired.
My PHP5/MySQL install got borked. Solution…
sudo mkdir /var/mysql
sudo ln -s /tmp/mysql.sock /var/mysql/mysql.sock
Enable PHP5 /private/etc/apache2/httpd.conf (line 114)
Add your vhosts to /private/etc/apache2/extra/httpd-vhosts.conf
Why does the Finder sidebar use the traditional special folder icons when the actual folder icons are the ugly-cant-tell-them-apart-ones? (Can’t wait for Candybar to start working.)
When you look at the translucent menu bar by itself, it’s sort of nice. But if there’s a window pushed up against it the transparency really stands out and looks strange. It’s not a good contrast.
I just used iChat’s new screen sharing function to help a co-worker from across the room. Normally I have to get up and walk over there. Not any more!
What the crap?? Command-tabbing doesn’t rotate back around when you reach the end of the application list. Wait. False alarm. It does – just not when you use the arrow keys to move through the list.
It reminded me of the time in my mis-spent youth when I got lost in IRC, spending evenings heckling the TV with my IRC friends. This is the geek equivalent of being stoner, by the way, with roughly the same effect on cognition . . . It’s a very loosely-coupled conversation.
Spot on.
An interesting (but probably useless) hack would be to take an opensource IRC client and wrap it around Twitter’s API.
I was out of town for a couple days last week and had a lot of time to kill at my hotel. Needing something to do I decided to write my own URL shortening service. This is hardly an original idea – TinyURL.com has been around for a long time. Newcomer url(x) is great, too. However, there are changes I’d like to see made to both sites so I decided to roll my own. Plus, it turned out to be a fun computer science-y puzzle (more on that later). I’ve called my shortening service foo9.net.
First off, I wanted the site to load fast. That meant no ads and no extra HTML cruft – only the necessary basics. It’s supposed to be a service – not a billboard. The homepage for foo9.net is as lightweight as possible. Especially when compared to TinyURL’s.
I also wanted to eliminate as many “clicks” as possible for the user. With url(x), you have to move the mouse and click on the URL field to select it. foo9 automatically selects the URL field for you. Just load the page and hit paste. Plus, once the URL has been shortened, the new link is already highlighted and ready to copy. We also provide a clickable link if you want to test it. You can even password protect your new URL so only trusted friends can access it.
After shortening your link, foo9 gives you a “secret” URL that will let you track how many visitors your link has had. I was considering tracking referral data and maybe even unique IP addresses, but decided against it for privacy reasons. If enough people ask for it I might implement these stats.
foo9 even has a simple developer API so you can shorten links from within your own applications – no need to visit our site.
And Now The Computer Science-y Part
URL shortening is neat problem to think about because the goal is to make the new URL as short as possible. The immediate solution is to simply hash the URLs. The problem with this is most hashing algorithms give you a long string of characters – usually 35 or more – which is how they can (in theory) guarantee there won’t be any collisions. If you hash a URL and then trim the new value to a small number of characters the hash loses all practical value.
The solution is to use an ID that increments with each new URL. We could simply assign an ID field to each URL and have the database auto-increment it. That’s a good start, but the shortened URLs quickly grow in length. TinyURL claims 47 million URLs. That would mean eight character long IDs. While probably shorter than the original URL, we can do better.
The reason the ID’s grow so quickly is because they’re counting in base 10. If we increase the symbols in our number system we can keep the URL short longer. An easy choice would be to use hexadecimal – base 16 – which counts 0 through 9 and the continues with A through F. That’s good, but once again, we can do much better.
foo9 uses a base 31 system. It’s a strange choice, but here’s why.
To maximize the number of numbers (and still keep things simple) I chose to use 0 – 9 and then A – Z for a total of 36 possible choices. With that many combinations the URL will stay relatively short for a long time.
So if base 36 works so well, why drop down to base 31? Usability, of course.
The full 36 character list has some hard to read symbols: O, 0, 1, I, and L. When they’re butted up against one another in a URL it’s hard to distinguish between each. URLs are normally sent around via copy/paste and clicking. But in the rare occurrence that you need to speak a URL to someone or transcribe it by hand, you’ll be glad the letters don’t look alike. So, 36 characters – take away the 5 look alikes – and you’re left with 31:
2 3 4 5 6 7 8 9 A B C D E F G H J K M N P Q R S T U V W X Y Z
It’s a fast solution and keeps the URL short. Here’s the base-10 to 31 function:
A lesson for all you iPhone owners out there: don’t leave your phone on a table that your dog can reach.
I got out of the shower this morning to find my dog, Gracie, gnawing away on my phone in the middle of the living room. I was a little upset, but life goes on. How’d the iPhone fare against the jaws of a 25-pound canine beast? See for yourself . . .
The bottom backside has a bunch of teeth marks in it. I can tell she was really biting into it hard. The ringer/speaker is still alive – barely. Even on full volume it’s real quiet now. The screen protector took the most damage. She bit holes right through a number of places, bent it back, and nearly had it peeled off.
But the screen? The actual glass? Not a scratch on it. Wow.
I’m a web developer by trade. I’ve been programming for the web for over ten years – prior to that I was (god forgive me) a VisualBasic and then .NET developer. Ever since switching to Mac I’ve been interested in building software for OS X. Over the last few years I read up on Cocoa and wrote a few practice apps. I followed most of the Cocoablogs and even read Aaron Hillegass‘ book. However, the lack of a good idea and all of my other web commitments kept me from digging in and writing my first real Mac app.
That all changed this summer when I attended WWDC. Talking with so many incredible developers really motivated me. A few months and one hell of a learning curve later VirtualHostX was born.
When I say “learning curve” I don’t mean actually writing the code. I’ve got a pretty strong C/C++ background (thanks, MTSU). That, coupled with my old VB skillz, made learning Cocoa and Objective-C an absolute joy. The learning curve was figuring out how to actually sell the damned thing. How do I handle user registrations? License codes? Program updates? Order tracking and book keeping?
Like I said, I’m a web developer. Tying everything together into a single “management console” seemed like the obvious solution. That solution is what I want to present here. Hopefully other new developers like myself will find it useful. Who knows? If there’s enough interest I’d even be happy to give out the source code, too. Until then, let me show you Appcaster.
. . .
The name Appcaster comes from the term “appcast” coined by Andy Matuschak. It handles pretty much every management function related to selling my app and distributing updates. Here’s a screenshot of the home page after first logging in.
The first tab, Applications, displays a list of all the apps I’m managing. Obviously, for me, there’s only my one program listed. It shows the newest version, when it was released, a link to the download, and a link to the program’s appcast feed. Clicking on the program’s name we can edit its details.
You can edit the app’s name, give a description, and also choose whether or not the appcast feed it generates (more on those later) include an MD5 checksum to verify the download. Much cooler, though, is the upload information. When you upload a new version, you have a choice of storing the file locally on your server or you can host it in Amazon S3. If your app should happen to get dugg or suddenly generate a ton of traffic, having your download hosted on S3 guarantees users will be able to download it – even if your web server should go down. It’s cheap, reliable, and secure hosting for your files. Don’t take my word for it. Read about Panic’s success with Coda.
So, now that you’ve got your app’s details filled in, it’s time to upload a new version. Click the Versions tab and . . .
You get a listing of all the releases your app has gone through – the release date, download link, file size, and MD5 checksum (if applicable). Basically, this is the same information that will be used to generate your program’s appcast feed. Let’s release a new version.
I like to make things as easy as possible – automation (however simple) turns me on. So, when you click the New Version tab, Appcaster automatically fills in the next incremented version number and release title. Also, the release notes field is smart. Individual lines are automatically converted into a bulleted list when submitted (so they look nice in the Sparkle update window). Choose your file, and click upload. If you’ve chosen to store your file in Amazon S3, Appcaster automatically uploads it onto their server and renames the file to conform to Sparkle’s naming conventions. (It picks the correct filename if you choose to store your file locally, too). The S3 integration comes from an Amazon web services PHP library I wrote last year.
Once the upload is completed, the new version automatically becomes available in your appcast feed which means your users will get notified of a new update as soon as Sparkle checks-in again. Also, the download link on my website is updated to point to the new release. Like I said, automation turns me on.
I’ll skip the screenshot since it looks the same as the previous one, but you can also edit an exiting version to change release notes or even replace the file your originally uploaded. Also not pictured is the ability to have multiple appcasts for each app. This lets you offer users the choice between checking for stable updates or downloading your latest bleeding edge build.
So that’s how you manage your releases. Let’s move on to payment processing. I chose PayPal over other 3rd party solutions like Kagi and eSellerate because it’s a) ubiquitous (who doesn’t have an account?) and b) it would be dead-easy to integrate with my website. Another consideration was that I didn’t want to blindly insert Kagi or eSellerate’s registration module into my application. I like knowing how things work – even if that means rolling my own solution. Luckily an open-source registration system exists. AquaticPrime is awesome. It was a cinch to add into VirtualHostX and even easier to tie into Appcaster since it comes with PHP example code.
I’ve setup my PayPal account to use Instant Payment Notification (IPN) to talk with Appcaster. Every time a user purchases my program, PayPal pings my server with the details. The order details are stored in a MySQL database and also emailed to my billing email address on GMail for backup purposes. Appcaster then generates the user’s license file and emails it to them in a thank-you letter.
Recent orders are displayed and clicking on a user’s name takes you to their order details page with the raw PayPal output.
Looking at the tabs above, I can click on Download License and download a copy of their license file. Likewise, Email License re-sends the thank you letter containing their license they originally received when they ordered.
In addition to managing existing orders, you can manually enter a new order.
Moving on to Stats, since Appcaster creates your appcast feeds, it also receives the anonymous update data sent by Sparkle Plus every time a user checks for a new version.
You can get an aggregate view of you users’ system configurations, or you can drill down deeper and look at the raw Sparkle update data.
It’s important to remember that your program’s stats don’t stop with what you collect yourself. You need to keep an eye on what other people are saying, too. Appcaster pulls in recent comments from users on iusethis.com, MacUpdate, and VersionTracker as well as total downloads and ratings information.
. . .
So that’s it. That’s Appcaster in a nutshell. I couldn’t imagine keeping track of all this data with anything less. It makes me think that other independent developers must have backend systems like this. Right? I’m really curious because I’ve never heard anyone discuss it before. I’d love to find out. Anyone care to share?
A few final notes. Overall, Appcast took about five hours to build. (It’s based on the Simple PHP Framework – a big help.) It has easily saved me that much time and more. Like I said above, if others are interested I’m more than happy to share the code. It ties together PayPal, AquaticPrime, and Sparkle in a way that I think many developers could benefit from.