I recently read the following message in a developers’ forum (rephrased here):
“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 and its consequences are discussed by Daniel Kahneman in his book “Thinking, Fast and Slow”.
“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.
We have tools or practices to to get immediate feedback on code, even on tests. Do you have any to recommend for documentation? The only things I can think of offhand are company standards/templates, and maybe “pair authoring”. Of course good self-explanatory code will reduce the need for *programmer* docs, but there’s still end-user docs….
Dave, I’m currently participating in a research project focusing on the development of tools to measure documentation quality. We are considering creating new extensions to CheckStyle for Java.
I’ve seen tools to check the spelling, grammar, style, and reading level of text. But have you seen anything that addresses whether the docs completely and accurately describe the software? Maybe something that looks at the exposed functionality, and the headings in the docs, could address completeness. Accuracy, though, seems like it would take a lot more AI than the current state of the art.
Indeed the tools I know are relatively simple. I’ve seen research works trying to address more sophisticated semantic analysis. I will try to look for a reference and share it here later.
Dave, check this paper, which also has many interesting references: https://ece.uwaterloo.ca/~lintan/publications/@tComment-icst12.pdf
It’s not applicable to every situation, but one technique that I’ve always found useful in these situations is to loop in the stakeholder(s). Given that we have x objectives, and that not all can be met simultaneously, which ones take priority? In practice I’ve found that the business appreciates the collaboration and being able to control what is, ultimately, a business issue.
I agree Gene, but you talk about business stakeholders when I’ve witnessed the technical leadership not being able to understand the conflicting goals. I think that many software developers share this experience of a R&D manager or team leader establishing non-realistic deadlines. Some programmers call this the “Mission-Impossible” project.
True…if the technical leaders don’t understand the value of transparency to maintaining trust, then there’s problems ahead (very ironic given the usual reaction of the business). You can only pull so many miracles out of the bag.
“Which ones take priority?”
“All of them!”
“Which is your *highest* priority?”
“All of them!”
“Which *one* is highest priority?”
“They’re *all* highest priority!”
“So ‘make the company name a lighter shade of blue’ is just as high priority as ‘users can’t log in if their city starts with a vowel’?”
“Yes! Everything on my list is TOP priority, and MUST be done THIS WEEK. What’s so hard to understand about that? Make It So or I’ll find someone else who can!”
At some point, you may have to answer the last statement with “OK, go get ’em”.
Yourdon has called such projects a “Death March”… http://en.wikipedia.org/wiki/Death_march_(project_management)
Regarding TDD, I don’t think it’s a good idea to rely solely on unit test to get feedback on software quality. There are several degrees of funcionality, usability, completeness and other software qualities that only testers can detect.
So, you may end up thinking that unit tests cover you against loss aversion, but testing in the “traditional” meaning will be the risk you’re still taking.
BTW, unit tests are better than nothing 🙂
Great post Hayim!
Although in general terms I agree with your conclusion, I think it might not be feasible in many situations. In some of these cases, we could talk about “managing technical debt”. The idea is that you may acquire a technical debt provided that you pay your debt soon, or at lest that you manage it so it never gets “unpayable”.
But, whenever possible, I agree that what you’re suggesting is the best way.
Thanks for your comment, Fabio. Now, if we believe that “you can’t manage what you can’t measure”, then we need quality metrics and feedback.
Both technical debt and risk taking psychology is unavoidable. We can reduce it following various parameters or guidelines or following specific patterns and TDD. The only way we can minimize it when we have all experts and experienced team.
Thanks for your comment, Yogesh. I agree with you that experience is fundamental. But I think that in a team with good communication, a single experienced developer can have a great impact even if all others are beginners.
The key question is, can i overcome technical debt by other means in a cost effective way. The answer is most likely, yes. For example, consider Windows software, it is a “fatware” . Windows contain highly un-optimized code and probably might contain very high dead code too, but by throwing additional hardware resources, it “performs” , outweighing the technical dept.
Make the developments cycles shorter, and the QA feedback faster. Often this should work for you.
Pingback: Attention Agile Programmers: Project Management is not Software Engineering | Effective Software Design
All requirements and software features have to be driven and prioritized by the client and stakeholders. That means that all critical/frequent usage scenarios must to be covered by the both quality unit and functional testing. That effort has to be included in the product delivery estimates and cost.
For everything else there is the monitoring support time.
So, with that approach no developer should be ever faced with such risk choices.
I agree with you, but you are describing and ideal situation that unfortunately is very far from the reality in most projects.
This is where I think adding code review in the process would help. However, you do need a team with good level of experience and expertise in order for this to be effective.
Pingback: On the Real Danger of Quick-and-Dirty Programming | Effective Software Design
Pingback: The Problem with Velocity in Agile Software Development | Effective Software Design
Pingback: Why estimating cognitive effort simplifies knowledge work
Pingback: Why estimating cognitive effort simplifies knowledge work - WebSystemer.no
Pingback: Why estimating cognitive effort simplifies knowledge work – Launch Tomorrow