I first came across the idea of forcing function from reading The Checklist Manifesto by Atul Gawande. The premise is that in fields such as medicine, aviation, and construction, the art has advanced to a level of complexity that makes it nearly impossible to avoid simple, human mistakes. Avoiding those simple mistakes becomes the greatest challenge that these professionals face in their fields.
One of the most effective methods to combat complexity of this nature, Gawande noted, was the introduction of a written checklist. A guide to walk the experts through complex procedures step by step, circumventing common pitfalls.
Gawande borrowed the term "forcing function" from engineering, and described the use of a checklist as a forcing function that drives necessary behaviors to avoid human mistakes.
In lean manufacturing, Shigeo Shingo called this technique baka-yoke, literally "fool-proofing" in Japanese. Shingo applied this technique to redesign an industrial process to make it easy for the assembly line workers to detect mistakes early and correct them, thereby improving the quality of their work.
After reading about the different ways that other professions have applied the idea of forcing function in their routines, I started looking for forcing functions in our field. What can we do to reduce human mistakes in software development processes?
The Agile Checklist
I did not have to look far. As a coach, I often advise teams not to treat agile practices like a Happy Meal—only picking what works for you and not buying into all the mainstream processes blindly. On the flip side, sometimes these simple and routine checkpoints prescribed by the agile Happy Meal are exactly what the team needs.
Stand-ups, retrospectives, backlog refinement meetings, and so on, are communication tasks on the agile checklist that spark conversations between various stakeholders in order to move the project forward.
These processes are designed to force the team to create a space on their schedule to minimize the risk of miscommunication.
Agile Manifesto famously emphasized individuals and interactions over processes and tools, and while processes and tools can never replace real interactions, they can encourage more effective behaviors that enhance interactions if designed correctly.
Back in middle school, I used to get points taken off of a math problem because I forgot to "show all my work." While writing down the steps of how I arrived at the conclusion helps my instructor identify any mistake in my thought process and understanding of the problem, it was often hard for me to explain my answer.
As an intuitive problem-solver, I struggled with verbalizing and structuring my thought process.
Practicing test-driven development helped me tremendously in this regard.
Test-driven development is a behavior-shaping constraint I intentionally introduced to my workflow that forces me to make incremental steps and document them carefully. In doing so, I can stay focused and organized, and help others and my future self to dissect and follow my thought process.
Why Forcing Functions
As the field of software development becomes more advanced and our arsenal of frameworks and tools grows larger, one of the most daunting problems we face will be how to avoid simple, human mistakes. Perhaps we forgot to check the error log, misinterpreted a customer request, or skipped a testing scenario due to the stress of an imminent deadline.
Just like the surgeons in medicine, master craftsmen in construction, or pilots in aviation, we may think of ourselves as experts, but we are still humans and we are fallible. If a simple process change like following a checklist or writing tests first can help mitigate some of the mistakes that we make, then that is worth pursuing.