“In a day?!”, I asked incredulously.
I had been telling my manager, Alex, about my first experience as a tech holder. The exercise had proved super fun and challenging to me, but I was slightly concerned about the roughly two weeks I had spent scoping the project before we kicked it off with the entire team. Not that I had delayed coding for the team — I’d got started well in advance while we were finishing up our previous tasks — but I felt I could have been more efficient.
“There’s really nothing to worry about”, Alex told me. “It’s your first, plus that project was pretty chunky, so I’m glad you took the time to get it right.”
And that’s when he dropped that bomb on me. “But, you know, depending on who you ask around Doctolib, some people will tell you that they can sit and scope a project pretty much in a day.”
Cue my reaction.
It made me reflect on what I thought tech scoping was. On the most basic level, a project’s scoping is supposed to answer these questions:
- What features are we going to add, change or remove in the app? What’s the intended user impact? That part is essentially provided by the product manager, but it can be challenged and iterated over together with the tech holder.
- How are we going to build those features? That is, the technical architecture of the project. What parts of the codebase are we modifying to get the desired features?
- How are we going to build those features, Part two? This time, meaning, who’s going to work on them, what’s the timeline for shipping each feature?
- What are the risks? What’s the plan if they materialize?
Now, here’s how I went about it the first time ‘round.
The Beaver-Dam Scoping strategy: thorough and robust
First, I’m in Architect mode, making structural choices for the project.
“For this feature, we want to add a signup form to this page, what does that entail? We’re not displaying it to all our users, so we need to compute which users are eligible.”
“The business rule is pretty complicated, and we’ll use it multiple times, so a helper on that model seems relevant, and we’ll pass that information to the front-end.”
“Interface-wise, we already have a signup form component, with one field that we’re not going to use. We can probably re-use that component and pass it a property to indicate whether or not it should include that field.”
“Since we’ll be displaying it in a high-traffic funnel, we might want to wrap the feature in a feature-switch, so that we can easily disable it in production in case anything goes wrong.”
If the feature is simple enough that it can be coded (automated tests included) by a developer in less than two, maybe three full days, then that’s it, that’s one story. If it’s more complex than that, I’ll split it up in smaller stories, that can be independently coded, tested and shipped.
Then comes Scout mode. I validate my macro choices by digging a bit further in the codebase, hunting for overlooked complexities. This is also a great occasion to assess risks and design their mitigations.
“So, which controller is used to pass information to that page? Okay, I can see that there’s some property-engineering done in the view, we should be careful with that.”
“Ah, there’s a helper method on our model that almost computes what we need, but not quite. Let’s see where else it’s used, and decide whether it makes sense to add our case in it.”
“This database query is more complex than I thought. We might need to consider doing this lookup elsewhere to preserve the app’s performance.”
In addition to handy implementation notes for my team in the stories, the product of this mode is something we do for almost every project at Doctolib: a scoping document, which lists the planned features, along with the controllers, models, views, components, jobs, etc. that we’re planning to touch. It serves two purposes:
- Information sharing with other feature teams. Without reading my colleagues’ scoping documents, I would have little idea of what most of them are working on. More pointedly, this has sometimes prevented two projects colliding!
- A sanity check on tech choices. Every single scoping document I’ve ever seen has received at least one or two important questions from other developers, and some of those have led to major project rethinking, which is pretty healthy.
Finally, Planner mode. Typically, the project’s stories depend on each other, and can’t be coded in any order. I need to chart the dependencies between stories. There:
That way, in a glance, we know where to pick up coding to start a feature, and where the bottlenecks are.
Using that, I can build an awesome timeline for the project, that accounts for:
- ballpark estimates of the duration of each stories,
- The availabilities of each dev,
- Planned bug days (pink rows in the picture below),
and compute a (very) rough delivery date.
Now, this isn’t really rocket science, but the great thing about this is that I can adjust this timeline as we go through the project, take weekly snapshots, and know when we’re falling behind our estimates. Case in point: the picture above is the timeline at the end of the project, and makes it obvious how 245 and 257 were long tasks that maybe could have been split.
It almost goes without saying (but almost is key here): this is a linear account of a process that was cyclical.
The project turned out really well! We’d anticipated most pitfalls, and everything was working as intended when we shipped. I got some positive feedback from my teammates for my scouting work on the stories, and felt like we’d tackled a complex project without much hassle. The only mildly disappointing outcome was the long time spent on two tickets, but as we weren’t under a hard deadline for delivery, this was far from a catastrophe. Plus, reflecting on them helped me consider how to better split stories in the future.
But in a later project, I got to try a very different approach.
The Duct-Tape Scoping strategy: frugal and agile
For the whole of Doctolib’s tech division, the COVID-19 crisis has meant major priority adjustments. Our product is a critical tool used on the frontlines of the response to the pandemic, and health care practitioners need us to ship many features as quickly as possible to help them organize their activity.
So when it was my turn to scope a COVID-related project, on a topic out of our team’s usual scope, with a *gasp* two-week deadline, scoping included, I thought, ‘Well, there’s an opportunity to test the one-day scoping, if I ever saw one.’ So, how did I proceed this time?
- Talk To Someone Who Knows™. This one’s a no-brainer. Since you’re picking up a topic from another team, even though they’re obviously busy, a 30-minute bootstrapping meeting with them is well worth it. It saves you hours of fumbling through their code while still being unsure you’ve covered everything relevant.
- Don’t overdo the Scout mode. Instead of turning every stone in the codebase, perform a quick due diligence exercise, to detect only what’s really out of the ordinary. Document only what either makes you change significant architecture choices, or what will save the developer who codes the story over 15 minutes. Let Convention Over Configuration pay off, it will take care of the rest. Better yet: if you think there are pieces of code that might be tricky, but clearly don’t threaten project architecture and aren’t top-priority, don’t hold off your team’s first commit to spend more time scoping them — let the coding begin, and look into them down the line. As a tech holder, you will likely be much more useful as a central repository for the project’s design than as one more person taking up stories.
- Optimize for “time to Minimum Viable Product (MVP)”. Most of the small details, edge cases and other improvements will probably be ten times quicker to detect once you ship your core features. In typical lean fashion, ship a minimum viable feature as soon as you can, hidden behind a feature-switch to avoid upsetting users, and crash-test the hell out of it. Magically, you’ve saved precious time by not building complex hypotheticals, and you can now use it to clean up any quirks and polish your feature.
Paradoxically, this kind of scoping demanded much more discipline from me than the other one. It’s actually very hard to let go of working out everything in detail. But it became clear by the project’s end that not only did this approach work, it was pretty much the only viable approach in our situation.
For the record, I didn’t exactly scope the project in a day, but rather, over two to three days, plus all the time spent throughout the actual coding. This is still massively different from the two weeks I spent on my first project, which was comparable in complexity, and given the short timeframe we had for delivery, it made all the difference in the world.
If you had told me about those two types of scoping in theory before I had done any, I would have said that the beaver-dam version is the better one. The last thing a project needs is unpredictability. The risks are many: developers playing treasure hunt for unknown lengths of time, shipping a broken or incomplete feature, complete project rewrite after discovering a hidden problem…
- Does extensive scoping really eliminate those risks?
- Even if it does, is it worth two full weeks of developer time?
Now, after my two experiences, it might be tempting to answer both questions with ‘no’, and declare the duct-tape scoping better. After all, it delivered comparable success, with much less time spent scoping.
You know where this is going, so let’s at least wrap it in a neat metaphor: between a flathead and a Phillips-head screwdriver, neither one is better than the other. What’s better is having a well-furnished toolbox, and knowing when and how to use the tools in it.
Some projects warrant investing in agility. Others in predictability. Some are worth building the huge charts, documenting the precise tech choices for. Others are better approached with the leanest mindset. All projects need a dedicated team, with a tech holder ready to own its tech choices.