Drew Barontini

Product Builder

Issue #33
7m read

Reverse Refinement

While I’ve spent most of my career as a software engineer, the past few years has been primarily focused on product strategy, management, and leadership. I’m still around the code, but not in it as much. I miss writing code all day—burying myself in technical challenges, finding elegant solutions, and refining user experiences. But I also find fulfillment in all the work that happens around writing code. It’s the ebb and flow of the craft. It’s the process.

Our team is working on a project under a tight deadline. We’re all hands on deck. I cleared out my entire schedule to focus solely on delivering the work. After getting the team aligned, I found myself with space. I’m not one for idle hands, so I started building a prototype for a dashboard we need. I spent nearly 20 hours writing code during the week. It was so fun. And, in doing so, I unlocked a new development process.

I call it Reverse Refinement.

There are three steps in the process:

  1. Build the prototype as fast as possible.
  2. Organize the discovered issues.
  3. Refine continuously in small iterations.

Build

When I started work on the dashboard, I spent the first day (roughly 4 hours) setting up the codebase and building the prototype. The goal was simple: Get it working. The code didn’t have to be elegant or even well-written—it just needed to work. So that’s what I did. I hard-coded values and worked through each part until I had the basic flow functioning.

That is what the Build step is for.

While the work is messy, the result points you in the direction of refinement.

There are three steps within Build:

  1. Definition: Determine the one assumption you need to prove, and then define the smallest version of that to consider the prototype a success.
  2. Exclusion: Specifically leave out anything you don’t want or need in the prototype. These are the areas you can avoid as you constrain the solution.
  3. Validation: Make sure the prototype works end-to-end and shows real, working behavior that reveal the next steps to take.

When I completed the prototype, I immediately had a list of tasks. I knew what work to do, what questions to ask, and where to prioritize my efforts. This is where the typical software process falls apart because the expectation is, if I pre-plan everything and write every task I can think of, then the work will go smoothly. But it never does. Work is discovered, not imagined.

It’s all guesswork until you do the work.

Building a prototype is the surest way to remove the guesswork. Learn by doing, and lean into the unknowns by building working software. The only validation comes from creation. AI can help to create a faster prototype, but be mindful of how much you rely on it because, in doing the work, you uncover what refinements are needed. AI is an enhancement, not a replacement for critical thinking.

Organize

Once the prototype is built and we have the discovered tasks, we need to Organize.

In this step, we take all the issues and give them a taxonomy:

  1. Scope: What named area it belongs to (Search, Transactions, etc.)
  2. Layer: Where it lives in the stack (Functional, Technical, Visual).
  3. Type: What type of issue it is (Core, Bug, Enhancement, Unknown).

When I shape work into a pitch for a team to work on, I include three named scopes. Each of these scopes are independent and can be built, completed, and shipped independently.

Why split it into three scopes?

When the team begins the work, they validate the scopes. Are they split out the right way? Should they be combined or renamed?

But with Reverse Refinement, this is unnecessary because the prototype reveals the lines of the work. We know what to do—we just have to organize it.

You do it with Scopes, Layers, and Types.

Scope

The Scope is the area of the feature. These are unique across products, and should be clearly named and written to communicate a consistent meaning to the team. So when I talk about the Search Filters (written as a proper noun), everyone knows exactly what I mean.

In the context of building the prototype, this is a way to group related units of work to better prioritize your efforts. Scopes are the early areas of the product that form the larger language of the product.

Layer

There are three Layers to group tasks:

  1. Functional: How it works.
  2. Technical: How it’s built.
  3. Visual: How it looks.

The core functionality is built in the prototype, but more Functional issues will surface. The Technical and Visual will be lower priority, but need refinement just the same.

When I built the dashboard prototype, it was in a codebase with an existing visual design. Most of the work was in the Functional to shore up the basic features. Most refinement was in the Technical to make sure those hack-y things I did could be refactored properly.

These Layers are helpful categories when classifying and discussing work. You can ask your team whether the issue is Functional, Technical, or Visual, and use that to determine the priority of the work.

  1. It needs to work well (Functional).
  2. It needs to be built well (Technical).
  3. It needs to look polished (Visual).

Type

There a four Types of tasks:

  1. Core: Must-have functionality.
  2. Bug: Something isn’t working right.
  3. Enhancement: Something to improve.
  4. Unknown: Work to discover.

I always stick with things in threes, yet Core is an assumed Type. Still, it’s important to distinguish on its own here. When I labeled the issues, anything without a label was assumed as Core. It is the natural default.

Now, with each taxonomy applied, you create a unique language for the work:

Refine

With a prototype built and the work organized, the next step is Refine. The goal is to continuously deliver work in small and fast iterations that improve the product rapidly.

In order to Refine, you have to:

  1. Prioritize: Choose the issue that will unlock the most learning, momentum, or value. I like to focus on the Unknowns because those are generative issues, which will create more work once you complete discovery. Use the taxonomies as your guide to find the right next step to make progress.
  2. Isolate: Make a clean, scoped change and push it to the live environment. Each change is like a frame in a time-lapse video where you watch something change steadily in front of your eyes.
  3. Adapt: Observe the result, get feedback, and keep iterating in prioritized, isolated changes to shape what comes next.

No Guesswork

The only way to understand the work is by doing the work. There’s no shortcut. But there are ways to get there faster. Starting with a prototype helps validate the solution and uncover the work to do; organizing the work establishes priorities; and building in tight feedback loops rapidly refines the work, creating a time-lapse effect as each iteration improves on the one before it.

Instead of pre-planning or over-optimizing before the work begins, be a hacker and get a working prototype together. And then work in reverse to refine the solution until it meets the quality bar you’ve set.

That’s Reverse Refinement.

Clarity Current Strategic Momentum

Enjoying this issue? Sign up to get weekly insights in your inbox: