Useable, Grammatical and Readable code

Useable, Grammatical and Readable code

Presented at Async 06/12/2018
https://asyncjs.com/readable-code/

As software developers, we all know that we need to make our code more readable - but how exactly? There is not a lot of literature out there on the subject, and what there is can be very dogmatic and contradictory.

In this talk, Daniel van Berzon attempts to tackle the issue by learning from the worlds of Linguistics and UX, which have successfully solved similar problems. As part of the talk Daniel will present the initial findings from his ongoing readability experiment at http://howreadable.com/

1a93f6606abdcf0ec6a850df9e4b830d?s=128

Daniel van Berzon

December 06, 2018
Tweet

Transcript

  1. Useable, Grammatical & Readable Code Daniel van Berzon @ocastahq ocasta.com

    @dvberzon info@howreadable.com
  2. Grammar Daniel van Berzon @ocastahq ocasta.com @dvberzon info@howreadable.com

  3. “Rachel and me went to the cinema” “Rachel and I

    went to the cinema” A B C
  4. Usability Daniel van Berzon @ocastahq ocasta.com @dvberzon info@howreadable.com

  5. A B C

  6. Readable Code Daniel van Berzon @ocastahq ocasta.com @dvberzon info@howreadable.com

  7. A B C var person; if(age > 18) { person

    = "adult"; } else { person = "child"; } var person = age > 18 ? "adult" : "child";
  8. Daniel van Berzon @ocastahq ocasta.com @dvberzon daniel@vanberzon.com Usability Grammar Readable

    Code Spanish Dutch Brexit Photography Magic Signing Guilbert & Sullivan Footy Television Flamenco Film Musicals
  9. Daniel van Berzon @ocastahq ocasta.com @dvberzon daniel@vanberzon.com Usability Grammar Readable

    Code
  10. Daniel van Berzon @ocastahq ocasta.com @dvberzon daniel@vanberzon.com Usability Grammar Readable

    Code
  11. howreadable.com

  12. Readable Code

  13. Writing code On your own For the computer Student

  14. Reading code Collaborating For developers Professional Reading : Writing 10

    : 1 - Robert C Martin
  15. Student Professional Cool Clever Efficient Succinct Exciting Clear Simple Intuitive

    Structured Boring write_code => => read_code
  16. Code that is easy to read … is hard to

    write • Too many options • Spoilers • Other people const a = 0; a b c d e f g h i
  17. const columns = [ {id: "date", name: "Date"}, {id: "recipient",

    name: "Recipient"}, {id: "location", name: "Recipient Location"}, {id: "sender", name: "Sender"}, {id: "message", name: "Message"} ]; Requirement that only admins should see the “Recipient” and “Recipient Location” columns. Introduce a boolean isAdmin
  18. const columns = [ {id: "date", name: "Date"}, {id: "recipient",

    name: "Recipient"}, {id: "location", name: "Recipient Location"}, {id: "sender", name: "Sender"}, {id: "message", name: "Message"} ]; const adminColumnIds = ['recipient','location']; // filter out recipient columns const visibleColumns = columns.filter((column) => { return isAdmin || !adminColumnIds.includes(column.id); });
  19. const columns = [ {id: "date", name: "Date"}, {id: "recipient",

    name: "Recipient", admin: true}, {id: "location", name: "Recipient Location", admin: true}, {id: "sender", name: "Sender"}, {id: "message", name: "Message"} ]; // filter out recipient columns const visibleColumns = columns.filter((column) => { return isAdmin || !column.admin; });
  20. const columns = []; columns.push({id: "date", name: "Date"}); if(isAdmin){ columns.push({id:

    "recipient", name: "Recipient"}); columns.push({id: "location", name: "Recipient Location"}); } columns.push({id: "sender", name: "Sender"}); columns.push({id: "message", name: "Message"});
  21. const date = {id:"date", name:"Date"}; const recipient = {id:"recipient", name:"Recipient"};

    const location = {id:"location", name:"Recipient Location"}; const sender = {id:"sender", name:"Sender"}; const message = {id:"message", name:"Message"}; const columns = isAdmin ? [ date, recipient, location, sender, message ] : [ date, sender, message ]; None of this effort is billable
  22. Readable Code = Easy to understand = Clear in intent

    = Logical = Easy to maintain / change = Unsurprising - Principal of ”Least Astonishment”
  23. function postcodeValid(params){ return strPresent(params.postcode); } function validateParams(params){ return firstNameValid(params) &&

    lastNameValid(params) && emailValid(params) && postcodeValid(params); }
  24. function postcodeValid(params){ return strPresent(params.postcode); } function validateParams(params){ return firstNameValid(params) &&

    lastNameValid(params) && emailValid(params) && postcodeValid(params); } Whitespace
  25. function postcodeValid(params){ return strPresent(params.postcode); } function validateParams(params){ return firstNameValid(params) &&

    lastNameValid(params) && emailValid(params) && postcodeValid(params); } Whitespace Indentation
  26. function postcodeValid(params){ return strPresent(params.postcode); } function validateParams(params){ return firstNameValid(params) &&

    lastNameValid(params) && emailValid(params) && postcodeValid(params); } Whitespace Indentation Breaking long lines
  27. Legible code ≠ Readable code function postcodeValid(params){ return strPresent(params.postcode); }

    function validateParams(params){ return firstNameValid(params) && lastNameValid(params) && emailValid(params) && postcodeValid(params); } Whitespace Indentation Breaking long lines
  28. Readability Syntax Naming Approach Organisation Consistency Structure

  29. Code readability describes how the structure of code can help

    a developer understand and control it.
  30. Usability

  31. ? Intuitive

  32. Usability Visual form Layout Feedback Familiarity Consistency Simplicity Structure

  33. Usability describes how the structure of an interface can help

    a user understand and control it.
  34. Code readability describes how the structure of code can help

    a developer understand and control it. Usability describes how the structure of an interface can help a user understand and control it.
  35. Developers = Users (interface) Readability = Usability Codebase = Interface

    (business logic)
  36. Grammar

  37. able to correctly use English than we are aware of.

    There are less people who are X ^ correctly X fewer X of whom ^ Mistakes
  38. Grammar Grammar conveys meaning • Word forms (Morphology) • Sentence

    structure (Syntax) • Meaning (Semantics)
  39. Gurf booged spink fooply

  40. Gurf booged spink fooply Gained information from Grammar -ed for

    past tense English word order: subject — verb — object (SVO) -ly for adverbs
  41. Gurf booged spink fooply Grammar helps us Understand the sentence

  42. Grammar describes how the structure of language can help a

    speaker understand and control it.
  43. Grammar describes how the structure of language can help a

    speaker understand and control it. code Code readability developer
  44. Grammar describes how the structure of language can help a

    speaker understand and control it. Usability user an interface
  45. Usability Grammar Readable Code

  46. Usability Grammar Readable Code

  47. Grammar

  48. A B C “Rachel and me went to the cinema”

    “Rachel and I went to the cinema”
  49. B: Rachel and I went to the cinema 2 pronouns

    for referring to oneself “I” as subject: “I went to the cinema” “Me” as object: "Rachel noticed me” “Rachel” and “I” are both subjects ∴ “Rachel and I” is correct Q.E.D. !!
  50. 1. Opinion 2. Size 3. Age 4. Shape 5. Colour

    6. Origin 7. Material 8. Purpose English has complex grammar rules … Adjective order Green little men Little green men lovely little old long green french silver serving spoon
  51. No one was ever taught this rule in school! Little

    green men Rachel and me went to the cinema Between you and I All debts are cleared between you and I Merchant of Venice Act 3 scene 2
  52. ? Little green men Rachel and I

  53. Noam Chomsky Universal Grammar Humans are born with an innate

    understanding of grammar. Prescriptive grammar Descriptive grammar
  54. Prescriptive Descriptive Arbitrary grammar rules that prescribe the way people

    should speak Vs. Innate grammar rules that describe the way people speak - Boldly to go - From whom is that? - Rachel and I went to the cinema - He wanted the book - Bob eats pizza (SVO) - Little green men
  55. Descriptive grammar Rachel and me and Rachel and I =

    Noun phrases When people speak naturally... The grammar of a sentence acts on a Noun Phrase as a whole, not on its internal parts. “Rachel and me are tall” “Me are tall” or “Me went to the cinema” ∴ Both fine! Q.E.D. !!
  56. ? Grammar Readable Code

  57. Some literature on readability Learning code readability Psychology of code

    readability Google JavaScript Style Guide Make your code easier to read with Functional Programming Idiomatic.js
  58. Feels quite prescriptive • Talk of idiom • Opinions presented

    as rules • Phrases like: Prefer…, Avoid…, Recommended • No references or links to research
  59. Prescriptive Descriptive

  60. No native speakers of: JavaScript Python C / C++ Ruby

    Java Baṣa Jawa Universal grammar applies to native language speakers Flaw in the metaphor
  61. Useful takeaways: • Accepted rules can be arbitrary • If

    people keep making a mistake
 ➞ It might not be a mistake • Base advice on empirical evidence • Don’t tell devs how to code
 ➞ Learn from how they code
  62. Over half of all developers are junior < 5 yrs

    - Robert C Martin
  63. Over half of all developers are junior < 5 yrs

    - Robert C Martin
  64. Over half of all developers are junior < 5 yrs

    - Robert C Martin
  65. Usability

  66. A B C

  67. Answer It depends! Radio buttons Dropdown See all the options

    One click Rich text options Less space Current selection clear Better on mobile
  68. Dropdown ✔ Default option is the recommended one Many options

    with natural order Selected option forms part of a sentence
  69. Radio Buttons ✔ Small number of options User should compare

    options Add context information
  70. Usability depends on context Context is different in each case

    Very difficult to formulate rules Leads to frustration Use of four letter words ! "
  71. Test

  72. Best way to work out if an interface is usable

    Easiest method is the Survey But → Jam experiment! → Try it out on users
  73. Psychologists in 2000 set up a supermarket display with 6

    24 or Varieties of jam, on alternating days But, Bought more jam with fewer options £££ Shoppers preferred having more options
  74. Jam experiment shows that Opinion ≠ Behaviour Surveys measure opinion

    Better to directly test behaviour Less choice More choice
  75. Types of user behaviour test: • A - B testing

    • User observation • Automated screen recording Directly measure user experience
  76. ? Usability Readable Code

  77. Best way to work out if code is Readable Don’t

    ask developer’s opinion → try it out on developers Directly measure behaviour
  78. Objective metric for readability? Ability to predict output Time to

    comprehension
  79. Readable Code

  80. A B C var person; if(age > 18) { person

    = "adult"; } else { person = "child"; } var person = age > 18 ? "adult" : "child";
  81. Ternary Operator vs If Else Look for a descriptive readability

    rule Testing the code on developers Directly measure ability to predict output and time to comprehension
  82. howreadable.com

  83. howreadable.com Measure code readability Developers shown a series of code

    samples Time how long they take to read the code After reading each sample asked: • Predict the result of the code • Rate how readable they found it • Add any comments → Proof of concept experiment
  84. Ternary a ? b : c; if(a){b}… Method

  85. Ternary a ? b : c; if(a){b}… Method

  86. Ternary a ? b : c; if(a){b}… 60% 40% Method

  87. • Simple - correct response in reasonable time • A

    predictable result • Self contained - predictable from the visible code • Any calculation / logic possible in your head • Avoid tricks / hidden bugs Code samples a ? b : c;
  88. function getResult(value) { return value > 4 ? 10 :

    20; } var result = getResult(3); function getResult(value) { if(value > 4){ return 10; } else { return 20; } } var result = getResult(3); Participant asked to predict value of `result` Ternary operator vs if else statement
  89. • Available in Js, Ruby and Python • Experiments presented

    in a random order • Equal number participants for each sample - Block randomisation howreadable.com • Other data captured: • Years programming • Main language • Browser agent / Display size ES5
  90. Participation 247 participants 38 50 159 Language choice Elixir Go

    C++ Typescript Other PHP Java C# Python Ruby JS Main Language 10 + 6 - 10 5 4 3 2 1 < 1 Years programming
  91. 9 Experiments Syntax • Ternary operator vs if else •

    Nested Ternary vs if else • arr.reduce vs for loop • switch case statements Conditionals • Order of if else • if else vs early return Naming Comments Abstraction
  92. Ternary vs if else 94.4% 98.4% 27.1s 23.5s 3.7 3.4

    Statistical analysis
  93. Ternary vs if else 0 2.5 5 7.5 10 1

    3 6 9 12 15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120123 126 129 132 135 138 141144 147 150 153 156 159 Ternary If else Seconds % of results Ternary if else Students T-Test P value ≤ 0.05 P = 0.44
  94. arr.reduce vs for loop var values = [1,2,3,4]; var result

    = values.reduce(function(sum, val){ return sum + val; }); var values = [1,2,3,4]; var result = 0; for(var i = 0; i < values.length; i++){ result += values[i]; }
  95. arr.reduce vs for loop 98.4% 92.4% 43.8s 29.1s 3.5 3.4

    50% slower P = 0.002
  96. Syntax • Ternary operator vs if else • Nested Ternary

    vs if else • arr.reduce vs for loop • switch case statements Conditionals • Order of if else • if else vs early return Naming Comments Abstraction 9 Experiments
  97. if(showPanel()){ $('panel').show() } Naming showPanel() There are only two hard

    things in Computer Science: cache invalidation and naming things. -- Phil Karlton
  98. action.completed() Naming • Set completed flag to true • Has

    the action been completed? • List of completed actions • Run procedures to complete the action • Run some post completion procedures
  99. array.filter(fn) Naming Residue Filtrate

  100. function processStr(str){ return str.toLowerCase().split('').sort().join('').trim(); } function isAnagramOf(str, testStr){ return processStr(str)

    == processStr(testStr); } var result = isAnagramOf("devil", "lived"); function sortAlphabetically(str){ return str.toLowerCase().split('').sort().join('').trim(); } function isAnagramOf(str, testStr){ return sortAlphabetically(str) == sortAlphabetically(testStr); } var result = isAnagramOf("devil", "lived"); Generic vs Specific P = 0.2
  101. Comments If you have to write a comment, your code

    isn't readable enough. Never! Always! 1 2 3 4 5 6 6 4 3 3
  102. Comments Your ideal should be: our code does not need

    comments. Practically tell a story with your comments
  103. No comment function doRangesOverlap(range1, range2) { return range1.end >= range2.start

    && range1.start <= range2.end; } var scores = { start: 1, end: 7 }; var desired = { start: 5, end: 9 }; var result = doRangesOverlap(scores, desired);
  104. No comment vs What comment // for any two ranges,

    do they overlap? function doRangesOverlap(range1, range2) { // does one start before the other ends // and end before the other starts return range1.end >= range2.start && range1.start <= range2.end; } // range of scores var scores = { start: 1, end: 7 }; // the desired range var desired = { start: 5, end: 9 }; // do the scores overlap with the desired range var result = doRangesOverlap(scores, desired); // for any two ranges, do they overlap?
  105. No comment vs What comment vs Why comment function doRangesOverlap(range1,

    range2) { // Two ranges overlap if one starts before the other ends // and ends before the other starts return range1.end >= range2.start && range1.start <= range2.end; } var scores = { start: 1, end: 7 }; var desired = { start: 5, end: 9 }; var result = doRangesOverlap(scores, desired); // Two ranges overlap if one starts before the other ends // and ends before the other starts
  106. No comment vs What comment vs Why comment vs Bad

    comment function doRangesOverlap(range1, range2) { // Two ranges overlap if one starts before the other starts // or ends before the other ends return range1.end >= range2.start && range1.start <= range2.end; } var scores = { start: 1, end: 7 }; var desired = { start: 5, end: 9 }; var result = doRangesOverlap(scores, desired); // Two ranges overlap if one starts before the other starts // and ends before the other ends
  107. No comment vs What comment vs Why comment vs Bad

    comment No difference More Readable Less readable
  108. No comment vs What comment vs Why comment vs Bad

    comment P = 0.34
  109. Why the high P values? • No effect to measure

    (null hypothesis) • The effect is small and the test too blunt • Sample size too low • There's a problem with the methodology... > 90%
  110. 0 2.5 5 7.5 10 1 3 6 9 12

    15 18 21 24 27 30 33 36 39 42 45 48 51 54 57 60 63 66 69 72 75 78 81 84 87 90 93 96 99 102 105 108 111 114 117 120123 126 129 132 135 138 141144 147 150 153 156 159 Ternary If else Seconds % of results Ternary if else Time to comprehension Why the long tail?
  111. I am not keen on the use of abbreviations as

    they mk cd hrd 2 rd. I would ask for a complete rewrite on a code review. Time to comprehension
  112. I am not keen on the use of abbreviations as

    they mk cd hrd 2 rd. I would ask for a complete rewrite on a code review. If else should be used over ternary when possible Ternary operator here will be better Shadowing the variable name result wasn't a great start... the variable name is misnamed. It's not strictly a name but rather a salutation Time to comprehension
  113. I am not keen on the use of abbreviations as

    they mk cd hrd 2 rd. I would ask for a complete rewrite on a code review. If else should be used over ternary when possible Ternary operator here will be better Shadowing the variable name result wasn't a great start... the variable name is misnamed. It's not strictly a name but rather a salutation String.prototype.charAt would be better in every way and simpler. In addition, this does nothing for i18n support. Time to comprehension
  114. I am not keen on the use of abbreviations as

    they mk cd hrd 2 rd. I would ask for a complete rewrite on a code review. If else should be used over ternary when possible Ternary operator here will be better Shadowing the variable name result wasn't a great start... the variable name is misnamed. It's not strictly a name but rather a salutation String.prototype.charAt would be better in every way and simpler. In addition, this does nothing for i18n support. Your textbook bad code If you write this you are bad and you should feel bad! Time to comprehension
  115. Reading code ≠ Reviewing code Possible some participants taking longer

    to read the code than necessary to understand it Finite ∞ Time to comprehension
  116. None
  117. • Show a timer • Remove comment box • Better

    instructions / signposting • Maybe fixed time? Time to comprehension
  118. New experiments • Code golf • Booleans: (!a && !b)

    vs (!(a || b)) • Chaining methods vs intermediate vars • Consistency Writing code in as few lines as possible
  119. Another approach? • Linguists research by searching Language corpus https://books.google.com/ngrams

    ?
  120. The future... • More statistical analysis of existing results •

    Increase sample size (marketing) • Offer more languages • Harder, more realistic tests • Get help, and funding!
  121. In the meantime? • Avoid array.reduce • Take advice of

    readability literature • Question prescriptive rules • If in doubt - try it out (on a junior!) • Help me! info@howreadable.com
  122. Thank you Daniel van Berzon @ocastahq ocasta.com @dvberzon info@howreadable.com