There are a lot of ways to waste time and effort when developing software, and it’s not even things like catching up on Facebook or playing table football I’m talking about.
It is completely possible to work incredibly hard without generating of value at all. Sometimes, it’s even our own good intentions that trip up us!
Sources of waste
1. Building the wrong thing
The worst possible waste is probably when we efficiently and using all our expertise, deliver something that turns out to be the wrong thing. This can get really costly if it takes us a long time to realise our mistake and we spend a lot of time down the wrong path.
In some cases, when this happens, the cause is some misunderstanding during the development. However, it might just as well be that we picked the wrong problem to solve from the start – or the wrong solution to that problem.
Perhaps someone in a position of authority has got some pet feature they think should be the highest priority and make us work on that. In other cases, we as a team assume we need something when we don’t.
An example of the latter can be when component teams work in isolation, each delivering their part of the architecture to the complete system. When it’s time to build the front-end, we realise that the back-end doesn’t do what we need it to do and the back-end team needs to go back and make changes, or that they have built more than we will end up using. Such a waste!
To minimise waste, we need to not only make sure we maximise our chances of starting the right thing. We also need to discover as soon as possible when we’re not. Invariably, this will involve short feedback loops.
- Focus on why we build something, rather than just aiming to deliver as many features we can.
- Confirm assumptions as early as possible, through prototyping and user testing.
- Ensure access to the customer, stakeholders or users throughout the development to give us quick answers when we need clarification
- Demonstrate the software frequently (and act on the feedback we get!)
- Whenever possible, we should strive to get small increments deployed all the way to live to confirm whether users respond the way we’re anticipating (A/B testing). This may seem like overhead but the alternative is much worse: assuming we’re doing the right thing, spending a lot of time implementing it and going live in a big boom, only to find out our customers hate it.
2. Unfinished work
Any work we have started but not yet finished can quickly cause waste.
Code written but not yet deployed to live is likely to quickly go stale when the rest of the code and requirements move on. In extreme cases, this can go as far as the code getting obsolete or so out-of-date that we need to throw it away. Often, the outcome is less extreme but it will still add overhead in the form of painful merges or require effort to keep branches up to date.
There are a lot of reasons why we might not straight away finish what we started. Maybe we’re waiting for someone to clarify requirements, or we’re blocked by some external dependency or someone else in the team, let’s say a tester, to become available. Maybe priorities have changed. And once our product is live, we will have to deal with live issues etc. etc.
It’s worth noting that it’s not just code we’re talking about, either. Maybe the work we started was to identify the requirements for a feature, but for some reason we haven’t started the development yet. Those requirements might well go stale too!
So, how do we reduce the amount of work started but not finished?
- Aim for small batch sizes. This includes splitting user stories so that we can complete them quickly. Also, we should avoid big releases, which tend to lead to stories getting held up by others, just because they have been lumped together in a release.
- Always seek to reduce the amount of time we spend waiting for others. Cross-functional teams, capable of delivering features end-to-end, is one of the best ways.
- When dependencies are unavoidable, try to identify them before something is brought into a sprint or added to your Kanban board.
- Make sure you have access to the Product Owner and – even better – users during the development, so that you can get quick clarification to your questions.
A disruption is anything that stops us from working on whatever we were working on, forcing us to switch our attention to something else.
Many disruptions can be as trivial as a badly timed question from another team member. Have you seen my stapler?
Multi-tasking, or more correctly “task switching”, is another common cause of waste. Maybe we have been assigned to more than one project. Maybe we have to deal with bugs, support requests or some other feature suddenly being given a higher priority than whatever we were doing. And that’s all before even mentioning meetings.
To make matters worse, the waste caused by a disruption is not just the time we spend on something else than our task. It is also the time we need to spend to get back into what we were doing. The more complicated the task, the more time we will end up wasting.
Disruptions can be notoriously hard to eliminate and the solution will, obviously, depend on the type of the disruption. Some things to try:
- Turn off email and instant messaging notifications and check them manually during natural breaks instead.
- Team agreements, such as “When someone has got their headphones on, don’t disrupt them” or “Try to solve the problem on your own for 15 minutes first, before asking anyone else”.
- When a meeting is unavoidable, try to schedule it back-to-back with some other meeting or first thing or last thing during the day. This avoids chopping up the whole day into small bits. Also, do all participants really need to be there for the meeting?
- Guard against “urgent” tasks by asking “Is this really the most important thing we can be doing right now?”
- If we must deal with urgent live issues, might it be an option to rotate support duty to one person at a time? And can we reduce the number of issues through spending a bit of time improving our product?
4. Re-inventing the wheel
Re-inventing the wheel is something of a special case of waste from building the wrong thing.
We might already have the functionality we need elsewhere in our application, maybe just in need of a slight tweak. Or there might be a solution (or experience!) available in another team. On top of that, there is obviously a myriad of third party libraries.
My bet is that in most cases, the reason we keep re-inventing the wheel is that we aren’t aware that a solution already exists. Often, someone else in the team would have known, if we asked them, as they wrote or used something already. In other cases, the code is at fault. If it’s badly structured, it will be hard to find or re-use things.
It’s worth bearing in mind, though, that sometimes the unaware person is the person specifying what we’re supposed to be building. If they don’t understand what we’ve got already and how it works, they may unintentionally introduce requirements that are slightly different for no good reason.
Such requirements may end up causing us to have to build something new when a slight tweak would have allowed us to reuse something existing.
Better documentation is unlikely to be the primary solution to this sort of waste. Someone writing a document describing something won’t help if no one reads that document. Instead:
- Spread the knowledge! That’s the main reason why we in Scrum do sprint planning together as a team. Not least is the second half of the sprint planning, where the team decides on a solution and do a task breakdown. This is an excellent opportunity for someone to say: “We’ve got that already”. Or to go back to the Product Owner and ask “Can we do it this way instead, it will be a lot quicker and easier”.
- Use refactoring to ensure well written, well-structured code that is reusable.
Gold-plating is another special case of doing the wrong thing. Specifically, when we build something to a higher standard than we need to or add extra features of little value.
Often, this is caused by the best of intentions. We’re all motivated by doing well and achieving things we can be proud of. One way to do so is to do our work to a very high standard. Another is to try to be as efficient as possible by assuming what is likely to be needed later and do it now, as it’s quicker to do while we’re working on the same piece of code. A third is making use of some exciting new technology, either because it seems well suited to solve the problem or because it will look good on our CV.
The problem with gold-plating is that we get little value in return for our efforts. If something would do the job almost as well with considerably less effort, we’ve wasted valuable time. Not least since any code we write now will also need maintenance in the future, continually adding cost to our development. It could even go as far as us introducing unnecessary constraints for what we’ll be able to do, if changes become prohibitively expensive.
When the problem is our good intentions, the solution is to redirect them to somewhere they give the maximum benefit. I think the most important part of this is to shift the team’s efforts, from simply delivering features to delivering outcomes. It’s not about creating the most polished feature we possibly can, it’s about making the biggest impact.
- Identify the most important metric to improve for your product and involve the team in coming up with the solutions. Or, better still, let the team own the solution altogether, within given constraints.
- Grow a culture where everyone asks “Based on what we’re trying to achieve, is this the most important thing we could be doing right now?”
- Verify as quickly as possible whether your chosen metric is moving, by using small, incremental releases.
As we can see above, there are many ways we can end up letting our efforts go to waste. The good news, however, is that as soon as we become aware of the problem, we can start looking out for that waste and start reducing it.
What are the biggest sources of waste in software development you have seen? Share your thoughts below in the comments!