How I Approach Software Development

Why I Wrote This Down

I recently joined Help Scout as the VP of Engineering. One of the first things I did was write down how I approach building software, so the team could understand how I think, and how I’d lead, before we’d worked through much together. As an engineering leader, my opinions and philosophy naturally shape the culture around me, so it seemed better to make them visible than to leave people guessing.

It started from conversations with a few ICs about how people approach ambiguous work. Internally, it serves two purposes:

  1. A viewpoint to compare against. Engineers work in different ways, and seeing someone else’s workflow is one of the cheapest ways to reflect on or change your own.
  2. A shared default for how work moves from idea to production. Not a mandate on personal habits, but an expectation for how the organization operates.

I’m sharing it here for the first reason. If you lead a team, I’d encourage you to write your own. I’ll admit, coding agents have played a role in evolving how I approach development, but coding agents are not the entirety of the approach. It’s more nuanced and layered.

Start with Outcomes, not Plans

Every piece of work starts with a short statement of objectives, goals, and outcomes. Could be a vision. That statement is the driver: it decides what counts as progress and when we can stop. It also provides the direction for the work. When ambiguity appears during the work, look to the outcomes to help create clarity.

The plan comes second and is allowed to be wrong [we know plans are wrong]. Outcomes should stay stable while the plan can change underneath them. If the outcomes keep changing, the work is not ready for an execution plan of any kind yet.

Two Modes of Working

These are habits, not personality types. Most of us default to one, and everyone can do both. The skill is noticing which one the work in front of you needs. Both modes start from the same outcomes. They differ in when work begins and how much of the plan is trusted up front.

Explore mode Plan mode
Starts work when Outcomes are clear and a rough plan exists The detailed plan is trusted
The plan is A hypothesis, expected to change A commitment, expected to hold
Progress shows up as Frequent demos of working software Planned tasks completed
Milestones are Shippable possibilities Checkpoints on the plan
Closest methods Iterative/agile, spikes, Shape Up’s uphill phase, walking skeletons Plan-driven delivery, design up front, waterfall
Fails when It never converges; demos replace decisions The plan outruns what anyone actually knows

The two modes are not equal partners. Explore is how we keep momentum. Plan is how we execute to delivery. In my approach, Explore is the primary workflow, and Plan is a small, short-lived branch off it.

This approach depends on product and design working the same way. Engineering cannot run an Explore trunk alone. Product needs to frame work as outcomes rather than fixed specs, accept a rough plan that changes, and come to demos ready to make decisions. Design needs to iterate in working software, slice by slice, rather than hand off finished designs up front. Without that alignment and contribution, the approach creates friction and churn: engineering explores while others expect fixed scope, slices get rebuilt to match late designs, and demos generate momentum without decisions.

A Note on Kent Beck’s 3X

If you know Beck’s Explore, Expand, Extract framework, the shared word is on purpose. Beck uses the ideas in the large: a product or team is in a phase, and the phase shapes what good outcomes look like. Extract outcomes are about efficiency, reliability, and cost; Explore outcomes are about learning and fit.

I use them in the small. Within any phase, a single project still moves from Explore to Plan. A team in Extract still explores a project’s shape before branching into delivery. Its outcomes just point at Extract-phase goals.

Explore is the Trunk; Plan is a Short Branch

Work lives on an Explore trunk: a run of thin slices and demos that keeps moving. When a piece firms up enough to have a clear boundary of time, scope, or both, it branches off into Plan mode, gets delivered, and merges back. Routing agent-shippable work onto a fast path, which I wrote about in What Agents Can Safely Own, is this same pattern applied to the whole SDLC.

A few things follow from treating it this way:

  • Shaping is continuous. It is not a gate passed once. Every demo is a chance to spot a piece ready to branch.
  • Plan branches stay small. A long-lived Plan branch is a warning sign, like a long-lived git branch. If one keeps growing, it was never really shaped and goes back to the trunk. I personally have low confidence in large, long detailed plans.
  • Commitments live on branches. The trunk is measured by momentum and demos. Each branch is measured by whether it delivered.

Trap: momentum must not stand in for convergence. The trunk only works if it is built from production-quality slices that add up to the product. Otherwise it becomes a stream of demos that never ships.

The people closest to the work decide when a piece is ready to branch. Pushing that call up to senior leadership should be rare.

Thin End-to-End Slices and Shippable Milestones

I build in thin end-to-end slices: a sliver of working software that runs from the UI through the business logic to the data, then gets fleshed out. There is something to demo early, and integration problems show up at the start instead of the end.

The idea has several names. Alistair Cockburn calls the first slice a walking skeleton: every main component linked end to end, with little flesh on it yet. Agile practitioners, Scott Ambler among them, call the practice vertical slicing, as opposed to building the “layer cake” one horizontal layer at a time. The Pragmatic Programmer calls it tracer code.

Spikes and Slices

Explore mode produces two kinds of code, and they are easy to confuse. Both are small, early, and demoable. What separates them is intent and quality bar.

Spike Slice
Answers Should we, and how? Does it work end to end, for real?
Quality bar Whatever answers the question fastest Production: tests, CI, real interfaces
Lifespan Ends when the question is answered Stays and becomes the product
Where it lives Off to the side of the trunk On the trunk

The quick test: would we be comfortable deleting this tomorrow? If yes, it is a spike. If no, it is a slice, and it needs tests and CI now.

When a spike proves the idea, rebuild it as a slice instead of promoting it. Agents make that rebuild cheap, which takes the sting out of throwing code away. They also make the rule more important, because an agent-built spike can look production-ready when it is not.

Prototyping is now a skill, not an artifact. Fast, rough, agent-assisted building is how you make spikes and how you make slices. The difference is what you do with the result.

Spikes are also how I try things I wouldn’t have attempted before. With agents, the cost of starting has dropped to minutes and the cost of trying to hours. So before putting a long estimate on something, spend an afternoon attempting it. The attempt is often quicker than the estimate, and it produces a much better one. I’ve written more about this in The Moment That Changes Things.

Each milestone is a slice that could ship. If we stopped at any milestone, customers would get something coherent, even if small.

Why Agents Make Slicing the Default

Left alone, agents tend to build layer by layer: schema, then API, then UI. Feedback waits until the end. Matt Pocock found that asking agents for vertical slices fixed this (Pragmatic Engineer, talk summary).

Before agents With agents
Main bottleneck Writing the code Reviewing and verifying the code
Cost of a thin slice High: a person wires boilerplate through every layer Low: agents do the wiring
Role of the slice Used selectively to de-risk hard integrations The default unit of work, because it keeps each review small

The old cost argument against slicing is gone. What stays expensive is review and verification, and a thin slice is how you keep those small.

Building Blocks Keep Slices Thin

A slice is only thin if most of it already exists. When existing building blocks, established patterns, and platform components cover the plumbing, a slice is mostly assembly, and new code goes only where the work is actually new.

This matters for people and agents alike. An agent following an established pattern and reusing platform components produces smaller, more consistent changes that are easier to review. An agent starting from scratch invents, and invention is expensive to verify.

Two things fall out from that. Platform investment directly speeds up slicing across every team. And when a slice has to invent a new building block, treat that as a signal: it may need a spike first, or it may belong to the platform rather than one project.

Making Verification Cheap

Slices and Plan branches are only as good as our ability to verify them. A slice is production quality only if we can show it works end to end, and a Plan branch merges back only once it has been verified.

At Help Scout, we have a local stack that runs code changes end to end on a laptop or inside a background coding agent’s environment. Not every company has this, and it is a real advantage.

It is also what makes coding agents effective. An agent that can run the system and its end-to-end tests checks its own work before I look at it. That closes the agent’s feedback loop, lets background tasks run with infrequent check-ins, and means reviews start from evidence instead of just a diff.

Working with Coding Agents: Foreground and Background

I run one foreground task and a few background tasks at the same time.

  • Foreground: a single primary task that gets my focus time, usually paired with a coding agent. This is where judgment, taste, and the hard decisions live.
  • Background: a few low-risk, low-attention tasks handled by agents. I check in infrequently to see where things stand and supply what they need to keep going. Two or three at a time is my target. The right number varies by person.

The two modes map onto this. Foreground work is often in Explore mode, because it needs me in the loop. Background work should be in Plan mode: well shaped, bounded, and checkable without me reading every line. If a background task keeps pulling my attention, it was not a background task. It goes back to shaping or moves to the foreground.

Matt Pocock describes something related as a day shift and a night shift: humans do planning and alignment, then agents implement unattended, then humans review and QA (talk summary). His split runs across time. Mine runs across attention, in parallel. The shared idea is that humans own the shaping and the verifying, and agents own the typing.

I expect this approach to change as the work shows me what’s wrong with it. That’s the point of writing it down.