Upgrade to Pro — share decks privately, control downloads, hide ads and more …

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/

Daniel van Berzon

December 06, 2018
Tweet

More Decks by Daniel van Berzon

Other Decks in Programming

Transcript

  1. Useable,
    Grammatical &
    Readable Code
    Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]

    View Slide

  2. Grammar
    Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]

    View Slide

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

    View Slide

  4. Usability
    Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]

    View Slide

  5. A B
    C

    View Slide

  6. Readable Code
    Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]

    View Slide

  7. A
    B
    C
    var person;
    if(age > 18) {
    person = "adult";
    } else {
    person = "child";
    }
    var person = age > 18 ? "adult" : "child";

    View Slide

  8. Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]
    Usability Grammar
    Readable Code
    Spanish
    Dutch
    Brexit
    Photography
    Magic
    Signing
    Guilbert & Sullivan
    Footy
    Television
    Flamenco
    Film
    Musicals

    View Slide

  9. Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]
    Usability Grammar
    Readable Code

    View Slide

  10. Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]
    Usability Grammar
    Readable Code

    View Slide

  11. howreadable.com

    View Slide

  12. Readable Code

    View Slide

  13. Writing code
    On your own
    For the computer
    Student

    View Slide

  14. Reading code
    Collaborating
    For developers
    Professional
    Reading : Writing
    10 : 1
    - Robert C Martin

    View Slide

  15. Student Professional
    Cool
    Clever
    Efficient
    Succinct
    Exciting
    Clear
    Simple
    Intuitive
    Structured
    Boring
    write_code => => read_code

    View Slide

  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

    View Slide

  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

    View Slide

  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);
    });

    View Slide

  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;
    });

    View Slide

  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"});

    View Slide

  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

    View Slide

  22. Readable Code = Easy to understand
    = Clear in intent
    = Logical
    = Easy to maintain / change
    = Unsurprising
    - Principal of ”Least Astonishment”

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  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

    View Slide

  28. Readability
    Syntax
    Naming
    Approach
    Organisation
    Consistency
    Structure

    View Slide

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

    View Slide

  30. Usability

    View Slide

  31. ?
    Intuitive

    View Slide

  32. Usability
    Visual form
    Layout
    Feedback
    Familiarity
    Consistency
    Simplicity
    Structure

    View Slide

  33. Usability describes how
    the structure of an
    interface can help a user
    understand and control it.

    View Slide

  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.

    View Slide

  35. Developers = Users (interface)
    Readability = Usability
    Codebase = Interface (business logic)

    View Slide

  36. Grammar

    View Slide

  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

    View Slide

  38. Grammar
    Grammar conveys meaning
    • Word forms (Morphology)

    • Sentence structure (Syntax)

    • Meaning (Semantics)

    View Slide

  39. Gurf booged spink fooply

    View Slide

  40. Gurf booged spink fooply
    Gained information from Grammar
    -ed for past tense
    English word order:
    subject — verb — object (SVO)
    -ly for adverbs

    View Slide

  41. Gurf booged spink fooply
    Grammar helps us
    Understand the
    sentence

    View Slide

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

    View Slide

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

    View Slide

  44. Grammar describes how
    the structure of language
    can help a speaker
    understand and control it.
    Usability
    user
    an interface

    View Slide

  45. Usability Grammar
    Readable Code

    View Slide

  46. Usability Grammar
    Readable Code

    View Slide

  47. Grammar

    View Slide

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

    View Slide

  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. !!

    View Slide

  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

    View Slide

  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

    View Slide

  52. ?
    Little green men Rachel and I

    View Slide

  53. Noam Chomsky
    Universal Grammar
    Humans are born with an
    innate understanding of
    grammar.
    Prescriptive grammar
    Descriptive grammar

    View Slide

  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

    View Slide

  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. !!

    View Slide

  56. ? Grammar
    Readable Code

    View Slide

  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

    View Slide

  58. Feels quite prescriptive
    • Talk of idiom
    • Opinions presented as rules
    • Phrases like: Prefer…, Avoid…, Recommended
    • No references or links to research

    View Slide

  59. Prescriptive
    Descriptive

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  65. Usability

    View Slide

  66. A B
    C

    View Slide

  67. Answer It depends!
    Radio buttons Dropdown
    See all the options
    One click
    Rich text options
    Less space
    Current selection clear
    Better on mobile

    View Slide

  68. Dropdown ✔
    Default option is the
    recommended one
    Many options with
    natural order
    Selected option forms
    part of a sentence

    View Slide

  69. Radio Buttons ✔
    Small number
    of options
    User should
    compare options
    Add context
    information

    View Slide

  70. Usability depends on context
    Context is different in each case
    Very difficult to formulate rules
    Leads to frustration
    Use of four letter words
    !
    "

    View Slide

  71. Test

    View Slide

  72. Best way to work out if an interface is usable
    Easiest method is the Survey
    But → Jam experiment!
    → Try it out on users

    View Slide

  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

    View Slide

  74. Jam experiment shows that
    Opinion ≠ Behaviour
    Surveys measure opinion
    Better to directly test behaviour
    Less choice
    More choice

    View Slide

  75. Types of user behaviour test:
    • A - B testing
    • User observation
    • Automated screen recording
    Directly measure user experience

    View Slide

  76. ?
    Usability
    Readable Code

    View Slide

  77. Best way to work out if code is Readable
    Don’t ask developer’s opinion
    → try it out on developers
    Directly measure behaviour

    View Slide

  78. Objective metric for readability?
    Ability to predict output
    Time to comprehension

    View Slide

  79. Readable Code

    View Slide

  80. A
    B
    C
    var person;
    if(age > 18) {
    person = "adult";
    } else {
    person = "child";
    }
    var person = age > 18 ? "adult" : "child";

    View Slide

  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

    View Slide

  82. howreadable.com

    View Slide

  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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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;

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  92. Ternary vs if else
    94.4% 98.4%
    27.1s 23.5s
    3.7 3.4
    Statistical analysis

    View Slide

  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

    View Slide

  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];
    }

    View Slide

  95. arr.reduce vs for loop
    98.4% 92.4%
    43.8s 29.1s
    3.5 3.4
    50% slower
    P = 0.002

    View Slide

  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

    View Slide

  97. if(showPanel()){
    $('panel').show()
    }
    Naming
    showPanel()
    There are only two hard things in Computer Science:
    cache invalidation and naming things.
    -- Phil Karlton

    View Slide

  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

    View Slide

  99. array.filter(fn)
    Naming
    Residue
    Filtrate

    View Slide

  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

    View Slide

  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

    View Slide

  102. Comments
    Your ideal should be: our code does not
    need comments.
    Practically tell a story with your comments

    View Slide

  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);

    View Slide

  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?

    View Slide

  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

    View Slide

  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

    View Slide

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

    View Slide

  108. No comment
    vs
    What comment
    vs
    Why comment
    vs
    Bad comment
    P = 0.34

    View Slide

  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%

    View Slide

  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?

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  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

    View Slide

  115. Reading code ≠ Reviewing code
    Possible some participants taking longer to read
    the code than necessary to understand it
    Finite

    Time to comprehension

    View Slide

  116. View Slide

  117. • Show a timer
    • Remove comment box
    • Better instructions / signposting
    • Maybe fixed time?
    Time to comprehension

    View Slide

  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

    View Slide

  119. Another approach?
    • Linguists research by searching Language corpus
    https://books.google.com/ngrams
    ?

    View Slide

  120. The future...
    • More statistical analysis of existing results
    • Increase sample size (marketing)
    • Offer more languages
    • Harder, more realistic tests
    • Get help, and funding!

    View Slide

  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! [email protected]

    View Slide

  122. Thank you
    Daniel van Berzon
    @ocastahq ocasta.com
    @dvberzon [email protected]

    View Slide