“I’m facing a dilemma. I must deliver the product by the end of this quarter, but there are still many tests I would like to execute. The product seems to be working, but even so I would like to run additional tests. However, if I do so I will miss the deadline. What should I do?”
Every programmer has been faced with this dilemma. And we all know what always happen in this case: The product is delivered on time, even with the risk of having some bugs. Meeting the deadline is considered more important than assuring 100% correctness.
There are many other situations in which a developer may make sacrifices to meet the deadline. This happens because the developer’s work is Multi-Objective. He must:
- Deliver on time.
- Deliver correct code.
- Deliver code with good design.
- Deliver well-documented code.
Frequently, there is not enough time to invest in all objectives, so some of them are assigned lower priority. This is the root of Technical Debt: A developer decides to postpone some task he should do now, because he does not have enough resources to satisfy all his objectives.
Now the question is: How do programmers decide what to postpone? How do they assign priorities to their conflicting tasks?
We would like to imagine that these decisions are being taken consciously and systematically. However, there are several unconscious and psychological influences. One of them is known as Loss Aversion.
“Loss Aversion refers to people’s tendency to strongly prefer avoiding losses to acquiring gains. Some studies suggest that losses are twice as powerful, psychologically, as gains.”
In one experiment people are presented with the following options:
- A certain loss of $100.
- A 50% risk of losing $200, with a 50% chance of not losing anything.
The first option represents the sure loss of a smaller amount, and the second option represents a risk of losing a higher amount. It was proved that most people prefer the second choice. In other words, in this situation most people would take the risk of losing a higher amount. As Kahneman’s writes:
“In bad choices, where a sure loss is comparable to a larger loss that is merely probable, diminishing sensitivity causes risk seeking.”
Let’s now see how this applies to software developers and their multiple objectives.
Risk Taking in Software Development
Going back to the programmer’s dilemma we presented in the beginning of this article, suppose a software developer is presented with the following choices:
- Continue testing the system and miss the deadline.
- Deliver the system as-is, with the risk of a serious bug being found afterwards.
The first option is a sure loss: The deadline is missed. The second option represents the risk of a higher loss: Perhaps the system has a serious bug, but perhaps not. Thus, because of Loss Aversion, the second option will be chosen by most programmers.
What makes things worse is that, for some objectives, quality is not being measured. So when a programmer decides not to invest in a task, he is not only taking a risk on the consequences of this decision. Actually, programmers gamble with the probability that their lack of investment will never be detected.
For example, it is hard to measure design quality. Very often, code-reviews are not systematic and technical debt is considered an acceptable “fact of life”. Technical debt may never be “paid”, and when it is paid, it will probably be paid by someone else.
It is also hard to measure documentation quality. There are not appropriate tools, and sometimes documentation is considered “nice-to-have”. Some programmers believe that documentation is superfluous and that code should be self-explainable.
Regarding testing, traditional development uses QA teams and it is expected that code will have bugs. Developers are not supposed to deliver 100% bug-free code.
However, in Test-Driven Development (TDD), developers are responsible for unit testing, and if the tests don’t run the code cannot be delivered. The programmer has an immediate feedback on the quality of his code, so there is no place left for risk taking.
In order to improve the quality of software systems, we should avoid risk-taking behaviors. Because of Loss Aversion, if we want to avoid risk-taking, each software development task should have its own tools and methods that allow programmers to receive immediate feedback on the quality of the code they are writing.