Software developers are asked to take on a lot of novel and interesting work. We are often asked to solve problems we’ve never seen before. But at the same time, we’re also asked how long it will take to solve those problems. Even if the changes we are asked to make seem routine and predictable, constantly updated languages, frameworks, libraries, and best practices ensure that we’re almost never building the same thing twice.
With all this uncertainty, even figuring out how to start can be a huge challenge.
On a recent project, instead of fighting the uncertainty, I decided to lean into it and use it to direct my work. I started with a hand drawn and annotated concept for a UI. The excitement was palpable. This feature could have major implications for our project and it could fully replace a third party integration that was in planning stages but made the team uneasy. The questions were simple and immediate.
Can we build this? Absolutely.
How long will it take? Well, I’m going to need to break this down and analyze it.
Getting the lay of the land
I started breaking down the project from the front-end backward as we had the initial concept sketch. The project was to build a custom report generator, where individual system reports could be aggregated into a single report package that could be regenerated each month or quarter to make regular reporting much easier for users.
As primarily a back-end engineer, the functionality specifically called for some drag and drop functionality which I had never implemented before in React. The drag and drop components represented separate reports, each with their own configuration and the goal was to aggregate them together for export to PDF.
Each of these individual reports can take a considerable amount of time to generate, so I knew we would need another background worker to pass the aggregated configuration. I went about exploring the needed features at a high level, breaking them out into roughly 10 users stories, some of which could be broken down into smaller stories. Not excessive resolution on the plan, but enough to fill out cards on the Kanban board and feel confident I wasn’t missing anything. As I filled out the Kanban cards I added more detail. Enough detail was added to the cards that I was confident I could hand off any task with a 15-30 minute intro discussion, but this was not a formal specification.
As I got started I put my focus on the areas that I understood the least. I wanted to ensure that the pieces with the most risk were tackled up-front. This was a fairly big project, I would be working on it for many weeks and I absolutely wanted to front-load anything that could take more time than expected.
My first decision was to stub out fake data so that I could build out some of the front-end without having to spend time crafting backend code. I stubbed out fake data to the point where I could build out the React drag and drop interface and components. Next I spent some time building out a proof of concept for generating the reports, concatenating the output, and spitting them all into a single PDF file.
Next I decided to tackle a single piece of the interface by building out a full React component for the most complex of the individual reports. That process had me jumping all over the code base building small pieces here and there that were almost entirely useless on their own. But slowly it started to come together.
I was rounding out this component and getting to the point where the configuration for a single report could be saved when a teammate contributed the first backend module to take a configuration and render a page. Now all of these separate puzzle pieces finally fit together to form a complete proof of concept. The first report rendering could be configured and aggregated multiple copies into a single PDF.
From here everything started falling into place quickly. We had identified all of the major pieces, sorted them by risk and uncertainty, and then slowly pieced them altogether. By the time we had completed the proof of concept we had the design fully proven out, and now we had a great picture of how long the rest of the work was going to take. Additional UI components and backend modules were completed one after another following the conventions we had already established and faster than I had imagined.
The fog of development
This process reminds me of playing Warcraft, Age of Empires or similar where in the early game you scout for resources, finding paths and pushing back the fog of war. You spread out to quickly create as much visibility as you can. Once you know the landscape you gain confidence and you’re off to the races. You prepare for the uncertainty early on of finding and gathering resources, and as the game progresses your strategy becomes increasingly narrow and predictable.
When embarking on a project it can often feel natural to just start working on items you’re familiar with. Or items that are easy (we all want to make progress!). Or even items that are mostly visual. You can make rational arguments for any of those choices. The problem is that when you do that, you’re only narrowing the cone of uncertainty a little bit. But by tackling the project in a more strategic order, you can knock out items that will give you more visibility and reduce uncertainty, giving you a more predictable outcome.