Optimizing For Readability

Optimizing For Readability

What do software engineers do all day long? Write code? Of course! But what about reading code, about understanding what’s happening? Aren’t we doing that even more? I believe we do. Because of that code should be as readable as possible! But what does that even mean? How do we achieve readable code? This talk will introduce you to coding principles and techniques that will help you write more readable code, be more productive and have more fun!

8480daec7137f28565bc2d2e666b915a?s=128

Tobias Pfeiffer

November 03, 2015
Tweet

Transcript

  1. None
  2. We write code

  3. Isn't it more about reading?

  4. Written once – read many times

  5. „(…) when you program, you have to think about how

    someone will read your code, not just how a computer will interpret it.“ Kent Beck
  6. „Any fool can write code that a computer can understand.

    Good programmers write code that humans can understand.“ Martin Fowler
  7. Not about architecture

  8. Methods & Code

  9. Nurturing a code base

  10. Extra effort

  11. Save time!

  12. Your code base?

  13. None
  14. It's about joy!

  15. Optimizing for Readability Tobias Pfeiffer @PragTob pragtob.info

  16. Crazy?

  17. Methods & Code

  18. None
  19. Keep It Simple Stupid

  20. Are comments a smell?

  21. Comments are an excuse of the code that it could

    not be clearer.
  22. Outdated comments are the worst

  23. The why not the what

  24. def paint_control(event) # some painting code rescue => e #

    Really important to rescue here. Failures that escape this method # cause odd-ball hangs with no backtraces. See #559 for an example. # puts "SWALLOWED PAINT EXCEPTION ON #{@obj} - go take care of it: " + e.to_s puts 'Unfortunately we have to swallow it because it causes odd failures :(' end
  25. Also known as the smell that tries to make other

    smells seem ok
  26. # do one thing ... ... ... ... ... #

    do another thing ... ... ... ... # do something more ... ...
  27. # do one thing ... ... ... ... ... #

    do another thing ... ... ... ... # do something more ... ...
  28. # do one thing ... ... ... ... ... #

    do another thing ... ... ... ... # do something more ... ... Cocepts
  29. Method too long

  30. Short Methods

  31. <= 8 LOC

  32. Extract Methods

  33. do_one_thing do_another_thing do_something_more Cocepts

  34. # context, outlet, times, time per step, state, data def

    pattern(c, o, t, l, s, d) # ... end
  35. Incomprehensible names

  36. # context, outlet, times, time per step, state, data def

    pattern(c, o, t, l, s, d) # ... end
  37. # context, outlet, times, time per step, state, data def

    pattern(c, o, t, l, s, d) # ... end
  38. Explanatory names

  39. Naming is hard

  40. def pattern(context, outlet, time, time_per_step, state, data) # ... end

  41. Argument order dependency

  42. Try to keep it to 2 parameters

  43. Example

  44. # allowed to drink? if customer.age >= 18 say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{['cola', 'mate'].sample}?" end
  45. # allowed to drink? if customer.age >= 18 say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{['cola', 'mate'].sample}?" end
  46. No magic numbers

  47. NON_ALCOHOLIC_DRINKS = ['cola', 'mate'] MIN_DRINKING_AGE = 18

  48. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  49. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  50. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  51. Query method

  52. Intention revealing method

  53. # ... text.color = red # ...

  54. # ... text.color = red # ...

  55. # ... highlight(text) # ...

  56. def highlight(text) text.color = red end

  57. def highlight(text) text.color = red text.underline = true update_highlights end

  58. # ... text.color = red text.underline = true update_highlights #

    ...
  59. # ... highlight(text) # ...

  60. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  61. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  62. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  63. # allowed to drink? if customer.age >= MIN_DRINKING_AGE say 'Okay'

    drink = prepare_drink requested_drink say 'here you go' hand_drink_over drink, customer else say 'I am sorry you are not legally allowed rather to drink here' say "Would you rather have a #{NON_ALCOHOLIC_DRINKS.sample}?" end
  64. if allowed_to_drink_alcohol?(customer) serve_drink requested_drink, customer else propose_non_alcoholic_drink end

  65. „If you have a good name for a method you

    don't need to look at the body.“ Martin Fowler
  66. „The easiest code to understand is the code you don't

    have to read at all.“ Tom Stuart (Berlin)
  67. prepare_drink requested_drink price = requested_drink.price check = Check.new check.add_price price

    say 'That whill be ' + check.total
  68. prepare_drink requested_drink price = requested_drink.price check = Check.new check.add_price price

    say 'That whill be ' + check.total
  69. prepare_drink requested_drink price = requested_drink.price check = Check.new check.add_price price

    say 'That whill be ' + check.total
  70. Same level of abstraction in a method

  71. prepare_drink requested_drink prepare_check requested_drink

  72. Nice code formatting

  73. @left ||= 0 @top ||= 0 @width ||= 1.0 @height

    ||= 0
  74. double character: 'something weird', stateMask: CTRL | modifier, KeyCode: character.downcase.ord

  75. 80 character width limit

  76. 80 character width limit

  77. 80 character width limit

  78. 80 character width limit

  79. 80 character width limit

  80. Identify concepts

  81. One language

  82. Don't Repeat Yourself

  83. Nurturing a code base

  84. Code bases detoriate

  85. No broken windows!

  86. None
  87. None
  88. Magical time?

  89. The boyscout rule

  90. None
  91. Opportunistic Refactoring

  92. TDD

  93. 80% Code Coverage

  94. 20% is never executed

  95. Code Review Culture

  96. „Brown Bag“ lunches

  97. Pair Programming

  98. Reaping the benefits

  99. Know when to break the rules

  100. If you still like your code from two years ago,

    then you are not learning fast enough.
  101. Enjoy writing readable code! Tobias Pfeiffer @PragTob pragtob.info

  102. Sources • The Pragmatic Programmer • Smalltalk Best Practice Patterns

    • Clean Code • Practical Object Oriented Design in Ruby
  103. Photo Credit • http://officeimg.vo.msecnd.net/en-us/images/MP900439313.jpg • http://officeimg.vo.msecnd.net/en-us/images/MC900021328.wmf • http://www.osnews.com/story/19266/WTFs_m • (CC

    BY-SA 2.0) – http://www.flickr.com/photos/83633410@N07/7658272558/in/photostream/ – http://www.flickr.com/photos/83633410@N07/7658165122/ – https://www.flickr.com/photos/93425126@N00/313056379/ • (CC BY-NC-ND 2.0) – http://www.flickr.com/photos/andih/86577529/ – http://www.flickr.com/photos/12584908@N08/3293117576/ – http://www.flickr.com/photos/jasonlparks/4525188865/ – http://www.flickr.com/photos/20714221@N04/2293045156/ – https://www.flickr.com/photos/eyewash/2603717864/ – https://www.flickr.com/photos/stevie_gill/3950697539/ – https://www.flickr.com/photos/randar/15787696685/ • http://www.flickr.com/photos/47833351@N02/5488791911/(CC BY-ND 2.0) • (CC BY 2.0) – http://www.flickr.com/photos/barry_b/76055201/ – http://www.flickr.com/photos/25165196@N08/7725273678/ – http://www.flickr.com/photos/29254399@N08/3187186308/ – https://www.flickr.com/photos/garryknight/5650367750/ – https://www.flickr.com/photos/alper/10742816123/ • (CC BY-NC-SA 2.0) – http://www.flickr.com/photos/dolescum/7380616658/ – http://www.flickr.com/photos/antonkovalyov/5795281215/ – http://www.flickr.com/photos/doug88888/2792209612/ – https://www.flickr.com/photos/denverjeffrey/4392418334/ • (CC BY-NC 2.0) – http://www.flickr.com/photos/37996583811@N01/5757983532/ – http://www.flickr.com/photos/sevendead/5650065458/ – https://www.flickr.com/photos/whitecatsg/3146092196/