This is the third post in a series about what makes a team effective. Effective means, the team does the right thing to reach its goal.
When we have a goal in front of us, we tend to think about how we can get there in a single fast step. However, most of the times in software development the goal moves while we are walking towards it. Either because our customer sees our progress and has a better idea, or because we understand the problem a bit clearer and find a better solution.
When the goal moves and we wanted to get there in a single big step, we invested a lot:
- we designed the whole solution up front and
- we probably implemented code that is no longer needed and needs to be removed again (resulting in additional costs)
Effective teams tackle a problem in small steps. They don’t want to get to the goal in a single big step at once, but they make a single small step into the direction of the goal. A minimal increment. This results in much less initial design (and potential waste) and the team can get feedback from the stakeholders much faster. When the goal moves, the team can direct its next small step in a new direction.
Working in small steps results in much less waste due to quicker feedback (verification of right direction) and less unnecessary work.
Incremental and iterative
These small steps are done by building software incrementally and iteratively. Each increment adds a new little feature and every iteration makes existing features a bit richer.
The first increment of a new feature is often a spike. A spike is a very narrow end-to-end solution. It provides almost no functionality, but goes through the whole system (e.g. from UI down to the database). In order to start with a very narrow spike, we make a lot of assumptions and simplifications (there are no error cases, the user makes no wrong input, the user can decrypt our raw data output) and build only the happiest possible path. Then we iterate on the feature and remove assumptions and simplifications (okay the user makes wrong inputs, the file really may not be on the hard disk, …). When there are no assumptions and simplifications left, we enrich the feature by adding functionality (e.g. filtering of search results)
Starting a new feature with a spike helps us to quickly build up a lot of knowledge about the feature itself, about the technology we use and about our solution. With the gained knowledge we are capable of making the right decisions about how to proceed implementing a solution. Finally, if there is enough time we can enrich the feature or release the software early because everything is functional.
We want to implement the following user story:
Our usability expert makes a draft mock-up of the UI (just enter some text, hit Search and see the result [I’m sure you are familiar with this approach 🙂 ])
We make a spike for this functionality with the following assumptions and simplifications:
- the user always search by entering a complete name (simplifies query)
- we have the searched person in our data (no not found special case)
- the result set contains only one person (simplifies result display)
Then we can start to eliminate assumptions and simplifications
- user searches by a partial name
- user searches by a partial number
- user searches with a combination of fields
- search results in multiple records
Finally, we can enrich our solution by showing better search results:
- show more data
- sortable grid (but that is probably unnecessary [or can you sort on Google??] )
Making small steps, we hopefully noticed that the solution is good enough before we implemented a sortable grid that no user ever will need.
Starting with a minimal solution and taking small steps helps the team to make informed decisions. Decisions about details are made when we already solved the big picture problems and therefore know much more about the problem and the solution.