Despite the lack of technical content here lately, I do actually still work for a living. I've been working on some implementation stuff lately, and have been struck by something that I've known for a while, but always comes home in a big way when I have to use someone else's UI. There's no substitute for use cases! I'm working with an API right now that was obviously designed by someone who thought it seemed like a good idea at the time, but didn't spend any time thinking about how this API was actually going to be used in the real world. The end result is that to actually use it, you have to go through way to many steps, each of which takes a different set of parameters that you may or may no already have. It's very frustrating.
I'm working with Scott on most of it, and from the very beginning of our involvement he predicted that we'd end up spending 6 hours a day reading docs and 2 hours coding to achieve the desired end result. It's actually been more like 7/1. I spend all day reading docs and trying to figure out how the API is supposed to work, then write 20 lines of code to solve the problem.
My own solution to this problem when I've been on the API writing side has been TDD. If I can write a test case, it at least forces me to think about how the API will be used enough to avoid some of the major pitfalls. On a larger scale project, the only solution is full-blown use case analysis. Write the use cases first, then figure out what the API should look like. Too often a hard-core technologist designs the API in the way he feels best exemplifies the underlying data structures. The problem is that the users almost never care about the nature of the underlying data structures. They need high level methods that answer questions, not CRUD based data exposition. At the very least, TDD forces us to think through what some of those questions might be. It's easy to miss some, however, so you really need to do use cases to find out what all the questions are before you write the API.