Good Code
@KevlinHenney
Four basic premises
of writing: clarity,
brevity, simplicity,
and humanity.
William Zinsser
Let us examine [software's]
difficulties. Following Aristotle, I
divide them into essence — the
difficulties inherent in the nature
of software — and accidents —
those difficulties that today
attend its production but that
are not inherent.
How much of what software
engineers now do is still
devoted to the accidental, as
opposed to the essential?
http://cacm.acm.org/magazines/2014/2/171689-mars-code
There are standard precautions that can
help reduce risk in complex software
systems. This includes the definition of a
good software architecture based on a
clean separation of concerns, data hiding,
modularity, well-defined interfaces, and
strong fault-protection mechanisms.
Gerard J Holzmann
"Mars Code", CACM 57(2)
http://cacm.acm.org/magazines/2014/2/171689-mars-code/fulltext
Firmitas
Utilitas
Venustas
Habitability is the characteristic of
source code that enables programmers,
coders, bug-fixers, and people coming
to the code later in its life to
understand its construction and
intentions and to change it comfortably
and confidently.
Habitability makes a place livable, like
home. And this is what we want in
software — that developers feel at
home, can place their hands on any
item without having to think deeply
about where it is.
Comments
A delicate matter, requiring taste and judgement. I tend to err on the side of
eliminating comments, for several reasons. First, if the code is clear, and uses
good type names and variable names, it should explain itself. Second, comments
aren't checked by the compiler, so there is no guarantee they're right, especially
after the code is modified. A misleading comment can be very confusing. Third,
the issue of typography: comments clutter code.
Rob Pike, "Notes on Programming in C"
There is a famously bad comment style:
i=i+1; /* Add one to i */
and there are worse ways to do it:
/**********************************
* *
* Add one to i *
* *
**********************************/
i=i+1;
Don't laugh now, wait until you see it in real life.
Rob Pike, "Notes on Programming in C"
A common fallacy is to assume authors
of incomprehensible code will somehow
be able to express themselves lucidly
and clearly in comments.
Kevlin Henney
https://twitter.com/KevlinHenney/status/381021802941906944
http://www.bonkersworld.net/object-world/
http://www.bonkersworld.net/object-world/
OBJECT-ORIENTED
VenetianBlind Door
Television
Picture
Glass
Sofa
TelevisionRemoteControl
Peephole
Naomi Epel
The Observation Deck
if (portfolioIdsByTraderId.get(trader.getId())
.containsKey(portfolio.getId()))
{
...
}
Dan North, "Code in the Language of the Domain"
97 Things Every Programmer Should Know
if (trader.canView(portfolio))
{
...
}
Dan North, "Code in the Language of the Domain"
97 Things Every Programmer Should Know
Details count.
Peter Weinberger
Architecture represents
the significant design
decisions that shape a
system, where
significant is measured
by cost of change.
Grady Booch
http://www.theregister.co.uk/2016/03/23/npm_left_pad_chaos/
function leftpad (str, len, ch) {
str = String(str);
var i = -1;
if (!ch && ch !== 0) ch = ' ';
len = len - str.length;
while (++i < len) {
str = ch + str;
}
return str;
}
function leftpad(content, length, pad) {
content = String(content)
pad = String(pad || pad === 0 ? pad : ' ')[0]
var left = Math.max(length - content.length, 0)
return pad.repeat(left) + content
}
var cache = [
'',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' ',
' '
];
function leftPad (str, len, ch) {
// convert `str` to `string`
str = str + '';
// `len` is the `pad`'s length now
len = len - str.length;
// doesn't need to pad
if (len <= 0) return str;
// `ch` defaults to `' '`
if (!ch && ch !== 0) ch = ' ';
// convert `ch` to `string`
ch = ch + '';
// cache common use cases
if (ch === ' ' && len < 10) return cache[len] + str;
// `pad` starts with an empty string
var pad = '';
// loop
while (true) {
// add `ch` to `pad` if `len` is odd
if (len & 1) pad += ch;
// divide `len` by 2, ditch the remainder
len >>= 1;
// "double" the `ch` so this operation count grows logarithmically on `len`
// each time `ch` is "doubled", the `len` would need to be "doubled" too
// similar to finding a value in binary search tree, hence O(log(n))
if (len) ch += ch;
// `len` is 0, exit the loop
else break;
}
// pad `str`!
return pad + str;
}
I have yet to see any problem,
however complicated, which,
when you looked at it in the
right way, did not become still
more complicated.
Anderson's Law
truths = {
"Padding an empty string to a length of 0 results in an empty string":
leftpad("", 0, "X") === "",
"Padding a non-empty string to a shorter length results in the same string":
leftpad("foobar", 3, "X") === "foobar",
"Padding a non-empty string to a negative length results in the same string":
leftpad("foobar", -3, "X") === "foobar",
"Padding a non-empty string to its length results in the same string":
leftpad("foobar", 6, "X") === "foobar",
"Padding to a longer length with a single character fills to the left":
leftpad("foobar", 8, "X") === "XXfoobar",
"Padding to a longer length with surplus characters fills using only first":
leftpad("foobar", 10, "XY") === "XXXXfoobar",
"Padding to a longer length with an empty string fills with space":
leftpad("foobar", 8, "") === " foobar",
"Padding to a longer length with no specified fill fills with space":
leftpad("foobar", 9) === " foobar",
"Padding to a longer length with integer 0 fills with 0":
leftpad("foobar", 7, 0) === "0foobar",
"Padding to a longer length with single-digit integer fills with digit":
leftpad("foobar", 10, 1) === "1111foobar",
"Padding to a longer length with multiple-digit integer fills with first digit":
leftpad("foobar", 10, 42) === "4444foobar",
"Padding to a longer length with negative integer fills with -":
leftpad("foobar", 8, -42) === "--foobar",
"Padding a non-string uses string representation":
leftpad(4.2, 5, 0) === "004.2",
}
truths = {
"Padding an empty string to a length of 0 results in an empty string":
leftpad("", 0, "X") === "",
"Padding a non-empty string to a shorter length results in the same string":
leftpad("foobar", 3, "X") === "foobar",
"Padding a non-empty string to a negative length results in the same string":
leftpad("foobar", -3, "X") === "foobar",
"Padding a non-empty string to its length results in the same string":
leftpad("foobar", 6, "X") === "foobar",
"Padding to a longer length with a single character fills to the left":
leftpad("foobar", 8, "X") === "XXfoobar",
"Padding to a longer length with surplus characters fills using only first":
leftpad("foobar", 10, "XY") === "XXXXfoobar",
"Padding to a longer length with an empty string fills with space":
leftpad("foobar", 8, "") === " foobar",
"Padding to a longer length with no specified fill fills with space":
leftpad("foobar", 9) === " foobar",
"Padding to a longer length with integer 0 fills with 0":
leftpad("foobar", 7, 0) === "0foobar",
"Padding to a longer length with single-digit integer fills with digit":
leftpad("foobar", 10, 1) === "1111foobar",
"Padding to a longer length with multiple-digit integer fills with first digit":
leftpad("foobar", 10, 42) === "4444foobar",
"Padding to a longer length with negative integer fills with -":
leftpad("foobar", 8, -42) === "--foobar",
"Padding a non-string uses string representation":
leftpad(4.2, 5, 0) === "004.2",
}
truths = {
"Padding an empty string to a length of 0 results in an empty string":
leftpad("", 0, "X") === "",
"Padding a non-empty string to a shorter length results in the same string":
leftpad("foobar", 3, "X") === "foobar",
"Padding a non-empty string to a negative length results in the same string":
leftpad("foobar", -3, "X") === "foobar",
"Padding a non-empty string to its length results in the same string":
leftpad("foobar", 6, "X") === "foobar",
"Padding to a longer length with a single character fills to the left":
leftpad("foobar", 8, "X") === "XXfoobar",
"Padding to a longer length with surplus characters fills using only first":
leftpad("foobar", 10, "XY") === "XXXXfoobar",
"Padding to a longer length with an empty string fills with space":
leftpad("foobar", 8, "") === " foobar",
"Padding to a longer length with no specified fill fills with space":
leftpad("foobar", 9) === " foobar",
"Padding to a longer length with integer 0 fills with 0":
leftpad("foobar", 7, 0) === "0foobar",
"Padding to a longer length with single-digit integer fills with digit":
leftpad("foobar", 10, 1) === "1111foobar",
"Padding to a longer length with multiple-digit integer fills with first digit":
leftpad("foobar", 10, 42) === "4444foobar",
"Padding to a longer length with negative integer fills with -":
leftpad("foobar", 8, -42) === "--foobar",
"Padding a non-string uses string representation":
leftpad(4.2, 5, 0) === "004.2",
}
toMap = object => new Map(Object.entries(object))
format = (proposition, ok) =>
proposition.fontcolor(ok ? "green" : "red") + "<br>"
present = truths =>
toMap(truths).forEach(
(ok, proposition) =>
write(format(proposition, ok)))
present(truths)
Padding an empty string to a length of 0 results in an empty string
Padding a non-empty string to a shorter length results in the same string
Padding a non-empty string to a negative length results in the same string
Padding a non-empty string to its length results in the same string
Padding to a longer length with a single character fills to the left
Padding to a longer length with surplus characters fills using only first
Padding to a longer length with an empty string fills with space
Padding to a longer length with no specified fill fills with space
Padding to a longer length with integer 0 fills with 0
Padding to a longer length with single-digit integer fills with digit
Padding to a longer length with multiple-digit integer fills with first digit
Padding to a longer length with negative integer fills with -
Padding a non-string uses string representation
Padding an empty string to a length of 0 results in an empty string
Padding a non-empty string to a shorter length results in the same string
Padding a non-empty string to a negative length results in the same string
Padding a non-empty string to its length results in the same string
Padding to a longer length with a single character fills to the left
Padding to a longer length with surplus characters fills using only first
Padding to a longer length with an empty string fills with space
Padding to a longer length with no specified fill fills with space
Padding to a longer length with integer 0 fills with 0
Padding to a longer length with single-digit integer fills with digit
Padding to a longer length with multiple-digit integer fills with first digit
Padding to a longer length with negative integer fills with -
Padding a non-string uses string representation
For every activity there is a
certain appropriate scale.
The Facebook iOS app has
over 18,000 Objective-C
classes, and in a single week
429 people contributing to it.
Facebook's code quality problem
Graham King
http://www.darkcoding.net/software/facebooks-code-quality-problem/
Your customers do
not buy your
software by the line.
David Evans
Quote from Kevlin Henney
Graphic by Sebastian Hermida
http://sbastn.com/2009/06/typing-is-not-the-bottleneck/

Good Code

  • 1.
  • 5.
    Four basic premises ofwriting: clarity, brevity, simplicity, and humanity. William Zinsser
  • 8.
    Let us examine[software's] difficulties. Following Aristotle, I divide them into essence — the difficulties inherent in the nature of software — and accidents — those difficulties that today attend its production but that are not inherent.
  • 9.
    How much ofwhat software engineers now do is still devoted to the accidental, as opposed to the essential?
  • 10.
  • 11.
    There are standardprecautions that can help reduce risk in complex software systems. This includes the definition of a good software architecture based on a clean separation of concerns, data hiding, modularity, well-defined interfaces, and strong fault-protection mechanisms. Gerard J Holzmann "Mars Code", CACM 57(2) http://cacm.acm.org/magazines/2014/2/171689-mars-code/fulltext
  • 12.
  • 16.
    Habitability is thecharacteristic of source code that enables programmers, coders, bug-fixers, and people coming to the code later in its life to understand its construction and intentions and to change it comfortably and confidently.
  • 17.
    Habitability makes aplace livable, like home. And this is what we want in software — that developers feel at home, can place their hands on any item without having to think deeply about where it is.
  • 21.
    Comments A delicate matter,requiring taste and judgement. I tend to err on the side of eliminating comments, for several reasons. First, if the code is clear, and uses good type names and variable names, it should explain itself. Second, comments aren't checked by the compiler, so there is no guarantee they're right, especially after the code is modified. A misleading comment can be very confusing. Third, the issue of typography: comments clutter code. Rob Pike, "Notes on Programming in C"
  • 22.
    There is afamously bad comment style: i=i+1; /* Add one to i */ and there are worse ways to do it: /********************************** * * * Add one to i * * * **********************************/ i=i+1; Don't laugh now, wait until you see it in real life. Rob Pike, "Notes on Programming in C"
  • 23.
    A common fallacyis to assume authors of incomprehensible code will somehow be able to express themselves lucidly and clearly in comments. Kevlin Henney https://twitter.com/KevlinHenney/status/381021802941906944
  • 24.
  • 25.
  • 26.
  • 27.
    if (portfolioIdsByTraderId.get(trader.getId()) .containsKey(portfolio.getId())) { ... } Dan North,"Code in the Language of the Domain" 97 Things Every Programmer Should Know
  • 28.
    if (trader.canView(portfolio)) { ... } Dan North,"Code in the Language of the Domain" 97 Things Every Programmer Should Know
  • 30.
  • 32.
    Architecture represents the significantdesign decisions that shape a system, where significant is measured by cost of change. Grady Booch
  • 33.
  • 34.
    function leftpad (str,len, ch) { str = String(str); var i = -1; if (!ch && ch !== 0) ch = ' '; len = len - str.length; while (++i < len) { str = ch + str; } return str; }
  • 35.
    function leftpad(content, length,pad) { content = String(content) pad = String(pad || pad === 0 ? pad : ' ')[0] var left = Math.max(length - content.length, 0) return pad.repeat(left) + content }
  • 37.
    var cache =[ '', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' ]; function leftPad (str, len, ch) { // convert `str` to `string` str = str + ''; // `len` is the `pad`'s length now len = len - str.length; // doesn't need to pad if (len <= 0) return str; // `ch` defaults to `' '` if (!ch && ch !== 0) ch = ' '; // convert `ch` to `string` ch = ch + ''; // cache common use cases if (ch === ' ' && len < 10) return cache[len] + str; // `pad` starts with an empty string var pad = ''; // loop while (true) { // add `ch` to `pad` if `len` is odd if (len & 1) pad += ch; // divide `len` by 2, ditch the remainder len >>= 1; // "double" the `ch` so this operation count grows logarithmically on `len` // each time `ch` is "doubled", the `len` would need to be "doubled" too // similar to finding a value in binary search tree, hence O(log(n)) if (len) ch += ch; // `len` is 0, exit the loop else break; } // pad `str`! return pad + str; }
  • 38.
    I have yetto see any problem, however complicated, which, when you looked at it in the right way, did not become still more complicated. Anderson's Law
  • 39.
    truths = { "Paddingan empty string to a length of 0 results in an empty string": leftpad("", 0, "X") === "", "Padding a non-empty string to a shorter length results in the same string": leftpad("foobar", 3, "X") === "foobar", "Padding a non-empty string to a negative length results in the same string": leftpad("foobar", -3, "X") === "foobar", "Padding a non-empty string to its length results in the same string": leftpad("foobar", 6, "X") === "foobar", "Padding to a longer length with a single character fills to the left": leftpad("foobar", 8, "X") === "XXfoobar", "Padding to a longer length with surplus characters fills using only first": leftpad("foobar", 10, "XY") === "XXXXfoobar", "Padding to a longer length with an empty string fills with space": leftpad("foobar", 8, "") === " foobar", "Padding to a longer length with no specified fill fills with space": leftpad("foobar", 9) === " foobar", "Padding to a longer length with integer 0 fills with 0": leftpad("foobar", 7, 0) === "0foobar", "Padding to a longer length with single-digit integer fills with digit": leftpad("foobar", 10, 1) === "1111foobar", "Padding to a longer length with multiple-digit integer fills with first digit": leftpad("foobar", 10, 42) === "4444foobar", "Padding to a longer length with negative integer fills with -": leftpad("foobar", 8, -42) === "--foobar", "Padding a non-string uses string representation": leftpad(4.2, 5, 0) === "004.2", }
  • 40.
    truths = { "Paddingan empty string to a length of 0 results in an empty string": leftpad("", 0, "X") === "", "Padding a non-empty string to a shorter length results in the same string": leftpad("foobar", 3, "X") === "foobar", "Padding a non-empty string to a negative length results in the same string": leftpad("foobar", -3, "X") === "foobar", "Padding a non-empty string to its length results in the same string": leftpad("foobar", 6, "X") === "foobar", "Padding to a longer length with a single character fills to the left": leftpad("foobar", 8, "X") === "XXfoobar", "Padding to a longer length with surplus characters fills using only first": leftpad("foobar", 10, "XY") === "XXXXfoobar", "Padding to a longer length with an empty string fills with space": leftpad("foobar", 8, "") === " foobar", "Padding to a longer length with no specified fill fills with space": leftpad("foobar", 9) === " foobar", "Padding to a longer length with integer 0 fills with 0": leftpad("foobar", 7, 0) === "0foobar", "Padding to a longer length with single-digit integer fills with digit": leftpad("foobar", 10, 1) === "1111foobar", "Padding to a longer length with multiple-digit integer fills with first digit": leftpad("foobar", 10, 42) === "4444foobar", "Padding to a longer length with negative integer fills with -": leftpad("foobar", 8, -42) === "--foobar", "Padding a non-string uses string representation": leftpad(4.2, 5, 0) === "004.2", }
  • 41.
    truths = { "Paddingan empty string to a length of 0 results in an empty string": leftpad("", 0, "X") === "", "Padding a non-empty string to a shorter length results in the same string": leftpad("foobar", 3, "X") === "foobar", "Padding a non-empty string to a negative length results in the same string": leftpad("foobar", -3, "X") === "foobar", "Padding a non-empty string to its length results in the same string": leftpad("foobar", 6, "X") === "foobar", "Padding to a longer length with a single character fills to the left": leftpad("foobar", 8, "X") === "XXfoobar", "Padding to a longer length with surplus characters fills using only first": leftpad("foobar", 10, "XY") === "XXXXfoobar", "Padding to a longer length with an empty string fills with space": leftpad("foobar", 8, "") === " foobar", "Padding to a longer length with no specified fill fills with space": leftpad("foobar", 9) === " foobar", "Padding to a longer length with integer 0 fills with 0": leftpad("foobar", 7, 0) === "0foobar", "Padding to a longer length with single-digit integer fills with digit": leftpad("foobar", 10, 1) === "1111foobar", "Padding to a longer length with multiple-digit integer fills with first digit": leftpad("foobar", 10, 42) === "4444foobar", "Padding to a longer length with negative integer fills with -": leftpad("foobar", 8, -42) === "--foobar", "Padding a non-string uses string representation": leftpad(4.2, 5, 0) === "004.2", }
  • 42.
    toMap = object=> new Map(Object.entries(object)) format = (proposition, ok) => proposition.fontcolor(ok ? "green" : "red") + "<br>" present = truths => toMap(truths).forEach( (ok, proposition) => write(format(proposition, ok))) present(truths)
  • 43.
    Padding an emptystring to a length of 0 results in an empty string Padding a non-empty string to a shorter length results in the same string Padding a non-empty string to a negative length results in the same string Padding a non-empty string to its length results in the same string Padding to a longer length with a single character fills to the left Padding to a longer length with surplus characters fills using only first Padding to a longer length with an empty string fills with space Padding to a longer length with no specified fill fills with space Padding to a longer length with integer 0 fills with 0 Padding to a longer length with single-digit integer fills with digit Padding to a longer length with multiple-digit integer fills with first digit Padding to a longer length with negative integer fills with - Padding a non-string uses string representation
  • 44.
    Padding an emptystring to a length of 0 results in an empty string Padding a non-empty string to a shorter length results in the same string Padding a non-empty string to a negative length results in the same string Padding a non-empty string to its length results in the same string Padding to a longer length with a single character fills to the left Padding to a longer length with surplus characters fills using only first Padding to a longer length with an empty string fills with space Padding to a longer length with no specified fill fills with space Padding to a longer length with integer 0 fills with 0 Padding to a longer length with single-digit integer fills with digit Padding to a longer length with multiple-digit integer fills with first digit Padding to a longer length with negative integer fills with - Padding a non-string uses string representation
  • 46.
    For every activitythere is a certain appropriate scale.
  • 47.
    The Facebook iOSapp has over 18,000 Objective-C classes, and in a single week 429 people contributing to it. Facebook's code quality problem Graham King http://www.darkcoding.net/software/facebooks-code-quality-problem/
  • 48.
    Your customers do notbuy your software by the line. David Evans
  • 49.
    Quote from KevlinHenney Graphic by Sebastian Hermida http://sbastn.com/2009/06/typing-is-not-the-bottleneck/