If there is one truth about software development that I’ve learned over the last 8 years, it’s this—almost all the work you’ll do is discovered on the go. You don’t know exactly what you need to build until you start.
It’s not that you don’t know what you’re building. It’s just hard, at the outset, to specify the individual tasks needed to get there. This is especially true when working in an existing, complex codebase. Where all the pieces and how they interact is too much to hold in your head at one time. But even in an evergreen project, you’re going to discover work as you build.
You todo list will start small and generic and grow larger and more specific. Add CRUD methods leads to Add insert method, Add update method, and Add delete method, which then lead to Add bulk insert, Implement soft delete, Add restore method, Add permission logic and error handling, Show loading state in creation form, Notify project members on delete and restore, etc. etc.
This is fine. This is natural. You might not record and track every one of these tasks, but this should feel familiar. It would be a waste of time to try and think of and document everyone one of those tasks ahead of time.
However, discovered work is still a risk. Discovering a huge chunk of unexpected work late in a cycle can be hugely disruptive. The team expected you to ship something next week. Marketing was ready to launch a campaign. Sales has been promising it to new clients. Customer support is buried in feature requests. But you just discovered a chunk of work that’s going to delay release by an unknown amount.
It’s not your fault. You didn’t make the work. It was always there you just discovered it. But it’s worth trying to discover this work as early as possible, to avoid the disruptions.
In my experience, there are two sources of destabilizing discovered work.
Product blindspots
Technical blindspots
Product blindspots are usually a result of poorly specified requirements. You knew were building a feature to do X. But it wasn’t until late in the cycle that you learned that it should also do Y. Maybe you built it assuming a certain user profile, or a certain state of the application. But, wait, what if the users has no projects yet? What if they did B before A?
If these are rare edge cases, they can be ignored and handled later. But if these are critical requirements it’s disruptive to discover them late in the game.
The way to get ahead of this is to spend more shaping before writing any code—mapping out, at a high level, what to build. The goal is not to come up with a complete list of todos, but to discover any product blind spots before writing a line of code.
The second source, technical blindspots, can be even more disruptive. You set out to solve a problem with a given tech stack, only to discover some technical constraints that you didn’t know ahead of time. This can add an unknown amount of time to actually shipping something. And if it turns out your chosen stack or solution is flawed and you need to start from scratch, it’s better to find that out sooner rather than later.
The good news is these are easier to spot. As a developer, you should know your blindspots. If you’re working with a technology or problem space you’re not familiar with, that’s a risk. When you start building, start in the ‘riskiest’ areas. Discover the uncertain work first. You’re using a new library for parsing PDFs? Build that part before you make some variation of the basic JavaScript form you’ve built a thousand times.
It helps to build a fully working slice first. Skip all the bells and whistles, and get something working end-to-end. Call it a POC, or a prototype, whatever. Just focus on getting something that works—that does the thing. The point is to expose yourself to as much of the core parts of feature as you can as fast as you can. And with a working slice you can start preliminary QA on it right away. I’ve found this is the fastest way to discover work. Especially if you record all the things you skip on your way to that hacky prototype (e.g. Add client-side validation, Send email on save, Prettify loading state, Store createdAt date).
Even if you shape before building and start with the riskiest bits first, discovered work is always there. You just don’t know what you don’t know. There will always be blindspots. But the best way to find them is to start building.