Often it isn't writing code that is the hard part of the job: it's trying to work out how long it's going to take to write it. Our companies want to ensure that our engineering salaries are being spent wisely, so it follows that they care about when we expect things to be delivered.
Despite the fact that we have more tools and technologies available to us than ever before, we still struggle to get things done on time. Even the most simple project can throw curveballs when it gets dropped into the middle of an existing system in the real world. As such, we really don't have a good sense of how long things will take. After all, building software isn't a mechanical process: it's a creative one.
This, as you've likely experienced, causes a lot of tension with our stakeholders: our customers want to know when they can expect something, our managers want to know when we'll be done, and we want to know when we can move on to the next thing.
Sometimes it feels like we can spend more time reporting on progress than actually making that progress in the first place. All to satisfy the need for predictability.
Just go faster?
Teams that struggle with estimating and hitting deadlines may have executives or non-technical leaders offering their advice on how to get things done faster. Perhaps you've been told to work harder, or smarter, or to just quit messing around and "get it done."
Maybe those that are giving you advice have been absorbing much of the literature that came out of the long boom cycle of the 2010s, where the prevailing wisdom was that the way that start-ups succeeded was by going fast, hard, and hacking things together. Blitzscaling, zero to one, and all that.
If you've read any of my previous articles, or my books, I always come back to the concept that anything you hear from others should be treated as tools rather than prescriptions. The real world is complex, context-dependent, and what works for you may not work for someone else, and vice versa. This doesn't make for good soundbites, but it's the truth.
Read around, experiment, and find what works for you.
Speed versus thoroughness
Back to time: everyone wants you to go faster. But what does that actually mean? If we assume that every team is working sustainably hard and is motivated, then the amount of work that can be done in a given time period is fixed. You can't just "go faster" without sacrificing something else.
The typical answer to the question of what gets sacrificed is "quality." But what does that mean? Does it mean that you're shipping bugs? I wouldn't want a team to release bad work on purpose. Does it mean that you're not writing tests? Maybe, depending on the context. But fundamentally I don't think that "quality" is the whole picture: a good engineering team that are worth their salt should have a generally fixed quality bar also. They would find it hard to do purposefully bad work.
Instead, I think that a healthier way to encapsulate speed, scope and quality is thoroughness. Thoroughness is about how much you're willing to explore the problem domain, how much you're willing to experiment versus build resilient systems, and how long what you're going to build is intended to last.
I like the term thoroughness as opposed to scope because, with time, scope has come to mean "what my product manager has said we need to build", rather than encapsulating the full range of potential engineering work that needs to be done.
I think of thoroughness as the superset of scope, scalability, and sustainability:
Scope is what you're building.
Scalability is how well it will work as you grow.
Sustainability is how well it will work over time.
These three things are in tension with each other and make for a much more nuanced discussion than just "go faster." Instead, we can have a conversation about what it means to be thorough, and what the trade-offs are around the time to deliver.
Trade offs
The more thorough that a team is in a project, the more time that they will need to spend on it. The right amount of thoroughness should be a conversation across disciplines, stakeholders, and the team.
For example, if you were building a first version of a product at a start-up and trying to see whether you get product-market fit, you might want to aim for low thoroughness and not worry too much about scalability or sustainability right now. After all, if nobody wants your product, then it doesn't matter how scalable or sustainable it is. However, importantly, you can still have low thoroughness and a rich product scope: it’s the other parts of thoroughness that suffer. You can still build a lot of features, but you wouldn't want to waste time on work that may get discarded.
The opposite would be true if you were building some critical global banking infrastructure: you'd want to be very thorough in your design and implementation, and you'd definitely want to make sure that it was scalable and sustainable. Even if the feature was a tightly scoped data store, you'd want to make sure that it was built to last and was highly performant and robust.
Depending on your problem domain context, the size of your company, and the maturity of your product, the shape of the curve plotted by speed versus thoroughness may differ. For example, it might be the case that as thoroughness increases, the time to deliver a feature increases linearly (e.g. a to-do list webapp). Or it might be that it increases exponentially (e.g. something simple but not straightforward like Instagram).
With this curve in mind, for a given project, you can have a discussion about where you want to be on the curve that represents acceptability.
Having a think about the effect of thoroughness in your team in general, or on a specific new project, is an interesting discussion to have. It brings another dimension to the typical iron triangle of scope, resources, and time. With thoroughness you can have more productive discussions about what it means to be thorough at this moment in time, and what the trade-offs are around the time to deliver.
For example, the distance between your present state and the desirable level of thoroughness may be a long way. However, if you are able to release to increasing numbers of cohorts of users as you progress on that thoroughness journey, you can get feedback, iterate, and still actually ship. This might work for you and your team getting a new product off the ground.
Or, instead, maybe you need to be highly thorough from the start, and therefore a long build duration before the first release is deemed acceptable with consensus amongst stakeholders achieved up front. This quells the "why is it taking so long?" questions with a constructive answer about the trade-offs that you're making. This might work for adding a new feature to a mature product whilst maintaining the high quality bar that your customers expect.
There's no free lunch
If you have a good team, there's no magical and sustainable way to "just go faster". And scope very rarely tells the whole story; at least, how we often use that word: it can overindex on a product-centric view of the world.
Instead, champion thoroughness. It's a more nuanced discussion around scope, scalability, and sustainability, and I think it's a more productive way for all of us to think about how we are spending our time.
Talk to your team about it:
What does thoroughness mean to you?
Do you maintain a similar level of thoroughness across all projects, or does it vary?
How do you communicate the trade-offs around thoroughness to your stakeholders?
How do you know when you've been thorough enough? What do you measure?
How do you know when you've been too thorough?
Very interesting. We've fallen into the psychological rut of using the term "scope" to mean functionality rather than the other things you include in the concept of thoroughness. As you pointed out, it's all about making acceptable trade-offs, but somehow the key things being traded off against each other are often elusive. Thinking out loud: what if we contextualise the "what's the problem to solve?" (typically what we think about when we think "scope") with "what part of the company's strategy is doing this achieving?". The latter question forces us to think about what it is that's important to _our_ survival as a company. Speed to market? Then acceptable is low thoroughness. Stable infrastructure with good uptime? Then acceptable is high thoroughness.
It rains truth to talk about how the processes and ideals of the 2010s start-up, "family," agile, many-hats, now-obsolete mindset. The scope, budget, timeline trifecta is now something of a relic and we have improved our stacks and flows beyond the description and diagnostic purposes of scope, budget, timeline. Thoroughness in tech, especially fintech, where I sit, is a much better consideration for product managers to collaborate with engineers and then internal, vertical stakeholders .Love this wrap. Thanks for sharing, James 🙏