March 29, 2007
Software Development as a Collaborative Game
Alistair Cockburn maintains that software development is a cooperative game:
If software development was really a science, you could apply the scientific method to it. If it was really engineering, then you could apply known engineering techniques. If software development was a matter of producing models, then you could spend your money developing models.However, it is none of those. Software development is a "game", a game of speed and cooperation within your team, in competition against other teams. It is a game against time, and a game for mind-share. You should spend your money to win that game.
Viewing software development as a game gives you better ideas on where to spend your money, how to structure your teams, and how they should allocate their efforts.
It's a fascinating, thought-provoking article on the essential nature of software development. I can now see why Bill de hra calls Cockburn "the agile world's best kept secret." I've only quoted the conclusion; I urge you read the complete article to get a full explanation of Cockburn's rationale behind the game analogy.
This game model of software development has stood me in good stead recently, as I evaluate military software projects and open-source software development. In some of the military software projects, what we see is predominance of the career and corporate-enhancing infinite games. It is quite clear that delivery of the software is a secondary concern, and growing the company, growing personal influence, or growing the career is what is many people's minds. The logic of the funny contractor behavior doesn't make sense until you realize they are playing a different game, in which different moves are called for. Then it suddenly all makes sense - even if you don't like it.Open-source development is different because it is not a resource-limited game, nor is it finite and end-point directed. Linus Torvald did not say, "We'll make a shippable copy of Linux, and then we can all go home." No, Linus is around, and it will evolve. The game is interesting as long as it is interesting. Any number of players may show up, and they are not on a time-line. The game will abandoned as soon as it stops being interesting for the players. In that sense, it is much more like musicians playing together, or carpet-wrestling, or lego building. It is a cooperative game that is not directed toward "reaching the goal", and is not built around managing scant resources. And so the moves that make sense in open-source development naturally don't make the same sense for a standard resource-limited, goal-seeking software development project.
The idea that games can inform real world design problems is not a new one; Damion Schubert's presentation What Vegas Can Teach MMO Designers is full of similar insight. Casinos are the original MMORPG spaces, as outlined in Damion's presentation (ppt).
The concept of software development as a collaborative game appeals to me. It speaks to a deeper level of engagement in the process than "I get paid to do this." We play games because we derive some kind of essential satisfaction from playing them. You might even say it's fun-- either the explicit kind, or the implicit kind.
Fun may be more relevant than you think to your project. Raph Koster is a notable game designer and programmer who writes entire books on the theory of fun.
Take a minute to read Raph's classic theory of fun (pdf) presentation. What you'll eventually realize is that designing for fun isn't just important for game developers. It's important for all software developers.
Do users want to use your application, or are they forced to use it?
In a recent ETech07 presentation (also available as a PDF), Raph connects the dots more explicitly. He deconstructs amazon.com, ebay.com, and linkedin.com for what they really are: massively distributed games. You'll want to read the transcript of the talk along with the sides to dig a little deeper into the concepts:
As you accomplish more, there need to be variant challenges. Connecting to a CEO on LinkedIn vs. connecting to the pr dude = different. What you want is for the game to acknowledge the fact that it's tougher to get on Reed Hoffman's linkedin rather than someone who sells ads.Social media is about cooperation, but the core of games is competitive. As soon as you give people a ladder to climb, they'll climb it. Ratings. Metrics of contribution. Other people need to see it to measure against it.
Software development is a collaborative game that you play, willingly or not, with your team and your users. You might say the secret of the game, then, is learning how to play the game so that everyone is having fun.
March 28, 2007
Learning on the Battlefield
I occasionally get emails from people asking how to prepare for a career in software development. Some are students wondering what classes they should take; others have been bitten by the programming bug and are considering their next steps.
I always answer with the same advice. There's no substitute for learning on the battlefield.
It appears to me that software development is happening in industry, not in the universities. Universities are great for problems that can be solved by sitting alone and thinking or experimenting for months on end. Universities were great for giving us automata theory, complexity analysis, compilers and the like. But universities are not at all well suited to understanding what is happening during software development.Software development at the moment is much more like the early manufacture of samurai swords, shields, and battlefield tactics. You make a pile of swords or war tactics, send them onto the battlefield, and see which ones worked better. Then you make different swords and tactics, and so on. You have to be on the battlefield.
![]()
I can't imagine learning the things I've learned while sitting peacefully in my office reflecting. Most of my original reflections and predictions were just wrong. So any one of you who is interested in this topic probably has to work as a developer or consultant, so you can see the moment-to-moment action and get raw data.
Of course, software development only teaches you how to talk to your computer. Higher education is still worthwhile because it teaches you how to talk to people. With a good educational background, you'll learn how to read effectively, how to write coherently, and how to think critically amongst your peers.
If I were founding a university I would found first a smoking room; then when I had a little more money in hand I would found a dormitory; then after that, or more probably with it, a decent reading room and a library. After that, if I still had more money that I couldn't use, I would hire a professor and get some textbooks. (Stephen Leacock)
For a fast-moving field like computer science, the work you're doing is far more relevant than any classes you're taking. If you must choose between formal schooling and work experience, always choose work. If you're in school, aggressively pursue real-world experience that compliments your schoolwork.
Fortunately, this is a battle you can fight on multiple fronts:
- If you're a student, seek out internships like your life depends on it. Some of the best programmers I've ever met have been college interns. Intern somewhere that you can absorb and learn as much as possible. You won't make much money, but the experience will be priceless.
- Participate in local user groups. User groups are an unbeatable resource for people just starting out in their careers; they're an excellent source of advice and mentorship.
- Contribute to an open-source project. There are thousands, so pick whatever strikes your fancy. But pick one and really dig in, become an active contributor. Absolutely nothing is more practical than working collaboratively with software developers all over the globe, from all walks of life.
- Publish articles. The cleverest code in the world won't help you if you can't clearly communicate how that code works, or what it's for. Try your hand at writing. CodeProject is an excellent sandbox to practice in. Publish an article and the large, active CodeProject community will let you know how you're doing with ratings and comments.
- Start a blog. Pick a writing schedule and stick with it; I recommend once a week at minimum. Select a general theme for your blog and write on topics related (at least tangentially) to that theme. And don't be an echo chamber.
You don't have to do all these things, but if you're serious about your career, pick at least two and follow through. For more detailed advice, I highly recommend Rob's advice on how to become a programmer.
In software development, you learn by doing. As long as you're out on the battlefield fighting the good fight, you're bound to improve.
March 27, 2007
Going Commando - Put Down The Mouse
One of the quickest ways to increase your productivity on the computer is to go commando: stop using the mouse. When you stop relying on the mouse for everything, you're forced to learn the keyboard shortcuts. Jeremy Miller calls this the first step to coding faster. I agree.
Keyboard shortcuts are almost always more efficient than using the mouse to point and click your way around the computer-- but you'll never learn them if you keep leaning on your trusty mouse to do all the work. Stop for a moment, resist taking the easy way out with the mouse, and force yourself to learn at least one new keyboard shortcut per day. Yes, it's a tiny bit of extra work. But it will pay off down the road: you'll spend less time mousing around, and more time getting things done.
I'm not anti-mouse by any means. I remember when mice were new; I'd never want to go back to the bad old days of keyboard-only interfaces. But most people I've observed using the computer these days rely almost exclusively on the mouse, to the detriment of their overall computer experience. Here are a few examples of how even the simplest keyboard shortcuts can make your daily routine easier:
- Logging in with the keyboard, using Tab and Enter.
- Going to a website using Alt+D and Control-Enter.
- Searching using CTRL+E then Enter.
- Editing text and moving your cursor with basic textbox shortcuts.
That's just the tip of the iceberg. Most applications have tons of useful keyboard shortcuts; you just have to put down your mouse long enough to discover a few of them. It's a shame more applications don't go out of their way to make keyboard shortcuts more discoverable. At the very least, I'd like to see Office 2007 type behavior where, as you press the keyboard accelerator key, all the possible keyboard shortcuts "light up".
Unfortunately, navigating through websites is nearly impossible without a mouse, due to the highly mouse-centric nature of HTML. I've given up on trying. But it is possible, if you're a die-hard. Unless you enjoy pressing the tab key umpteen million times, you'll definitely want to check out Jon Galloway's mouseless computing recommendations, wherein he conquers the HTML keyboard challenge.
For best computing results, try to use your mouse and your keyboard to the fullest. But to do that, you've got to actively wean yourself off the mouse. Try going commando every now and then. It will be awkward and painful at first. You'll be sorely tempted to switch back to your old faithful mouse to get things done. Resist this urge! I guarantee whatever you're trying to do is possible-- and ultimately quicker-- if you persist with the keyboard.
March 26, 2007
What's Wrong With The Daily WTF
Alex Papadimoulis originally invited me to be a guest editor at The Daily WTF nearly six months ago. I was honored and accepted immediately. Since then, The Daily WTF has been rechristened Worse Than Failure.
I'm a big fan of Alex and WTF; his blog is fantastic, and WTF went from being a brilliant, hilarious germ of an idea to a staple of many developer's daily reading lists.
It's ironic, then, that what I wrote ended up being a direct criticism of The Daily WTF. It's almost like I've fallen into the Spolsky rut; invite me to speak at your big important Java conference, and I'll create a session that tells you why you're all idiots for using Java. Or, perhaps I was channeling Groucho Marx. One of his most famous jokes goes something like this: I sent the club a wire stating, please accept my resignation. I don't want to belong to any club that will accept me as a member.
I give Alex tremendous credit for finally posting my entry, even though it never quite fit the WTF format. I hope it doesn't feel too much like a public service announcement, but it's something I absolutely had to get off my chest. It's a topic Dennis Forbes has struggled with as well:
This is a repeating theme: On the one side are the great programmers, and on the other are the people endlessly bound to give TheDailyWTF source material.Do people really think such a schism exists? Is the impression that great developers are infallible, never creating any bad code at all, ever? Are bad programmers just stumbling from one WTF to another?
Of course not.
I fear the output of any developer who claimed that they've never written bad code. I would fear them because they're either bald-faced liars -- believing that simply saying it repeatedly will somehow convince others into this fiction -- or they're completely blind to their own weaknesses.
Every developer in the real world has had bad days, brain faults, or bad interpretations of new languages, environments or libraries. It's simply a given of the profession.
I have no problem at all with the entertainment value of WTF. Laughing at Rube Goldberg code is therapeutic, even educational. But whether the code in question is catastrophically stupid or just plain ill-advised, we have to do something about it. Until we do, we are implicitly perpetuating the painful, costly cycle of bad coders writing bad code, ad infinitum. And that hurts all of us.
Reprogramming WTF code isn't enough. We need to reprogram the developers producing the WTF code. With my guest article, I was trying to inspire readers to take on the burden of reprogramming bad developers, rather than passively waiting for the bad developers to come to their senses on their own. That strategy never works.
I can absolutely guarantee that the kinds of developers who could benefit most from reading WTF simply do not-- and never will-- read the WTF website. Individually, personally, we have to do more to reach out to these developers: mentoring, apprenticeship, user groups, peer pressure, code reviews, etcetera. Do whatever you can, whatever makes sense to you, but do something. Pitch in so the next poor sap won't have to deal with WTF code, or at the very least, can benefit from slightly less crazy WTF code in the future.
I know it's asking a lot. It's tempting to get your daily fix of drive-by amusement and move on. But I believe it's our collective duty to leave the profession of software engineering better than we found it. There's so much we can do, and WTF is merely a starting point.
March 23, 2007
Folding: The Death of the General Purpose CPU
A few recent articles have highlighted the disproportionate contribution Playstation 3 consoles are making to the Folding@Home effort. The OS statistics page for Folding@Home tells the tale:
| TFLOPS | Active CPUs | Total CPUs | |
| Windows | 152 | 160,173 | 1,626,609 |
| Mac/PPC | 7 | 8,776 | 95,435 |
| Mac/Intel | 9 | 2,864 | 7,400 |
| Linux | 43 | 25,239 | 216,067 |
| GPU | 43 | 733 | 2,228 |
| PS3 | 659 | 26,911 | 29,843 |
There are a couple caveats to bear in mind when reading this chart:
- The measurement of FLOPS isn't an exact science. It would be more accurate to compare actual work units returned, but I don't see any way to do that from the folding statistics page.
- Current PC and Mac / PPC contributors span the entire gamut of CPUs released in the last seven years.
- Folding does cost money, in the form of electricity. Superior clients offer efficiency: bang per watt. You could make a compelling argument that certain clients with low efficiency aren't worth the cost of the electricity they're using. For reference, a PS3 and a gaming-class PC both use about 200 watts of power under load.
The Playstation 3 is indeed dominating the charts; as of this writing, the PS3 is responsible for a whopping 72 percent of the computing power in the entire Folding@Home project.
UPDATE: as of 3/26/2007, the F@H network has arbitrarily halved the TFLOPS score for the PS3.
It's only a matter of time-- a few weeks at most-- before the PS3 constitutes more than 95 percent of the computing power in the entire Folding@Home network. This doesn't surprise me in the least. The Playstation 3 can harness the considerable power of its specialized Cell CPU to crunch work units far more efficiently than any general purpose CPU ever could.
If you look closely at the chart, you'll see even more powerful evidence of the dominance of specialized processors.
GPU clients run on modern, high-end video cards. The GPU on these video cards is even more specialized than the Cell processor in the PS3.
The GPU client is limited to the current high-end ATI X1800 and X1900 video cards at the moment, which are already a generation behind NVIDIA's newest 8800 series. Even so, the GPU clients are almost 2.5 times faster than the PS3. Of course, this performance differential is more than balanced by the fact that PS3 is an easily obtainible (albeit somewhat expensive) consumer item; it's trivially easy to add one to the Folding@Home network, whereas the Folding@Home GPU client is quite immature, and few users have the necessary high-end ATI video cards to use it.
But the real lesson of this chart lies in the OS X / Intel data point. Intel-based Macs are, by definition, based on only the newest Intel processors-- Core Duo or better. Even so, it's an utter blowout:
| Intel Core Duo | 1x |
| PS3 | 7.8x faster |
| GPU | 18.6x faster |
With these kinds of performance ratios-- and I expect the performance gap to widen every year-- there's almost no point in adding general purpose CPUs to the folding network any more. It's a waste of time, effort, and electricity.
For folding and other distributed computing efforts, it's the death of the general purpose CPU as we know it.
March 22, 2007
Top 6 List of Programming Top 10 Lists
Presented, in no particular order, for your reading pleasure: my top 6 list of programming top 10 lists. To keep this entry concise, I've only quoted a brief summary of each item. If any of these sound interesting to you, I encourage you to click through and read the original author's thoughts in more detail.
Jerry Weinberg: The 10 Commandments of Egoless Programming
- Understand and accept that you will make mistakes.
- You are not your code.
- No matter how much "karate" you know, someone else will always know more.
- Don't rewrite code without consultation.
- Treat people who know less than you with respect, deference, and patience.
- The only constant in the world is change.
- The only true authority stems from knowledge, not from position.
- Fight for what you believe, but gracefully accept defeat.
- Don't be "the guy in the room."
- Critique code instead of people -- be kind to the coder, not to the code.
Dare Obasanjo: Top 10 Signs Your Software Project is Doomed
- Trying to do too much in the first version.
- Taking a major dependency on unproven technology.
- Competing with an existing internal project that is either a cash cow or has powerful backers.
- The team is understaffed.
- "Complex problems require complex solutions".
- Schedule Chicken
- Scope Creep
- Second System Syndrome
- No Entrance Strategy.
- Tackling a problem you don't know how to solve.
Omar Shahine: Top 10 Tips for Working at Microsoft (or Anywhere Else)
- Process is no substitute for thinking.
- Get out of your office.
- Use your product (the one your customers will).
- Fix things that are broken rather than complain about them being broken. Actions speak better than your complaining.
- Make hard problem look easy. Don't make easy problems look hard.
- Use the right communication tool for the job.
- Learn to make mistakes.
- Keep things simple.
- Add value all the time.
- Use their product.
Michael McDonough: The Top 10 Things They Never Taught Me in Design School
- Talent is one-third of the success equation.
- 95 percent of any creative profession is shit work.
- If everything is equally important, then nothing is very important.
- Don't over-think a problem.
- Start with what you know; then remove the unknowns.
- Don't forget your goal.
- When you throw your weight around, you usually fall off balance.
- The road to hell is paved with good intentions; or, no good deed goes unpunished.
- It all comes down to output.
- The rest of the world counts.
Andres Taylor: Top 10 Things Ten Years of Professional Software Development Has Taught Me
- Object orientation is much harder than you think.
- The difficult part of software development is communication.
- Learn to say no.
- If everything is equally important, then nothing is important.
- Don't over-think a problem.
- Dive really deep into something, but don't get hung up.
- Learn about the other parts of the software development machine.
- Your colleagues are your best teachers.
- It all comes down to working software.
- Some people are assholes.
Steve Yegge: 10 Great Books
- The Pragmatic Programmer: From Journeyman to Master
- Refactoring: Improving the Design of Existing Code
- Design Patterns
- Concurrent Programming in Java(TM): Design Principles and Pattern (2nd Edition)
- Mastering Regular Expressions, 2nd Edition
- The Algorithm Design Manual
- The C Programming Language, Second Edition
- The Little Schemer
- Compilers
- WikiWikiWeb
You may wonder why I included a top 10 list from someone who is clearly a designer and not a programmer. I agree with Joey deVilla:
Software development is a kissing cousin of engineering (if not an engineering discipline itself), and blends creativity with math and science. That's why I find that a lot of advice to creative types is also applicable to software developers.
You may also want to contrast and compare my recommended reading list with Steve Yegge's. And yes, there is a reason Refactoring and Design Patterns aren't on my list, just as I'm sure there's a reason Code Complete is not on Steve's list.
March 21, 2007
A Race of Futuristic Supermen!
I've seen a lot of painfully bad IT web comics in my day, but I'm happy to say that Bug Bash, by Hans Bjordahl, is not one of them.
This particular strip is one of my favorites because it hits so close to home. Software developers truly believe, in their heart of hearts, that they are typical users. Be sure to check out the sequel strip, How Good Software Goes Bad, Part II, and while you're at it, the rest of the bug bash archives.
March 20, 2007
Code Access Security and Bitfrost
The One Laptop Per Child operating system features a new security model-- Bitfrost. It's an interesting departure from the traditional UNIX and LINUX security model.
The 1971 version of UNIX supported the following security permissions on user files:
- non-owner can change file (write)
- non-owner can read file
- owner can change file (write)
- owner can read file
- file can be executed
- file is set-uid
These permissions should look familiar, because they are very close to the same security permissions a user can set for her files today, in her operating system of choice. What's deeply troubling -- almost unbelievable -- about these permissions is that they've remained virtually the only real control mechanism that a user has over her personal documents today: a user can choose to protect her files from other people on the system, but has no control whatsoever over what her own programs are able to do with her files.
In 1971, this might have been acceptable: it was 20 years before the advent of the Web, and the threat model for most computer users was entirely different than the one that applies today. But how, then, is it a surprise that we can't stop viruses and malware now, when our defenses have remained largely unchanged from thirty-five years ago?
BitFrost intends to address this problem by adding a new level of permissions that applies to code, not users: code access security.
Consider the Solitaire game shipped with most versions of Microsoft Windows. This program needs:
- no network access whatsoever
- no ability to read the user's documents
- no ability to utilize the built-in camera or microphone
- no ability to look at, or modify, other programs
Yet if somehow compromised by an attacker, Solitaire is free to do whatever the attacker wishes, including:
- read, corrupt or delete the user's documents, spreadsheets, music, photos and any other files
- eavesdrop on the user via the camera or microphone
- replace the user's wallpaper
- access the user's website passwords
- infect other programs on the hard drive with a virus
- download files to the user's machine
- receive or send e-mail on behalf of the user
- play loud or embarassing sounds on the speakers
The critical observation here is not that Solitaire should never have the ability to do any of the above (which it clearly shouldn't), but that its creators know it should never do any of the above. If the system implemented a facility for Solitaire to indicate this at installation time, Solitaire could irreversibly shed various privileges the moment it's installed. This severely limits or destroys its usefulness to an attacker were it taken over.
If I sound skeptical, that's because BitFrost sounds suspiciously similar to .NET framework code access security, as outlined in the System.Security.Permissions namespace. It's an enormous, complex list of explicit permissions you can grant or deny in your application's install manifest, exactly as described in the Solitaire example above. It sounds great in theory: establish a limited set of permissions your application needs up front, and let the .NET runtime worry about enforcing those permissions while your application is running.
But in practice, very few .NET developers make use of code access security. It appears Microsoft noticed that, too:
It seems Microsoft does not understand why nobody uses Code Access Security. In fact, Microsoft has a survey on the Internet. You can go ahead and answer the survey but if you have followed this entry, you should know what I am getting at: Code Access Security is too hard. Don't get me wrong, I think Code Access Security is great. In particular, the stack walk mechanism is terrific. But the policy side is way too hard for most people.
The CAS model was so profoundly unsuccessful in .NET 1.0 and 1.1 that ClickOnce in .NET 2.0 effectively does away with CAS. You're now exactly one click away from running a full trust application that can do whatever it wants to on your machine, with no restrictions of any kind.
Perhaps the OLPC's BitFrost model will fare better than .NET Code Access Security did. But somehow I doubt it. What good is a security model that's so cumbersome to use, nobody ever adopts it?
March 19, 2007
Primary Keys: IDs versus GUIDs
Long-time readers of this blog know that I have an inordinate fondness for GUIDs. Each globally unique ID is like a beautiful snowflake: every one a unique item waiting to be born.
Perhaps that's why I read with great interest recent accounts of people switching their database tables from traditional integer primary keys ...
ID Value -- ----- 1 Apple 2 Orange 3 Pear 4 Mango
.. to GUID keys.
ID Value ------------------------------------ ----- C87FC84A-EE47-47EE-842C-29E969AC5131 Apple 2A734AE4-E0EF-4D77-9F84-51A8365AC5A0 Orange 70E2E8DE-500E-4630-B3CB-166131D35C21 Pear 15ED815C-921C-4011-8667-7158982951EA Mango
I know what you're thinking. Using sixteen bytes instead of four bytes for a primary key? Have you lost your mind? Those additional 12 bytes do come at a cost. But that cost may not be as great as you think:
- The Cost of GUIDs as Primary Keys (SQL Server 2000)
- Myths, GUID vs. Autoincrement (MySQL 5)
Using a GUID as a row identity value feels more natural-- and certainly more truly unique-- than a 32-bit integer. Database guru Joe Celko seems to agree. GUID primary keys are a natural fit for many development scenarios, such as replication, or when you need to generate primary keys outside the database. But it's still a question of balancing the tradeoffs between traditional 4-byte integer IDs and 16-byte GUIDs:
| GUID Pros
| GUID Cons
|
I'm not proposing that every database switch to GUID primary keys, but I do think it's important to know the option is out there. If you're still on the fence, what should I choose for my primary key? has excellent advice and a solid analysis of the tradeoffs.
March 16, 2007
Creating User Friendly 404 Pages
We understand what 404 means: Page Not Found. But the average internet user has no idea what 404 means or what to do about it. To them, it's yet another unintelligible error message from the computer. Most 404 pages are unvarnished geek-speak. Consider the default 404 page under IIS:
The default 404 page under Apache is no better:
Internet Explorer tries to shield the user from these poorly constructed 404 pages by automatically substituting friendlier error messages:
It's not bad. It's certainly an improvement over the default 404 from Apache or IIS. But we can do better.
We can stop relying on the default behavior of our webservers and web browsers, and create our own custom 404 page. Unfortunately, many sites have custom 404 pages that are barely discernable from the generic webserver defaults. You wonder why they bother.
So, what exactly should a user-friendly custom 404 page do? Although there's an entire website dedicated to documenting funny 404 pages, funny isn't necessarily helpful. What can we do to help the user at this point? I have some ideas.
- Drop the 404
Yes, the HTTP response code is 404, but there's absolutely no reason that ever needs to be shown on the actual page. Error codes aren't helpful. A simple explanation of the problem in plain English is all that's required. Any 404 page that has the characters "404" on it, if not already an outright failure, is already well on its way to becoming one.
- Automatically notify you of the 404
Repeat after me: it is not the user's job to inform you about problems with your website. If you require the user to click a button to notify you about a 404, or if you require the user to fill out a broken link form, you have utterly failed your users. 404 notification should be automatic, and by that I do not mean "sit in my log files until I eventually have time to look for it". I suggest weekly or monthly 404 rollup reports, emailed automatically to the powers that be. I'd also recommend real-time email notification if there is a sudden spate of 404s, so you have an opportunity to fix the problem while it's still relevant-- before the world gives up on your seemingly nonexistent page.
- Try to find what the user was looking for and provide links to possible matches
Don't just put a search box on the 404 page and force the user to perform a search. That's a cop-out. Instead, automatically perform a search on their behalf, using the erroneous URL as the search input, and display those results on the 404 page. You can also try to correct the URL, based on rules derived from the top ten or top fifty observed 404 errors. Does the URL end in .htm instead of .html? Is it spelled wrong? Are your URLs case-sensitive? Was the page moved, renamed, or reorganized somewhere else? It's sensible to have a search box on your 404 page for convenience's sake, but forcing the user to perform a search should always be the method of last resort.
- Present links to the most popular or most recent items
If someone is visiting your website, statistically speaking, there's a good chance they are coming to see the same attraction everyone else is. Even if they aren't, your popular content is popular for a reason. Why not present links to your "greatest hits" on the 404 page? Similarly, if you run a periodic website like a blog, or a newspaper, display the last few articles or entries on the 404 page. And at the very least, you'll want a link back to the main website. Provide a filtered list of relevant links, and an errant user will never be more than one click away from escaping their current predicament.
- Keep the 404 page simple
Your 404 page should be brief, concise, and to the point.* You're already dealing with confused users who can't find what they're looking for. Don't add insult to injury by spamming the user with a giant, complicated 404 page containing a complete sitemap of your website. For example, the apple.com 404 page makes this mistake.
I found that Jakob Nielsen, A List Apart, and 404 Research Lab also had good advice on making 404 pages potentially user friendly instead of the geeky, incomprehensible dead end signs they usually are.
Unfortunately, I haven't had time to implement a better 404 page on my own website. Yet. If you're looking for live examples of 404 pages that get this right, I can recommend the 1976 design 404 page, as well as the useit.com 404 page. Sadly, this is an extremely short list because so few websites meet the criteria I outlined above. I sampled 404 pages from dozens of websites and most fail spectacularly, serving up 404 pages that are downright user hostile.
Whichever route you choose, never settle for the default 404 page. Replace it with a custom 404 page that is polite, illuminating, and most of all, helpful.
* But not too brief. You have to make your customized 404 page larger than 512 bytes, otherwise IE will assume it's a standard web server 404 message and replace it with its own friendly-ized version.

