One of the most influential books of my software career is Steve Krug's Don't Make Me Think. While the book is a little dated now, it contains a plethora of software design gems. The one that stuck with me the most over the years is "Conventions are your friends" in Chapter 3.
Short of copying and pasting the whole section, here are my three favorite excerpts, starting with how an idea becomes a convention:
All conventions start life as somebody’s bright idea. If the idea works well enough, other sites imitate it and eventually enough people have seen it in enough places that it needs no explanation.
Why conventions are useful (emphasis mine):
As a rule, conventions only become conventions if they work. Well-applied conventions make it easier for users to go from site to site without expending a lot of effort figuring out how things work. (...) There’s a reassuring sense of familiarity...
Krug's ultimate recommendation:
Innovate when you know you have a better idea (and everyone you show it to says “Wow!”), but take advantage of conventions when you don’t.
Reduce, Reuse, Recycle
About a year ago I started on the initial product design that would become Runscope. Knowing we were building something completely new I wanted to introduce as few new concepts as possible. With Krug's voice in my head I was determined to make the best use of existing conventions.
I thought it would be fun to look back at the concepts we borrowed from other services with the benefit of hindsight. Which ones worked out? Which do we regret? Let's find out.
Buckets are the term we use for organizing your requests by project, app, customer or whatever else works for you. The name was borrowed from S3 but my intial idea for how they would work was more like Gmail's filters and labels. Using a well-known name from another developer tool with the behavior from another tool ended up being pretty confusing. Some early external feedback drove this point home and in the end buckets ended up much closer to their S3 brethren. Verdict: right decision after an adjustment.
In a fast moving stream of API calls, we were looking for a way to single out requests to save and easily reference later. Gmail's stars seemed like a good model for this. That ended up to not be the case. It forced people to use buckets for lighter-weight organization and those weren't a good fit for a variety of reasons. We needed a middle ground: a simple organization method within a bucket. Verdict: Not a useful convention for us.
We replaced Stars with Collections. They're conceptually similar to Gmail's labels: lightweight, user-defined and optionally one-to-many. With starred requests you had to attribute your own meaning to what starring meant. For collections, you define the meaning in the name you give them. It's much more flexible. Verdict: Right decision.
In need of a way to share API calls across account boundaries (e.g. to send to an API's support team) I immediately thought of Dropbox's shareable links. We implemented it just like Dropbox, with an explicit click to make a request public and create a public, shareable URL. Public links can be revoked at any time. Revoking and resharing creates a new, unique URL.
A funny thing happened. When asking people to share requests with us, people would click the link to go to the share preview page and then send us the URL for that page, even after clicking the 'Create Share Link' button and being presented with the public URL. Even making the button and resulting URL much more prominent didn't fix it. It took a little bit of
history.replaceState() cleverness to mitigate the confusion.
If I could go back, I'd simplify the feature. Every request would have a single non-guessable URL with a simple public/private visibility toggle (like Sentry). We may still do this, though revokability is an issue. Verdict: Right idea, but a little over-engineered.
The first version of our identity database had tables
Users with every user belonging to a single account. Frank wisely deleted that as soon as he saw it. People very rarely have a single organizational association. We ended up using the GitHub model of users and organizations (we call them Teams). This has given us and our customers a lot of flexibility. Verdict: one of the best early decisions...thanks Frank!
These examples are just from our initial Traffic Inspector product. In Runscope Radar (our new product for automated testing) we've also re-used concepts like integration testing assertions and variables with a Mustache-like template syntax.
Next time you're designing a new feature, listen to your inner Steve Krug:
Sometimes time spent reinventing the wheel results in a revolutionary new rolling device. But sometimes it just amounts to time spent reinventing the wheel.