Examples of (bad) consequences of a lack of software quality and some solutions. This presentation presents some examples of (bad) consequences of a lack of software quality, in particular how poor software quality led to the direct deaths of 89 people. It then provides some background on software quality, especially the concept of Quality Without a Name. It then discusses many principles, their usefulness, and their positive consequences on software quality. Some of these principles are well-known in object-oriented programming while many others are taken from the book 97 Programmers. They include: abstraction, encapsulation, inheritance, types, polymorphism, SOLID, GRASP, YAGNI, KISS, DRY, Do Not Reinvent the Wheel, Law of Demeter, Beware of Assumptions, Deletable Code, coding with reason, and functional programming. They pertain to dependencies, domains, and tools.
(In details: Beautify is Simplicity, The Boy Scout Rule, You Gotta Care About the Code, The Longevity of Interim Solutions, Beware the Share, Encapsulate Behaviour not Just State, Single Responsibility Principle, WET Dilutes Performance Bottlenecks, Convenience Is Not an -ility, Code in the Language of the Domain, Comment Only What the Code Cannot Say, Distinguish Business Exception from Technical, Prefer Domain-specific Types to Primitive Types, Automate Your Coding Standards, Code Layout Matters, Before You Refactor, Improve Code by Removing It, Put the Mouse Down and Step Away from the Keyboard)
Unlocking the Future of AI Agents with Large Language Models
Consequences and Principles of Software Quality v0.3
1. Yann-Gaël Guéhéneuc
This work is licensed under a Creative
Commons Attribution-NonCommercial-
ShareAlike 3.0 Unported License
Yann-Gaël Guéhéneuc
Software Quality
yann-gael.gueheneuc@concordia.ca
Version 0.2
2024/03/01
5. 5/74
Context
Consequences of Poor Quality
– Toyota Software Glitches Killed 89 People
– Reasons for Poor Quality
A Message to the Future
Write Code as If You Had to Support It for
the Rest of Your Life
8. 8/74
Consequences of Poor Quality
Just a few examples among many
The Therac-25 incident: a
cautionary tale in
software errors
UK Post Office software
bug led to convicting 736
innocent employees
TUI airline miscalculated
flight loads
Citibank UX caused a
$500 million failure
Knight Capital Group
$440M loss due to bad
trades
Toyota software glitches
killed 89 people
Uber sued for $45 million
because of a notification
showing after log-out
Nest Thermostat update
left users in the cold
because of software bugs
https://softwaremill.com/bad-software-examples-how-much-can-poor-code-hurt-you/
10. 10/74
Reasons for Poor Quality
MISRA C
– Motor Industry Software Reliability Association
– Software development guidelines
Toyota not always followed guidelines
– MISRA C
– Its own
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
11. 11/74
Reasons for Poor Quality
Electronic Throttle Control System (ETCS)
https://static.nhtsa.gov/odi/inv/2014/INRD-DP14003-60186P.pdf
12. 12/74
Reasons for Poor Quality
Post-mortem analyses
– NASA
• 14 of 35 rules violated for 7,134 violations
• E.g., 105/343 “switch” blocks without “default”
– Barr’s team
• 80,000 violations of MISRA C
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
13. 13/74
Reasons for Poor Quality
McCabe Cyclomatic Complexity metric of
ETCS code
– 67 functions with complexity over 50
– Throttle angle function complexity of 146
• 1,300 lines long, no unit test plan
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
14. 14/74
Reasons for Poor Quality
McCabe Cyclomatic Complexity metric of
ETCS code
– 67 functions with complexity over 50
– Throttle angle function complexity of 146
• 1,300 lines long, no unit test plan
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
15. 15/74
Reasons for Poor Quality
Global variables in ETCS code
– Ideally, 0
– 4,720 read-only & text variables
– 11,253 read/write variables
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
16. 16/74
Reasons for Poor Quality
Global variables in ETCS code
– Ideally, 0
– 4,720 read-only & text variables
– 11,253 read/write variables
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
17. 17/74
Reasons for Poor Quality
Concurrency bugs
– Difficult to identify, reproduce
– Nested scheduler unlocks
– Shared global variables
• Not all “volatile”
• Not all masked
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
18. 18/74
Reasons for Poor Quality
Concurrency bugs
– Difficult to identify, reproduce
– Nested scheduler unlocks
– Shared global variables
• Not all “volatile”
• Not all masked
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
19. 19/74
Reasons for Poor Quality
Recursion and overflow
– Safety rules typically forbid recursion
– Stack 94% full + any recursion
– Overflow not always causing reset
– Memory after stack is OSEK RTOS
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
20. 20/74
Reasons for Poor Quality
Recursion and overflow
– Safety rules typically forbid recursion
– Stack 94% full + any recursion
– Overflow not always causing reset
– Memory after stack is OSEK RTOS
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
21. 21/74
Reasons for Poor Quality
And also
– Wrongly coded watchdog
– Ignoring RTOS error codes
– Major task excluded from watchdog
– No single responsibility
– Many large functions
– No configuration management
– No bug tracking system
https://users.ece.cmu.edu/~koopman/pubs/koopman14_toyota_ua_slides.pdf
25. 25/74
A Message to the Future
(By Linda Rising)
“Think of every line of code you write as a
message for someone in the future”
– “Pretend you're explaining to this smart [programmer]
how to solve this tough problem”
“That the smart programmer in the future [should]
see your code and say, 'Wow! This is great!”
– “I can understand perfectly what's been done here and
I'm amazed at what an elegant”
– “I'm going to show the other folks on my team”
26. 26/74
Write Code as If You Had to Support
It for the Rest of Your Life
(By Yuriy Zubarev)
“[H]ow do you keep up with all the best
practices you've learned and how do you
make them an integral part of your
programming practice?”
“I think the answer lies in your frame of mind
or, more plainly, in your attitude.”
28. 28/74
Quality
Quality Without a Name
Technical Debt
Beautify is Simplicity
The Boy Scout Rule
You Gotta Care About the Code
The Longevity of Interim Solutions
30. 30/74
Quality Without a Name
“There is a point you reach in tightening a nut, where you
know that to tighten just a little more might strip the thread,
but to leave it slightly looser would risk having the hut
coming off from vibration. If you've worked with your hands
a lot, you know what this means, but the advice itself is
meaningless.”
—Robert Pirsig, circa. 1972
31. 31/74
Quality Without a Name
“There is a point you reach in tightening a nut, where you
know that to tighten just a little more might strip the thread,
but to leave it slightly looser would risk having the hut
coming off from vibration. If you've worked with your hands
a lot, you know what this means, but the advice itself is
meaningless.”
—Robert Pirsig, circa. 1972
32. 32/74
Quality Without a Name
“There is a point you reach in tightening a nut, where you
know that to tighten just a little more might strip the thread,
but to leave it slightly looser would risk having the hut
coming off from vibration. If you've worked with your hands
a lot, you know what this means, but the advice itself is
meaningless.”
—Robert Pirsig, circa. 1972
“[T]oo often software developers spend their days grinding
away for pay at programs they neither need nor love. But
not in the Linux world - which may explain why the
average quality of software originated in the Linux
community is so high.”
—Eric Raymond, 1998
34. 34/74
Quality Without a Name
ニワトリのヒナの雌雄鑑別
(chick sexing)
http://discovermagazine.com/2011/sep/18-your-brain-knows-lot-more-than-you-realize
35. 35/74
Quality Without a Name
ニワトリのヒナの雌雄鑑別
(chick sexing)
“The master would stand over the
apprentice and watch. The student
would pick up a chick, examine its
rear, and toss it into one bin or the
other. The master would give
feedback: yes or no.”
—Eagleman, 2011
http://discovermagazine.com/2011/sep/18-your-brain-knows-lot-more-than-you-realize
36. 36/74
Quality Without a Name
public void diso() throws CorruptIndexException, FileNotFoundException, IOException
DISCO disco = DISCO.load("cc.en.300-COL.denseMatrix");
float sim = disco.semanticSimilarity("shopping", "product", DISCO.getVectorSimi
System.out.println("++++++++++++++++++++++++++++++++++++++++++similarity betwee
// get word vector for "Haus" as map
Map<String,Float> wordVectorHaus = disco.getWordvector("shopping");
// get word embedding for "Haus" as float array
float[] wordEmbeddingHaus = ((DenseMatrix) disco).getWordEmbedding("shopping");
// solve analogy x is to "Frau" as "König" is to "Mann"
try {
List<ReturnDataCol> result = Compositionality.solveAnalogy("bride", "groom", "c
} catch (WrongWordspaceTypeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
37. 37/74
Technical Debt
"As [a] program is continually changed, its
complexity, […] deteriorating structure, increases
unless work is done to maintain or reduce it."
—Meir Manny Lehman, 1980
“Every minute spent on not-quite-right code counts
as interest on that debt. Entire engineering
organizations can [stop] under the debt load[…]"
—Ward Cunningham, 1992”
38. 38/74
Beautify is Simplicity
(By Jørn Ølmheim)
“Beauty of style and harmony and grace and
good rhythm depends on simplicity.”
— Plato
“Plato is telling us that the enabling factor for
all of these qualities is simplicity.”
39. 39/74
The Boy Scout Rule
(by Uncle Bob aka Robert C. Martin)
“Always leave the campground cleaner than
you found it.”
“[L]eaving a mess in the code should be as
socially unacceptable as littering.”
“Teams help each other, and clean up after
each other. They follow the Boy Scout rule
because it's good for everyone”
40. 40/74
You Gotta Care About the Code
(By Pete Goodliffe)
“No programmer is an island.”
https://www.creativefabrica.com/it/product/palm-tree-with-small-island/
52. 52/74
The Longevity of Interim Solutions
(By Klaus Marquardt)
Why?
– “It is useful.”
Consequences?
– “[I]nterim solution remains in place. Forever.”
– Not “with accepted production quality”
What to do then?
– “Change the forces that influence the decision”
56. 56/74
Encapsulation
In the 1980s, object-oriented programming
languages became popular, in part because they
propose encapsulation
Encapsulation is
– A language mechanism for restricting access to some of
the object's components
• Modifiers public, protected, private…
– A language construct to bundle data with the methods
operating on that data
• Classes and objects
57. 57/74
Encapsulation
In the 1980s, object-oriented programming
languages became popular, in part because they
propose encapsulation
Encapsulation is
– A language mechanism for restricting access to some of
the object's components
• Modifiers public, protected, private…
– A language construct to bundle data with the methods
operating on that data
• Classes and objects
Fundamental to OO
programming languages
58. 58/74
Inheritance, Types
Reuse and subtyping
combined
– To factor out code,
e.g., in PADL
– To create a taxonomy,
e.g., in Java libraries
59. 59/74
Polymorphism
Definition
– Subtype polymorphism, almost universally called
polymorphism in object-oriented programming
– The ability to create a variable, a function, or an
object that has more than one form
– Superset of overloading, overriding
Problem: change behaviour of concrete objects
Solution: polymorphism
60. 60/74
Overriding, Overloading
Overriding
– A language feature that allows a subclass or a
child class to provide a specific
implementation of a method that is already
provided by one of its super / parent classes
Overloading
– Methods that have the same name but different
signatures inside the same class or a class
hierarchy
61. 61/74
Abstraction, Types
From worst to best
BankAccount
1. ArrayList
getBankAccounts()
2. List
getBankAccounts()
3. Iterator
getBankAccounts()
Shape
1. Vector
getPoints()
2. Vector
getPoints()
3. Iterator
getPoints()
62. 62/74
Missing Opportunities for
Polymorphism
(By Kirk Pepperdine)
“[P]olymorphic coding style will yield a
smaller, more readable and less fragile code
base. The number of missed opportunities is
a simple count of the if-then-else statements
in our code.”
69. 69/74
Do Not Reinvent the Wheel
Before implementing a feature, always look
for simpler, existing solutions
– Existing piece of code?
– Existing libraries?
Beware when reusing an existing solution
– Licensing issues
– Dependency issues
– Ratio cost / benefit in the long term
74. 74/74
Beware the Share
(By Udi Dahan)
“The code review that I had felt so ready for
came as a rude awakening — reuse was
frowned upon!”
“Context. […] Up until I had pulled out those
libraries of shared code, these parts were
not dependent on each other. Each could
evolve independently.”
75. 75/74
Encapsulate Behavior, not Just State
(By Einar Landre)
“[D]evelopers might decide to wrap all the
business rules into an object very often
referred to as OrderManager or
OrderService. In these designs, Order,
Customer, and Item are treated as little more
than record types.
76. 76/74
Single Responsibility Principle
(by Uncle Bob aka Robert C. Martin)
“Gather together those things that change
for the same reason and separate those
things that change for different reasons.”
public class Employee {
public Money calculatePay() {
//...
}
public String reportHours() {
//...
}
public void save() {
//...
}
}
77. 77/74
Single Responsibility Principle
(by Uncle Bob aka Robert C. Martin)
“Gather together those things that change
for the same reason and separate those
things that change for different reasons.”
public class Employee {
public Money calculatePay() {
//...
}
public String reportHours() {
//...
}
public void save() {
//...
}
}
public class Employee {
public Money calculatePay() {
//...
}
}
public class EmployeeReporter {
public String reportHours(Employee e) {
//...
}
}
public class EmployeeRepository {
public void save(Employee e) {
//...
}
}
78. 78/74
WET Dilutes Performance
Bottlenecks (By Kirk Pepperdine)
“The performance implications of DRY
versus WET become very clear when you
consider their […] effects on [performance].”
private ArrayList<Customer> allCustomers = ...;
// ...
public ArrayList<Customer> findCustomersThatSpendAtLeast(Money amount) {
ArrayList<Customer> customersOfInterest = new ArrayList<Customer>();
for (Customer customer : allCustomers) {
if (customer.spendsAtLeast(amount))
customersOfInterest.add(customer);
}
return customersOfInterest;
}
79. 79/74
WET Dilutes Performance
Bottlenecks (By Kirk Pepperdine)
“The performance implications of DRY
versus WET become very clear when you
consider their […] effects on [performance].”
public class CustomerList {
private ArrayList<Customer> customers = new ArrayList<Customer>();
private SortedList<Customer> customersSortedBySpendingLevel =
new SortedList<Customer>();
// ...
public CustomerList findCustomersThatSpendAtLeast(Money amount) {
return new CustomerList(
customersSortedBySpendingLevel.elementsLargerThan(amount));
}
}
81. 81/74
Domain
Convenience Is Not an -ility
Code in the Language of the Domain
Comment Only What the Code Cannot Say
Distinguish Business Exception from
Technical
Prefer Domain-specific Types to Primitive
Types
82. 82/74
Convenience Is Not an -ility
(By Gregor Hohpe)
“Most experienced programmers have
learned that a good API follows a consistent
level of abstraction, exhibits consistency and
symmetry, and forms the vocabulary for an
expressive language.”
parser.processNodes(text, false);
83. 83/74
Code in the Language of the Domain
(By Dan North)
“Making domain concepts explicit in your
code means other programmers can gather
the intent of the code much more easily than
by trying to retrofit an algorithm into what
they understand about a domain.”
if (portfolioIdsByTraderId
.get(trader.getId())
.containsKey(portfolio.getId())) {
// ...
}
if (trader.canView(portfolio)) {
// ...
}
VS.
84. 84/74
Comment Only What the Code
Cannot Say (By Kevlin Henney)
“"a comment is of zero (or negative) value if
it is wrong."”
“Comments that parrot the code offer
nothing extra to the reader”
“Comments should say something code
does not and cannot say.”
“Comment what the code cannot say, not
simply what it does not say.”
85. 85/74
Distinguish Business Exception from
Technical (By Dan Bergh Johnsson)
“An unresolvable technical problem can
occur when there is a programming error.”
“In contrast to these, we have the situation
where you cannot complete the call for a
domain-logical reason.”
“Mixing technical exceptions and business
exceptions in the same hierarchy blurs the
distinction and confuses the caller about
what the method contract is”
86. 86/74
Prefer Domain-specific Types to
Primitive Types (By Einar Landre)
“In Java, C++, Python, and
[others,] the abstract data
type is known as class.”
“Using classes such as
Velocity_In_Knots and
Distance_In_Nautical_
Miles adds a lot of […]
code quality”
The code becomes more
readable as it expresses
concepts of a domain, not
just Float or String.
The code becomes more
testable as the code
encapsulates behavior that
is easily testable.
The code facilitates reuse
across applications and
systems.
88. 88/74
Tools
Automate Your Coding Standards
Code Layout Matters
Before You Refactor
Improve Code by Removing It
Put the Mouse Down and Step Away from
the Keyboard
89. 89/74
Automate Your Coding Standards
(By Filip van Laenen)
“Well-formatted code
doesn't earn you points
with a customer that wants
more functionality.”
“Make sure code
formatting is part of the
build process, so that
everybody runs it
automatically every time
they compile the code.
Use static code analysis
tools to scan the code for
unwanted anti-patterns. If
any are found, break the
build.”
90. 90/74
Code Layout Matters
(By Steve Freeman)
“People are really good at visual pattern
matching”
“The code's layout is part of this
expressiveness too.”
“The more I can get on a screen, the more I
can see without breaking context”
91. 91/74
Before You Refactor
(By Rajith Attapattu)
“[Start] by taking stock of the existing
codebase and the tests written against that
code.”
“Avoid the temptation to rewrite everything.”
“Many incremental changes are better than
one massive change.”
“After each iteration, it is important to ensure
that the existing tests pass.”
92. 92/74
Improve Code by Removing It
(By Pete Goodliffe)
“What are you working on right now? Is it all
needed?”
93. 93/74
Put the Mouse Down and Step Away
from the Keyboard (By Burk Hufnagel)
“[While] you're coding, the logical part of
your brain is active, and the creative side is
shut out. It can't present anything to you until
the logical side takes a break.”