Here's a collection of opinions I hold on what makes a great Developer Experience (DX). Note that some of these apply more broadly than their category (e.g. frameworks).
Something recently clicked. Developer Experience is a part of Software Architecture.
Frameworks and Libraries
- Onboard as fast as possible: To keep creatives in the flow, you want to enable them to get started as quickly as possible. Try to ensure frameworks and libraries optimize for getting started quickly. For example,
brew install bat. Optimize for quick iterations and fast feedback loops to the developer.
- Make upgrading easy: When making a major version change, limit the “blast radius” of the changes to make it easy for folks to update dependencies. Ideally, changes should start out opt-in with many months of lead time before landing in a major version. Then, major versions should include codemods – scripts that run code transforms to help automatically migrate code and fix breaking changes.
- Helpful error messages: When applicable, include hyperlinks in error messages to provide more context on how to solve the error. Your tools should be providing you feedback as you type. The faster, the better (e.g. type checking, linting) before runtime or compilation errors. Don't make me think.
This is what FB developers will see in their local sandbox when building features for the upcoming redesign. Regardless of your stance on FB the company, this is a really powerful example of how a considered developer experience can directly impact the end user experience.
- Strong defaults and conventions: Have an opinion about “the right way” to build software. For example, don't make me think about setting up routing, just use the file-system-based routing with Next.js. Don't make me configure compilation and bundling, just set up good defaults for me with webpack/swc/vite/esbuild.
- Provide escape hatches: The counter to strong defaults is to make sure there are escape hatches when the developer wants to break from the standard configuration. One reason Next.js was successful in the beginning was being able to easily override webpack without leaving the framework, whereas CRA required something like craco after ejecting.
- Reduce risk with dependencies: When you
npm i next, you only install 13 dependencies from npm. The rest of the dependencies are inlined into Next.js to have faster installation times and improved security. In the future, we'd like to turn Next.js into a single binary you can install.
- Lead with code: Developers want to write code. Give them code examples as starting blocks. Don't bury the lede.
- Solve the problem (aka: answer the question): Developers come to docs to learn the answer to a question, challenge, or problem they're trying to resolve. Give them the answer through multiple methods (video, text, tutorials, guides, etc.), so they learn the solution in a way that works for them.
- Automated documentation: When documenting an API, it's helpful to generate the docs from the source of truth (code) to ensure they remain in sync. For example, Vercel's API docs are auto-generated from its OpenAPI spec.
- Not just the happy path: The documentation is a reference guide for developers trying to get work done. Often, this means searching for an error and looking for a solution they can copy/paste. It's important to document the workaround and hacks, too. I'd rather acknowledge a gap in the product and unblock the developer rather than leave them frustrated.
- Optimize for skimming: Let's face it, we all skim. Especially when reading developer documentation. My eyes jump directly to code blocks, trying to find the solution to my given problem. To help provide the best DX, consider adding helpful code comments in the code snippets and showing multiple options or permutations of the desired feature/API.
- Be precise: Avoid technical jargon and idioms. If you're using an acronym, spell it out the first time and don't assume the reader knows what it is. Your docs should be accessible for both beginners and experts. Consider putting content that's helpful for experts but not critical for the happy path in collapsible “deep dive” sections.
- Progressively expose complexity: Keep the first-time experience crisp while progressively informing developers about more complex features as they continue building with the product. It's not feasible to expect developers to learn about the entirety of the platform to get started.
The four interfaces of developer experience: APIs, CLIs, GUIs, and docs. Treat each as a product, so that those products can treat developers as customers 🤍
- Don't break API workflows: API versioning should be very intentional and explicit. Err on the side of over-communication when making changes to APIs and give developers plenty of time to update to new versions. I've personally enjoyed Stripe's API versioning – they have an excellent post if you want to learn more. I've seen some instances where AWS sends a deprecation email about an API that's been stable for years, plus gives them years of upgrade time.
- Let me try out APIs quickly: Some of my favorite API documentation allows you to generate an API key and try out endpoints in a few seconds. Some even recognize that you're already logged in and personalize the page based on your account information. Square does this well. I also like GraphiQL for this – you view the entire graph schema, make requests, run mutations, format your code, and more.
An API needs designing. It needs a conscious language and consistent conventions. Standard auth. Paging. Careful error codes and messages. Versioning.