Test-driven development [TDD] is a way of thinking (Part 2)

Julio
7 min readJun 11, 2019

--

In part 1, we learned two things: that TDD is the practice of thinking backwards and that TDD better aligns developers with the business.

Both types of thinking are valid.

Even though we practice TDD at the IBM Garage, it’s not wrong to think forward. We use both on a regular basis.

We may ask ourselves in the morning, “Should I wear a raincoat today?” So, we search for data in the weather app to make a decision. We thought backwards.

Which athlete should receive the MVP award? Thinking backwards would start with a potential answer — an athlete — and work backwards to see if that athlete satisfies the MVP award. With so many options, this method may take awhile. It’ll be easier to think forward by starting with collecting data and working with that to conclude which athlete meets the criteria for the MVP.

Thinking forward is valuable in engineering practice.

If we only test drive — i.e., think backwards — the code we build may likely end up being superficial. If we build a thing that acts like XYZ, it doesn’t mean we built XYZ. Usually, business requirements come in some sort of expected behavior format, so TDD is only inspecting the code at a surface level.

Let’s use the Fahrenheit to Celsius problem as an example. Why is c = (f — 32) * 5/9? Thinking backwards, we know why. If we were to think forward, we need to answer the question: what are we modeling? Because c = (f — 32) * 5/9 is meaningless as far as we know.

If we were to spend more time analyzing the problem, it will make better sense to visually represent the problem in the Cartesian plane.

The three points cover our three test cases, but does this model cover the business’ requirement?

No, because the business wants the conversion formula to cover more than just three points. When we tried answering the question “which athlete should receive the MVP award?”, we thought forward because there were too many options. For this example, there are too many points to cover on the x-axis, so thinking forward is a better strategy.

If we use our prior knowledge of plane geometry, we can conclude that the Fahrenheit to Celsius formula is simply a linear equation that can be represented as y = mx + b, where m is the slope, and b is the y-intercept.

We also know that we can complete a line with only two points. The slope m can be found using the point-slope formula, and the y-intercept b can be found by substituting a point with the slope.

Here is the new code:

The new code makes a significant difference to the readability and understandability of the Fahrenheit to Celsius problem.

Previously, we modeled our solution as c = (f — 32) * 5/9. Now, it is modeled as a linear equation that connects two points: the freezing and boiling points, or (32,0) and (212,100), respectively.

The two points explain why it only took two test cases to test-drive the function. More importantly, our slope and y-intercept functions model the thought process that we followed to test-drive the second test (2.2 in part 1), only this time, that thought is not lost for all eternity. This design could not have been completed without thinking forward, but thinking forward comes at the cost of requiring the proper knowledge.

Novices naturally think backwards.

In an experiment where subjects were told to solve a physics problem, experts looked at the qualitative aspects and only stated the answer to a procedure. Meanwhile, novices looked at the quantitative aspects and stated the answer after finding the correct procedures from value substitutions. [1]

Even though finding an answer from value substitution may seem like a more sophisticated approach, it does not explain why the formula works. Remember when we crammed for finals in college? There was no time for a conceptual understanding. We just memorized the subject matter and applied it. That burden makes it more challenging to transfer concepts that apply to similar problems since the subject matter is only remembered at a surface level.

Novices think backwards when problem solving because they lack the fundamental framework to build models that can only be known with experience. That’s why the role of an architect is usually the responsibility of a more experienced senior.

When an expert knows the answer to a procedure, they naturally avoid the backwards thought-process. That’s why we initially solved the Fahrenheit to Celsius problem by thinking forward — because we are somewhat experts in temperature conversion. Thinking backwards is memory intensive. We need to hold key assumptions in mind and to verify that they hold as we continue thinking backwards.

However, when we test-drive, the key information that needs to be held while thinking backwards is preserved in the automated tests. Intensive working memory is left to the computer, for which it is much better-suited. Validating each step is done instantly, making it easy to take a step back when we get stuck. Test-driving makes it simpler and more practical to think backwards, something novices already do in a somewhat inefficient manner.

TDD is a learning tool, but many see it as a tool that has to be learned. Although the latter is true for most beginners, the eventual goal is the former.

Experts should also think backwards though.

It’s easy to think forward and make mistakes. Humans, like experts, are bound by many cognitive biases that impact decision making. We organize and cherry-pick facts that support our emotionally committed ideas to influence others. We connect beliefs of the outside world to the beliefs of ourselves and change our minds only if it benefits us or those around us. We selectively remember the good outcomes and not the bad ones. We seek information that confirms our prior knowledge, and in effect, build an extreme view. We are statistically less likely to change our minds after we pass a certain age. [2]

Two psychologists, Rosenblit and Keil, asked a number of participants how well they understood how things (like a speedometer, helicopter, etc.) work, and the participants answered in a 7-point scale. Then, they were told to explain in as much detail how that thing works. Followed by that, they were challenged with a question about how to operate the thing. Every time the participant’s understanding was tested, their level of confidence decreased. They started with an enormous amount of overconfidence and ended with a more calibrated under-confidence. The experiment shows us that people are overconfident of their knowledge. Rosenblit and Keil calls this the illusion of explanatory depth. [3]

It is believed that we have this illusion for a number of factors like underestimating how little we learn when we consume information, or how we falsely assume the lower level understanding when all we learned was the higher level.

All of these biases lead each person to come away with different conclusions when we have the same information. Thinking forward has its value, but it is not a replacement for thinking backwards.

Thinking forward lets us train our intuition, but thinking backwards helps us learn what we don’t know.

Throughout my 4 years at the IBM Garage…

…I have found that both types of thinking are best done at certain stages of the engagement.

During a development planning meeting, like Inception, it is not recommended to begin by communicating about the technical details with clients or anyone in the team just yet. Discussing technical details will trigger everyone to think forward, leading people to different conclusions because of the differences in expertise.

The time is better spent by talking about the user in the story. Everyone understands a well-told story. Once stories are told and business expectations are set, then we may want to start thinking forward by sharing our intuitions in architecture diagrams. The diagrams are rough drafts that are validated as the software is built using TDD — i.e., thinking backwards. While thinking backwards is the best choice for completing business requirements, thinking forward critiques our backwards thinking.

Special thanks to Jeanette Pranin and Davia Denisco for reading early drafts.

References:

  1. Larkin J, McDermott J, Simon D, Simon H (1980) Expert and Novice Performance in Solving Physics Problems. https://www.researchgate.net/publication/281345564_Expert_and_Novice_Performance_in_Solving_Physics_Problems/download
  2. Freakonomics Radio (2019) How to Change Your Mind (Ep. 379). http://freakonomics.com/podcast/change-your-mind/
  3. Rozenblit L, Keil F (2011) The misunderstood limits of folk science: an illusion of explanatory depth. https://www.ncbi.nlm.nih.gov/pmc/articles/PMC3062901/

Bring your plan to the IBM Garage.
Are you ready to learn more about working with the IBM Garage? We’re here to help. Contact us today to schedule time to speak with a Garage expert about your next big idea. Learn about our IBM Garage Method, the design, development and startup communities we work in, and the deep expertise and capabilities we bring to the table.

Schedule a no-charge visit with the IBM Garage.

--

--

Julio

Writing code for over 10 years and counting. I specialize in building scalable, full-stack cloud applications.