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. A B C var person; if(age > 18) { person

    = "adult"; } else { person = "child"; } var person = age > 18 ? "adult" : "child";
  2. 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
  3. 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
  4. 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
  5. 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); });
  6. 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; });
  7. 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"});
  8. 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
  9. Readable Code = Easy to understand = Clear in intent

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

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

    lastNameValid(params) && emailValid(params) && postcodeValid(params); } Whitespace Indentation Breaking long lines
  12. 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
  13. Code readability describes how the structure of code can help

    a developer understand and control it.
  14. 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.
  15. able to correctly use English than we are aware of.

    There are less people who are X ^ correctly X fewer X of whom ^ Mistakes
  16. Gurf booged spink fooply Gained information from Grammar -ed for

    past tense English word order: subject — verb — object (SVO) -ly for adverbs
  17. Grammar describes how the structure of language can help a

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

    speaker understand and control it. Usability user an interface
  19. A B C “Rachel and me went to the cinema”

    “Rachel and I went to the cinema”
  20. 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. !!
  21. 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
  22. 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
  23. Noam Chomsky Universal Grammar Humans are born with an innate

    understanding of grammar. Prescriptive grammar Descriptive grammar
  24. 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
  25. 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. !!
  26. 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
  27. Feels quite prescriptive • Talk of idiom • Opinions presented

    as rules • Phrases like: Prefer…, Avoid…, Recommended • No references or links to research
  28. No native speakers of: JavaScript Python C / C++ Ruby

    Java Baṣa Jawa Universal grammar applies to native language speakers Flaw in the metaphor
  29. 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
  30. Answer It depends! Radio buttons Dropdown See all the options

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

    with natural order Selected option forms part of a sentence
  32. Usability depends on context Context is different in each case

    Very difficult to formulate rules Leads to frustration Use of four letter words ! "
  33. Best way to work out if an interface is usable

    Easiest method is the Survey But → Jam experiment! → Try it out on users
  34. 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
  35. Jam experiment shows that Opinion ≠ Behaviour Surveys measure opinion

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

    • User observation • Automated screen recording Directly measure user experience
  37. Best way to work out if code is Readable Don’t

    ask developer’s opinion → try it out on developers Directly measure behaviour
  38. A B C var person; if(age > 18) { person

    = "adult"; } else { person = "child"; } var person = age > 18 ? "adult" : "child";
  39. 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
  40. 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
  41. • 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;
  42. 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
  43. • 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
  44. 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
  45. 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
  46. 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
  47. 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]; }
  48. 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
  49. if(showPanel()){ $('panel').show() } Naming showPanel() There are only two hard

    things in Computer Science: cache invalidation and naming things. -- Phil Karlton
  50. 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
  51. 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
  52. 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
  53. Comments Your ideal should be: our code does not need

    comments. Practically tell a story with your comments
  54. 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);
  55. 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?
  56. 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
  57. 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
  58. No comment vs What comment vs Why comment vs Bad

    comment No difference More Readable Less readable
  59. 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%
  60. 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?
  61. 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
  62. 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
  63. 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
  64. 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
  65. Reading code ≠ Reviewing code Possible some participants taking longer

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

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

    vs (!(a || b)) • Chaining methods vs intermediate vars • Consistency Writing code in as few lines as possible
  68. The future... • More statistical analysis of existing results •

    Increase sample size (marketing) • Offer more languages • Harder, more realistic tests • Get help, and funding!
  69. 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]