On making room for craft
I’m building the design engineering practice at DuckDuckGo, and one of the principles I’ve written down is to reduce scope before reducing quality. I like the principle. The awkward bit is making it mean something when there’s a deadline and more work than time.
Agreeing that we should care about the details is fairly easy. Deciding which feature to leave out so we’ve actually got time to finish the others is where it gets awkward.
That’s the part I want us to get good at. We’re still building the practice, so this is an intention rather than a story about having solved it. But I don’t want our standard of work to depend on somebody finding a spare evening to make the product feel coherent.
Put the whole interaction in the estimate
Take an imaginary export feature. People need to download a report, and we’d like to give them a choice of file formats, saved preferences and a history of previous exports.
The tempting version of the plan lists those capabilities and estimates the work to build each one. Then we start implementing and discover that generating a report takes a while. Someone needs to explain that wait. Exports can fail, so we need a useful failure state. The button can be pressed twice, and we need to decide what the second press does.
None of those things is particularly surprising once you think about someone actually using the feature. They just weren’t visible in the list of capabilities.
If we describe that work as polish, it becomes very easy to defer. The export works, after all. You press the button and eventually a file appears. But the person who presses it doesn’t know whether anything is happening, whether they should try again or whether they’ve broken something.
I’d rather estimate the experience of requesting and receiving a report. That includes what happens whilst the system is working and how someone recovers when it fails. Extra formats and saved preferences can then be separate decisions with their own costs.
| Keep in the first release | Consider for a later release |
|---|---|
| One useful export format | Additional formats |
| Clear progress and completion feedback | Saved export preferences |
| An understandable failure and a way to retry | A browsable export history |
| Keyboard access and protection against accidental duplicate requests | More elaborate transition effects |
The list would change with the audience. Someone might need two formats from the beginning, or rely on the history to do their work. I want those to be decisions we make deliberately, so the plan doesn’t only fit because we’ve quietly left out half of what happens after pressing the button.
Be specific about what needs care
Craft can become a frustrating word if it means whatever the most particular person in the room wants it to mean.
I care about motion, typography and the way one surface relates to another. I can happily spend time on a detail that somebody else barely notices. That doesn’t make every improvement equally important to the product we’re trying to ship.
Emil’s writing about when animations are useful is a helpful reminder to question the effect itself. We should be able to explain what our extra work helps someone understand or do. Sometimes the answer is a more pleasant experience, and that’s a valid answer. It still needs to sit alongside the other things we’re asking the team to finish.
For the export, I’d start by making sure people can tell that the request has begun, and understand what to do if it fails. Once that works, we can spend some time on how the feedback arrives and whether a little movement helps it feel clearer.
That gives a review somewhere useful to start. Instead of asking people to make it feel better, we can point to the uncertainty: I pressed the button and couldn’t tell whether the request had started. Someone can investigate that and propose a fix. They don’t have to guess which version of taste they’re supposed to satisfy.
Give finishing an owner
At Moneybox, my work included building the foundations of our design system. At DuckDuckGo, I’m thinking about how we make quality repeatable across a developing practice. Both make me interested in how a decision survives beyond the person who first cared about it.
A shared component can give the next feature a good loading state by default. A short explanation can help another engineer recognise the same problem elsewhere. Neither removes the need to review the feature in context, but they reduce how much we need to rediscover.
I want the people shaping an interaction to stay involved long enough to see it working with real content, awkward states and ordinary input. That time has to exist in the plan. Calling it a final pass doesn’t help if the release date assumes the work ended when the happy path was merged.
We’ll still miss things and come back to decisions after shipping. I’m comfortable with that. I just don’t want the plan to depend on somebody rescuing the same unfinished parts every time.
When we’re next looking at a plan that only just fits, I want to ask which part of the experience we’re assuming somebody will finish later. Then we can either make room for that work or reduce what we’re asking the feature to do.