What Works – Deliver Small Chunks

This is the third post in a series that formed the basis of my 2017 DevCon session on Increasing Code Quality While Staying Lean. Check out the first post for an introduction to the series. This series describes techniques that have made a big impact at SeedCode and we hope you’re inspired to incorporate some of these into your own work.

(Updated, May 2024)

We Break Things into Small Chunks

Of all the things we do, this probably has the widest application. I think of this when I’m replying to a customer’s email, when I’m designing a new feature, or writing up the cases for what’s to be done in a sprint. And the more I keep this in mind, the better things go.

Here’s what we do:

  • We deliver every 5 to 20 hours of code.
  • For large projects, we deliver every week. (Every two weeks for intricate apps that touch finance.)
  • Deliver means deploy: putting code into production with data migration and everything.

We do not listen to a client for 2 hours then head into the desert for 4 months to build their software, hoping they like it when we return. That is not how great software is made. Instead, we break things into really small chunks so we don’t outrun our understanding of the client’s issues. By delivering small pieces of work more often, that work gets validated quickly so clients can easily course correct.

In order for this to work, the small pieces of larger mods need to be put into production. Delivering small pieces doesn’t help if they’re not deployed and validated. Whenever possible, we construct sprints so that the outcome is a usable small feature—not part of a feature.

The same applies to work on our own products. Over the course of a two-week sprint, we should have many small deliverables (many short QA videos). The alternative is the demoralizing realization that, at the end of the sprint, we made a wrong turn early on—a wrong turn that went unchecked because nobody saw our work for weeks.

Tactics for Shipping Small Chunks

What does this look like when we’re making cases?

  • Cases should be binary: something that can be completely done or not. “Get started on…” or “Improve…” is not a case.
  • Use timeboxing to keep things small. That means sticking to your delivery schedule even when features start to balloon. At the end of our sprints we QA and ship what we have and create new cases for the gaps or undone edge cases. Those become just more small chunks.
  • We create gap / bug cases as we find them during development and QA. It can be hard to know which gaps need to be closed now and which can be deferred to a case. But just because we have spotted an issue, it doesn’t necessarily need to be fixed immediately: we don’t want to harden routines that haven’t been validated first. So, we’ll often acknowledge the gap in our delivery video and close it once the client has confirmed we’re on the right track. We think of this as “validating the hub before adding spokes.”
  • In cases where what we have isn’t a whole user-facing feature, we may disable the interface but still ship the code. This reduces the drift between the code in production and the code in dev, which is often a source of bad surprises and anxiety for developers.
  • When we can’t deploy into production, we deploy into a test environment with real data and real users (not just the project leaders). This might be the case for finance-heavy apps, online booking, or where customers have a formal UAT environment.
  • FileMaker developers often freak out about this since “deployment” is one of the toughest things they do. Migrating data and backfilling data changes are time-consuming and fragile. All I can say is that this is a place to invest in systems–be they as simple as thorough checklists, scripted imports, moving solutions to the separation model, or using automated deployments like OttoDeploy.
  • In Salesforce, where we’re often developing in a sandbox, we ideally want a full sandbox so we’re deploying into tables with real data. When that’s not practical, we like to have a subset of actual data loaded into the sandbox vs working with simplified, example records.

Velocity: Delivering Projects Every Week

We’ve been delivering in small chunks for a long time now: at least 13 years. But the best evidence for why this works comes from the fact that we’re delivering more often on our biggest projects. When we started our largest custom development project ten years ago, we decided to deliver every three weeks, at the end of each sprint. This seemed audacious at the time, and I remember lots of talks with Jason, our lead engineer, about how that would work. That original plan was delivering 70 hours of new work every three weeks (we QA’ed that work in 2-3 hour cases, with a video for each case).

But over time, and especially as we got into trickier parts of the project, Jason started doing some mid-sprint deliveries. He said it was less stressful to deliver what he’d done as it was finished than to save it up for a bigger delivery, with more moving parts, at the end of the sprint. There was less “spooky music” when the deliveries were smaller and more frequent—less foreboding that there was something just out of sight about to surprise him.

That eventually turned into delivering every week, a process that came about organically as a result of Jason trying to get a handle on his work. The team is now delivering about 30 hours a week on that project per developer.

We started delivering more often on our toughest project and have stuck with it, which is the best evidence we have that this works.

Why This Works

We don’t outrun our understanding of the problem

With small chunks, we’re speaking to the customer more often. Our work is also getting validated sooner because it’s being deployed in small enough pieces for the customer to digest. This means our work can be seen by all our constituents, not just the project’s informants. And we’re getting feedback now instead of months from now.

No more half-done features: increased restart speed

It sucks to restart work on something that was never finished. Having no half-done code means greater role portability, as it’s easier to pick up someone’s completed scarf than the half-scarf-half-yarn tangle dredged up from their drawer.

Redefines what’s a “bug”

This one sneaks up on you, but if you’re always delivering small chunks, it gets much easier to make a distinction between an error (i.e. “this column does not add up”) and something that just hasn’t been tackled yet (“I thought we’d be able to sort these columns by clicking on the header?”).

Most of what we used to call “bugs” are really either things we misunderstood or edges we haven’t gotten to yet. An iterative delivery process makes that obvious to both your clients and your developers, keeping everyone’s morale high and making billing disputes a non-issue. Billing looks more like agreeing on a run rate (dollars per week or per sprint) and then checking in to see if that run rate is delivering features at a good velocity.

Reduced cognitive load

We know that incomplete tasks take up more mental energy–much more–than things which are put to bed. So when we finish a case we try to put that to bed: ideally, that means ship and deploy it. For JavaScript projects, things get put to bed in two stages; they start feeling done when they’re merged into our main branch. And they are fully off our plate when they’re shipped. Uncommitted code Unmerged code is the greatest cognitive load, the loudest spooky music: large amounts of unmerged code are cancer.

Recent Ideas

Smaller Chunks

In the last few months, we’ve begun experimenting with very small deliveries. We role-play what it would look like to break a larger feature down so that we could work on a discrete piece every day. This seemed ridiculous at first, but quickly proved to be pretty doable–we don’t actually deliver that often, but we do “package” that often–closing cases and writing the docs–though in practice, this is more like every other day. And this is happening more in our work on DayBack core than in our custom work.

We call this role-playing “the game,” and we’ve found two real benefits to playing the game, even when applied to things that already appear to be pretty small features.

  1. It makes you see the feature more clearly. In particular, it lets you see the consequences of each change you propose to make: the lens of “ship a few times a week” seems to throw consequences into relief.
  2. The truly tangible benefit is agility (below).

Agility

We were recently working on a small new feature for a customer: maybe 10 hours of code in DayBack. As part of “the game,” we’d broken this into 4 pieces and deployed each one as it was completed. The day before we’d promised to deliver the whole thing to our customer, one of our developers had an “automotive complication” that required his full attention. We emailed the customer and told them that their feature was live except for a small interface refinement (the last chunck we hadn’t shipped yet) and that we’d get that deployed next week. The customer was happy, and our developer could get to work on his car without distraction.

Picture the alternate universe in which we hadn’t deployed those 3 earlier chunks: in order to get the customer anything, we need to rush the QA and deployment of everything we’d done so far, risking the inclusion of unfinished code, and definitely stressing our developer at a time when they needed to step away from the project in the first place.

This is where breaking things into small chunks really pays off. The customer may not even be able to see the difference in many cases, but to the developer it makes a big impact. Jason reminded me, “These earlier chunks can be soft launches, and maybe we don’t even tell the customer…unless we have a complication…but that kind of detail doesn’t matter to the developer, because as far as they are concerned, those are done.”

And when that developer does come back to finish the last piece, it will really feel like a refinement to something already completed, rather than like opening up the entire feature again.

That’s just a small example of something we’ve seen over and over since we started delivering more often: when we have to change direction, because someone’s car breaks down or because a customer pivots to another area of their project, we’ve more or less packed our bags already. We’re ready to head in a new direction, knowing that we can easily come back to the code we’re setting aside.

Jason adds, “It’s the developer we’re looking out for, because that’s how you build amazing apps.”

Featured Posts

Follow Along

Stay up to date with the latest news & examples from SeedCode

Leave a Reply

Your email address will not be published. Required fields are marked *

Check out some of our other posts ...

Improved Resource Selection

We’ve made some big changes to how you filter and assign resources when editing events in DayBack. These changes will make it much easier to

Suggesting Appointment Slots

Show Available Slots that Match Multiple Criteria Schedulers often look for gaps in their schedules to find the open resources for each opportunity. But sometimes,

Introducing Draft Settings Mode

Following up on this idea that people stretch themselves when they feel a little safer, we’ve been very focused on the customization experience for DayBack

COMPANY

FOLLOW ALONG

Stay up to date with the latest news & examples from SeedCode

© 2024 SeedCode, Inc.