Assumptions
As software developers it is our job to test our assumptions. So how do you go about knowing, testing, and rethinking them?
As software developers we have to make assumptions. Making assumptions is our job.
But making assumptions is easy. Knowing your assumptions, testing, rethinking, and acting on them is hard.
As software developers it is our job to test our assumptions. So how do you go about knowing, testing, and rethinking them?
For this post, I am talking about assumptions we make about how software systems work. The kind of assumptions we need to make to build, test, and debug software. However, we all make assumptions about how the world works too. Knowing, testing, and rethinking our assumptions about the world is as important as doing this practice in our work.
Recognizing Assumptions
When you look at a software system it can be hard to know, innately, what your assumptions are about it. You may be deeply embedded in the system and think "this is just how it works, though" or you may be familiar with the framework and have a fundamental belief about how it functions.
To recognize my assumptions I need to test them by saying them out loud. On pair programming calls in planning sessions I often pause and reflect what I believe to be true about a system to others I'm talking with.
I ask people to question my statements and I often start by questioning them myself. This is an important practice because it helps turn my beliefs about a system into assumptions that can be tested.
I don't always succeed at recognizing my assumptions. But pausing to state how I think the system works helps me focus on whether my fundamental assumptions about the system are true and how they might influence the outcome.
Testing Assumptions
At times, testing assumptions is as easy as writing some code and seeing the results. These are the easy ones. Lets say you open up an old file and notice that there are no tests. The file is complex and appears to "just work."
Testing assumptions in this case is as easy as writing tests. I frequently use tests to help me understand existing functionality. I'll write tests that fail in order to see the correct output and learn how the system works.
Other times I need a more data-driven approach. In a project a few years ago we were upgrading a GraphQL server from a very old version of Apollo Server to a newer one. We had the assumption that the change would go un-noticed by clients but we needed to test this.
We built a new server to run side-by-side with the new one and sent requests to both servers and compared the results and latency. This allowed us to carefully validate our assumptions without impacting client experience.
Finally, there are times when all we have is data on an event or incident and we need to figure out what happened. In these situations we need to state our assumptions about how the system works and then look to the data to validate our ideas.
Rethinking Assumptions
This is the hardest part. Once you know we have made an assumption, you have to be open to being wrong and you have to know what to do if it is correct.
Being proven wrong is a good thing. As odd as it sounds, learning that your assumption about a system is wrong is empowering because you now know more about the system.
This is where the whole process starts over again. If my assumption is proven wrong, I take in this information, look at the system again and test out a new assumption.
If my assumption about a system is proven correct, I use this information to extrapolate and ask what I can learn next.
Act on Assumptions
I have proposed a circular process of stating, testing, and rethinking assumptions. But it is important that this process moves forward. Moving towards a better understanding of a software system enables us to make the system better, extend it, and make it faster.
There will always be a point in this cycle where you have to decide that the data you have points you in a direction and you are going to continue down that path.
Be wary of spiralling. Catch yourself from a cycle of self-doubt and use this process to move forward. The cycle of testing and rethinking is meant to refine your knowledge and skills. Once you have tested your assumptions about a system you can move forward in your understanding of the system.