Refactoring and Readability - OSCON 2019

Refactoring and Readability - OSCON 2019

Quality literature isn’t produced by just writing; it’s in the rewriting that excellence is achieved. This is also true with code. Readability is crucial to code quality and is best achieved by switching your mind-set from writer to reader. That switch fits naturally into the act of refactoring.

Bruce Gray shines a spotlight on swapping hats, moving fluidly from problem solving (writer role) to communicating (editor role) and back. Refactoring is to programmers as lifting is to UPS workers: so basic that it gets overlooked, yet so fundamental that doing it naively can hurt. Refactoring is worth practicing as a discrete skill, bound to an implied value judgement of better code, best served with a separate commit workflow, and unsafe without automated testing.

E8c82943a6b1f2acdf4b7fbf4538e1fd?s=128

Bruce Gray

July 17, 2019
Tweet

Transcript

  1. Refactoring and Readability OSCON
 
 2019-07-17
 
 ( For coders,

    or coders-to-be )
  2. None
  3. Refactoring and Readability http://speakerdeck.com/util
 
 <bruce.gray@acm.org> <<< >>> >>> <<<

  4. ( This space intentionally left blank )

  5. Refactoring and Readability http://speakerdeck.com/util
 
 <bruce.gray@acm.org> <<< >>> >>> <<<

  6. Q&A ==>

  7. /me

  8. Util

  9. Perl 6

  10. Can we agree
 that duels are dumb
 and immature?

  11. Can we agree
 that duels are dumb
 and immature? Sure!

  12. Can we agree
 that duels are dumb
 and immature? --

    Aaron Burr Sure! -- Alexander Hamilton
  13. RosettaCode.org

  14. CodeFights 40 languages

  15. last;

  16. • Algorithms • Data structures • Patterns • Idiomatic coding

    • Code smells • Automated Testing • Commit workflow • Coding standards • Hiring • Language selection • API design • Theory of Programming Languages
  17. Refactoring

  18. None
  19. Refactoring Safely

  20. Refactoring Safely Sanely

  21. git init
 git add .
 git commit -m 'Initial commit'

  22. sqlite + cUrl + perl + md5

  23. Modes Fix Add Refactor

  24. Modes Fix Add Refactor

  25. Force

  26. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  27. 
 Forces Surrounding Code (Context) Code Easy to write (hack

    hack hack) Standard form
 (Pattern, Idiom, Standards, Vocab) Ease of change (Flexibility) Easy to read (Time until comprehension ) Performance (Speed) Boundaries of Responsibility (Slicing)
  28. 
 Forces Surrounding Code (Context) Code Easy to write (hack

    hack hack) Standard form
 (Pattern, Idiom, Standards, Vocab) Ease of change (Flexibility) Easy to read (Time until comprehension ) Performance (Speed) Boundaries of Responsibility (Slicing)
  29. 
 Forces Surrounding Code (Context) Code Easy to write (hack

    hack hack) Standard form
 (Pattern, Idiom, Standards, Vocab) Ease of change (Flexibility) Easy to read (Time until comprehension ) Performance (Speed) Boundaries of Responsibility (Slicing)
  30. 
 Forces Surrounding Code (Context) Code Easy to write (hack

    hack hack) Standard form
 (Pattern, Idiom, Standards, Vocab) Ease of change (Flexibility) Easy to read (Time until comprehension ) Performance (Speed) Boundaries of Responsibility (Slicing)
  31. 
 Forces Surrounding Code (Context) Code Easy to write (hack

    hack hack) Standard form
 (Pattern, Idiom, Standards, Vocab) Ease of change (Flexibility) Easy to read (Time until comprehension ) Performance (Speed) Boundaries of Responsibility (Slicing)
  32. 
 Forces Surrounding Code (Context) Code Easy to write (hack

    hack hack) Standard form
 (Pattern, Idiom, Standards, Vocab) Ease of change (Flexibility) Easy to read (Time until comprehensio n) Performance (Speed) Boundaries of Responsibility (Slicing)
  33. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  34. 
 Forces Surrounding Code Code 
 Inertia
 Respect
 Fear Easy

    to write Standard form Ease of change Easy to read Performance Boundaries of Responsibility
  35. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  36. Word

  37. // Array `packed` is ["hat", "glasses"]

  38. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks';

  39. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

  40. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

    # Array `packed` is ['hat', 'glasses', 'socks']
  41. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

    # Array `packed` is ['hat', 'glasses', 'socks'] last_one = packed[-1]
  42. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

    # Array `packed` is ['hat', 'glasses', 'socks'] last_one = packed[-1] packed = packed[0:-1]
  43. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

    # Array `packed` is ['hat', 'glasses', 'socks'] last_one = packed[-1] packed = packed[0:-1]
  44. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

    # Array `packed` is ['hat', 'glasses', 'socks'] last_one = packed[-1] packed = packed[0:-1] last_one = packed.pop()
  45. Don't
 Repeat
 Yourself

  46. // Array `packed` is ["hat", "glasses"] packed[packed.length] = 'socks'; packed.push('socks');

    # Array `packed` is ['hat', 'glasses', 'socks'] last_one = packed[-1] packed = packed[0:-1] last_one = packed.pop()
  47. 
 Forces Surrounding Code Code Easy to write Standard form


    (Pattern, Idiom, Standards, Vocab) Ease of change Easy to read Performance Boundaries of Responsibility
  48. https://docs.python.org/3/reference/


  49. https://docs.python.org/3/reference/
 https://docs.python.org/3/library/


  50. https://docs.python.org/3/reference/
 https://docs.python.org/3/library/
 string
 itertools
 etc

  51. my $suspect; for my $p (@people) { if ( $p

    =~ /sketchy/ ) { $suspect = $p; last; } }
  52. my $suspect; for my $p (@people) { if ( $p

    =~ /sketchy/ ) { $suspect = $p; last; } } use List::Util qw<first>; my $suspect = first { /sketchy/ } @people;
  53. http://www.ecma-international.org/ecma-262/

  54. http://www.ecma-international.org/ecma-262/
 
 developer.mozilla.org/en-US/docs/Web/JavaScript

  55. Mechanics

  56. sub final_form ($fighter) { ... code ... }

  57. sub trigger_final_form ($fighter) { ... code ... }

  58. sub final_form ($fighter) { } sub trigger_final_form ($fighter) { ...

    code ... }
  59. sub final_form ($fighter) { return trigger_final_form($fighter); } sub trigger_final_form ($fighter)

    { ... code ... }
  60. sub trigger_final_form ($fighter) { ... code ... }

  61. Refactor to Debug:
 Wrapping

  62. sub should_log ( $department ) { my $r; if (

    $audits{$department} ) { $r = 1 } elsif ( $department eq 'IA' ) { $r = 1 } else { $r = 0 } return $r; }
  63. sub should_log ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; }
  64. sub should_log ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; }
  65. sub should_log_WRAPPED ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; }
  66. sub should_log_WRAPPED ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; } sub should_log ( $department ) { my $r = should_log_WRAPPED($department); return $r;
  67. sub should_log_WRAPPED ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; } sub should_log ( $department ) { say "> should_log:", Dumper $department; my $r = should_log_WRAPPED($department); say "< should_log:", Dumper $r; return $r;
  68. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  69. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  70. Rules Of Optimization wiki.c2.com First Rule Of Optimization - Don't.

    Second Rule Of Optimization - Don't... yet. Profile Before Optimizing
  71. That's another show...

  72. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  73. Readability

  74. What's in a name?

  75. for my $car ( sort @cars ) { }

  76. for my $car ( sort @cars ) { } my

    @sorted_cars = sort @cars; for my $car (@sorted_cars) { }
  77. seek_manxome() whiffle() burble() snicker-snack() galumph()

  78. # These seven lines are to slay the Jabberwock. seek_manxome()

    whiffle() burble() snicker-snack() galumph()
  79. # These seven lines are to slay the Jabberwock. seek_manxome()

    whiffle() burble() snicker-snack() galumph()
  80. sub slay-the-Jabberwock { seek_manxome() whiffle() burble() snicker-snack() galumph() } ...

    slay-the-Jabberwock();
  81. A good full Pipe

  82. None
  83. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  84. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  85. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  86. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  87. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  88. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  89. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  90. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  91. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  92. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  93. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  94. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  95. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  96. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  97. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  98. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  99. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  100. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  101. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  102. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  103. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  104. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  105. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  106. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  107. if ( $s->wants_change_of_station ) { push @transfers, $i; } }

  108. push @transfers, $i if $s->wants_change_of_station;

  109. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  110. if ( !$promote ) { $promote = $s; }

  111. $promote = $s if !$promote;

  112. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } push @transfers, $i if $s->wants_change_of_station; }
  113. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } push @transfers, $i if $s->wants_change_of_station; }
  114. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } } for my $i ( keys @soldiers ) { my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  115. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } } for my $i ( keys @soldiers ) { my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  116. my ( $promote, $medals ); for my $i ( keys

    @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } } my @transfers; for my $i ( keys @soldiers ) { my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  117. my @transfers; for my $i ( keys @soldiers ) {

    my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  118. my @transfers; for my $i ( keys @soldiers ) {

    my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  119. my @transfers; for my $i ( keys @soldiers ) {

    push @transfers, $i if $soldiers[$i]->wants_change_of_station; }
  120. my @transfers; for my $i ( keys @soldiers ) {

    push @transfers, $i if $soldiers[$i]->wants_change_of_station; }
  121. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  122. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  123. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  124. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  125. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  126. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  127. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  128. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  129. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  130. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } @target = grep { CONDITION } @source;
  131. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { CONDITION } @source;
  132. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { CONDITION } keys @soldiers;
  133. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { CONDITION } keys @soldiers;
  134. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  135. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers; die if join(',', @temp) ne join(',', @soldiers);
  136. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers; log if join(',', @temp) ne join(',', @soldiers);
  137. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  138. my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  139. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  140. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  141. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  142. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  143. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  144. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  145. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  146. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  147. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  148. my @transfers; my @temp = grep { $soldiers[$_]->wants_change_of_station } keys

    @soldiers;
  149. my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;

  150. my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;

  151. my ( $promote, $medals ); for my $i ( keys

    @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  152. my ( $promote, $medals ); for my $i ( @soldiers

    ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  153. my ( $promote, $medals ); for my $i ( @soldiers

    ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  154. my ( $promote, $medals ); for my $s ( @soldiers

    ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  155. my ( $promote, $medals ); for my $s ( @soldiers

    ) { if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  156. my ( $promote, $medals ); for my $s ( @soldiers

    ) { if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  157. my $medals; for my $s ( @soldiers ) { if

    ( $s->valor ) { $medals += 2; } } my $promote; for my $s ( @soldiers ) { if ( $s->valor ) { $promote = $s if !$promote; } }
  158. my $medals; for my $s ( @soldiers ) { if

    ( $s->valor ) { $medals += 2; } } my $promote; for my $s ( @soldiers ) { if ( $s->valor ) { $promote = $s if !$promote; } }
  159. use List::Util qw<sum first>; my $medals; for my $s (

    @soldiers ) { if ( $s->valor ) { $medals += 2; } } my $promote; for my $s ( @soldiers ) { if ( $s->valor ) { $promote = $s if !$promote; } }
  160. use List::Util qw<sum first>; my $medals; for ( @soldiers )

    { if ( $_->valor ) { $medals += 2; } } my $promote; for ( @soldiers ) { if ( $_->valor ) { $promote = $_ if !$promote; } }
  161. use List::Util qw<sum first>; my $medals; for ( @soldiers )

    { if ( $_->valor ) { $medals += 2; } } my $promote; for ( @soldiers ) { if ( $_->valor ) { $promote = $_ if !$promote; } }
  162. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote; for ( @soldiers ) { if ( $_->valor ) { $promote = $_ if !$promote; } }
  163. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers;
  164. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  165. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  166. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  167. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  168. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  169. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  170. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  171. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  172. my ( $promote, $medals, @transfers ); for my $i (

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } } if ( $s->wants_change_of_station ) { push @transfers, $i; } }
  173. use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers; my @transfers = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  174. use List::Util qw<sum first>; my @transfers = grep { $soldiers[$_]->wants_change_of_station

    } keys @soldiers; my @valor = grep { $_->valor } @soldiers; my $medals = 2 * @valor; my $promote = $valor[0]; # Version for people who cannot pause their performance obsession
  175. Wow!

  176. def factorial(n): n0 = 1 n1 = 1 n2 =

    2 n3 = 6 n4 = 24 n5 = 120 n6 = 720 n7 = 5040 n8 = 40320 n9 = 362880 n10 = 3628800 n11 = 39916800 n12 = 479001600 n13 = 6227020800 n14 = 87178291200 n15 = 1307674368000 if n == 0: return n0 elif n == 1: return n1 elif n == 2: return n2 elif n == 3: return n3 elif n == 4: return n4 elif n == 5: return n5 elif n == 6: return n6 elif n == 7: return n7 elif n == 8: return n8 elif n == 9: return n9 elif n == 10: return n10 elif n == 11: return n11 elif n == 12: return n12 elif n == 13: return n13 elif n == 14: return n14 elif n == 15: return n15
  177. def factorial(n): n0 = 1 n1 = 1 n2 =

    2 n3 = 6 n4 = 24 n5 = 120 n6 = 720 n7 = 5040 n8 = 40320 n9 = 362880 n10 = 3628800 n11 = 39916800 n12 = 479001600 n13 = 6227020800 n14 = 87178291200 n15 = 1307674368000 if n == 0: return n0 elif n == 1: return n1 elif n == 2: return n2 elif n == 3: return n3 elif n == 4: return n4 elif n == 5: return n5 elif n == 6: return n6 elif n == 7: return n7 elif n == 8: return n8 elif n == 9: return n9 elif n == 10: return n10 elif n == 11: return n11 elif n == 12: return n12 elif n == 13: return n13 elif n == 14: return n14 elif n == 15: return n15
  178. def factorial(n): if n == 0: return 1 elif n

    == 1: return 1 elif n == 2: return 2 elif n == 3: return 6 elif n == 4: return 24 elif n == 5: return 120 elif n == 6: return 720 elif n == 7: return 5040 elif n == 8: return 40320 elif n == 9: return 362880 elif n == 10: return 3628800 elif n == 11: return 39916800 elif n == 12: return 479001600 elif n == 13: return 6227020800 elif n == 14: return 87178291200 elif n == 15: return 1307674368000
  179. def factorial(n): fact = [ 1, 1, 2, 6, 24,

    120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000] return fact[n]
  180. def factorial(n): f = 1 for x in range(2, n+1):

    f *= x return f
  181. @factorials = 1, |[\*] 1 .. *; # Perl 6

  182. @factorials = 1, |[\*] 1 .. *; # Perl 6

    fact = [1] # Caches between calls! def factorial(n): while len(fact)-1 < n: fact.append( fact[-1] * len(fact) ) return fact[n]
  183. def factorial(n): f = 1 for x in range(2, n+1):

    f *= x return f
  184. import math factorial = math.factorial

  185. def factorial(n): f = 1 for x in range(2, n+1):

    f *= x return f
  186. def factorial(n): n0 = 1 n1 = 1 n2 =

    2 n3 = 6 n4 = 24 n5 = 120 n6 = 720 n7 = 5040 n8 = 40320 n9 = 362880 n10 = 3628800 n11 = 39916800 n12 = 479001600 n13 = 6227020800 n14 = 87178291200 n15 = 1307674368000 if n == 0: return n0 elif n == 1: return n1 elif n == 2: return n2 elif n == 3: return n3 elif n == 4: return n4 elif n == 5: return n5 elif n == 6: return n6 elif n == 7: return n7 elif n == 8: return n8 elif n == 9: return n9 elif n == 10: return n10 elif n == 11: return n11 elif n == 12: return n12 elif n == 13: return n13 elif n == 14: return n14 elif n == 15: return n15
  187. def factorial(n): f = 1 for x in range(2, n+1):

    f *= x return f
  188. Can't miss

  189. Really can't miss

  190. Rate today's session O’Reilly Events App Session page on conference

    website
  191. Q&A

  192. Refactoring and Readability http://speakerdeck.com/util
 
 <bruce.gray@acm.org> <<< >>> >>> <<<

  193. Thanks!

  194. Copyrights

  195. Copyright Information: Images • Camelia • (c) 2009 by Larry

    Wall
 http://github.com/perl6/mu/raw/master/misc/ camelia.txt • New rules for Science Journalism • Zach Weinersmith
 http://www.smbc-comics.com/comic/ 2010-11-26 • Packages • © Randall Munroe
 https://xkcd.com/576/

  196. Copyright Information: This Talk This work is licensed under a

    Creative Commons Attribution 4.0 International License. CC BY https://creativecommons.org/licenses/by/4.0/ (email me for the original Apple Keynote .key file)
  197. Recommended Links • The original book, for Java. Now also

    for Ruby and JS
 https://refactoring.com/ • Book: Refactoring JavaScript. Worth learning JS just to read it!
 http://refactoringjs.com/ • The Art of Readable Code
 http://shop.oreilly.com/product/9780596802301.do • http://wiki.c2.com/?RulesOfOptimization • http://wiki.c2.com/?ProfileBeforeOptimizing
  198. Anti-Links • None yet.
 If I did not list a

    relevant book in Links,
 it probably just means I have not read that book in depth yet.
  199. History • v 0.99 2019-06-06
 Presented at Atlanta Perlmongers
 (shelved)

    • v 1.01 2019-06-14
 Presented at Southeast LinuxFest
 60 minutes with Q&A • v 1.02 2019-06-17
 Presented at The Perl Conference
 50 minutes with Q&A • v 1.03 2019-06-17
 Presented at OSCON, with many changes
 40 minutes with Q&A

  200. Removed
 (Not presented, 
 but maybe worth reading)

  201. Dense

  202. for my $car (@vehicles) { my $color = $colors_by_type[ $car->type

    ]; if ( not $color->available ) { $color = $colors_by_type[ rand @colors_by_type ]; } $car->assemble_inspect_and_ship($color); $dealers[ $car->order_source ]++; }
  203. for my $car (@vehicles) { my $color = get_car_color(@car); $car->assemble_paint_and_ship($color);

    $dealers->give_credit_for_order($car); }
  204. Wholesale (changes)

  205. print_machine( $machine, $format, $start ); reset_machine( $machine, $init_value ); confuse_machine(

    $machine, $level, $ray ); print_register( $register ); reset_register( $register ); amend_register( $register, $new_value );
  206. print_machine( $machine, $format, $start ); reset_machine( $machine, $init_value ); confuse_machine(

    $machine, $level, $ray ); print_register( $register ); reset_register( $register ); amend_register( $register, $new_value );
  207. print_machine( $machine, $format, $start ); reset_machine( $machine, $init_value ); confuse_machine(

    $machine, $level, $ray ); print_register( $register ); reset_register( $register ); amend_register( $register, $new_value );
  208. print_machine( $machine, $format, $start ); reset_machine( $machine, $init_value ); confuse_machine(

    $machine, $level, $ray ); print_register( $register ); reset_register( $register ); amend_register( $register, $new_value );
  209. $machine->print( $format, $start ); $machine->reset( $init_value ); $machine->confuse( $level, $ray

    ); $register->print(); $register->reset(); $register->amend( $new_value );
  210. print_machine( $machine, $format, $start ); reset_machine( $machine, $init_value ); confuse_machine(

    $machine, $level, $ray ); print_register( $register ); reset_register( $register ); amend_register( $register, $new_value );
  211. $machine->print( $format, $start ); $machine->reset( $init_value ); $machine->confuse( $level, $ray

    ); $register->print(); $register->reset(); $register->amend( $new_value );
  212. print_machine( $machine, $format, $start ); reset_machine( $machine, $init_value ); confuse_machine(

    $machine, $level, $ray ); print_register( $register ); reset_register( $register ); amend_register( $register, $new_value );
  213. print_machine( $machine, $format, $start );

  214. print_machine( $machine, $format, $start );

  215. print_machine( $machine, $format, $start ); $machine->print( $format, $start );

  216. Enter the Matrix Final Chapter

  217. foo(); bar(); foo(); bar(); foo(); bar(); foo(); bar();

  218. for (1 .. 4) { foo(); bar(); }

  219. 31w + 55x + 46y + 30z = 76 84w

    + 92x + 37y + 72z = 16 57w + 37x + 34y + 85z = 71 93w + 62x + 71y + 49z = 42 86w + 48x + 36y + 42z = 88 -34w + 71x + 47y + 32z = 73 21w + 32x + 34y + 19z = 54 -99w + 25x + 39y + 62z = 23
  220. [ 1, 0, 0, 0, 31, 55, 46, 30, 76

    ], [ 0, 1, 0, 0, 84, 92, 37, 72, 16 ], [ 0, 0, 1, 0, 57, 37, 34, 85, 71 ], [ 0, 0, 0, 1, 93, 62, 71, 49, 42 ], [ 0, 0, 0, 0, 86, 48, 36, 42, 88 ], [ 0, 0, 0, 0, -34, 71, 47, 32, 73 ], [ 0, 0, 0, 0, 21, 32, 34, 19, 54 ], [ 0, 0, 0, 0, -99, 25, 39, 62, 23 ],
  221. [ 1, 0, 0, 0, 31, 55, 46, 30, 76

    ], [ 0, 1, 0, 0, 84, 92, 37, 72, 16 ], [ 0, 0, 1, 0, 57, 37, 34, 85, 71 ], [ 0, 0, 0, 1, 93, 62, 71, 49, 42 ], [ 0, 0, 0, 0, 86, 48, 36, 42, 88 ], [ 0, 0, 0, 0, -34, 71, 47, 32, 73 ], [ 0, 0, 0, 0, 21, 32, 34, 19, 54 ], [ 0, 0, 0, 0, -99, 25, 39, 62, 23 ],
  222. [ 1, 0, 0, 0, 31, 55, 46, 30, 76

    ], [ 0, 1, 0, 0, 84, 92, 37, 72, 16 ], [ 0, 0, 1, 0, 57, 37, 34, 85, 71 ], [ 0, 0, 0, 1, 93, 62, 71, 49, 42 ], [ 0, 0, 0, 0, 86, 48, 36, 42, 88 ], [ 0, 0, 0, 0, -34, 71, 47, 32, 73 ], [ 0, 0, 0, 0, 21, 32, 34, 19, 54 ], [ 0, 0, 0, 0, -99, 25, 39, 62, 23 ],
  223. def gauss(m): n, p = len(m), len(m[0]) for i in

    range(n): k = i + argmax(m[i:n],i) m[i], m[k] = m[k], m[i] ⋮
  224. k = i + argmax( m[i:n], i )

  225. def argmax(m,i): col = [abs(row[i]) for row in m] return

    col.index(max(col))
  226. def argmax(m,i): col = [abs(row[i]) for row in m] return

    col.index(max(col)) # Double work!
  227. # Perl 5 use List::UtilsBy qw<max_by>; $tallest = max_by {

    $_->height } @people; # Perl 6 $tallest = @people.max( *.height ); # Python (since 2.5 in 2006) tallest = max(people, key=lambda x: x.height);
  228. max( range(i, n), key = lambda x: abs(m[x][i]) )

  229. max( range(i, n), key = lambda x: abs(m[x][i]) )

  230. k = i + argmax( m[i:n], i ) k =

    max(range(i, n), key = lambda x: abs(m[x][i]))
  231. k = i + argmax( m[i:n], i ) k =

    max(range(i, n), key = lambda x: abs(m[x][i])) $k = max_by { abs($m[$_][$i]) } $i..$#m; #P5
  232. def column_index_with_max_abs_value(m,i): return max(range(i, n), key = lambda x: abs(m[x][i]))

    k = column_index_with_max_abs_value(m,i)
  233. Key knowledge (Perl) • List::Util first max min sum all

    any none uniq shuffle • List::UtilsBy max_by min_by count_by • perlfunc Perl Functions by Category • Test::Tutorial Intro to Automated Testing • Devel::Cover Shows code that lacks testing • Benchmark Performance comparisons • Devel::NYTProf Perfomance profiler
  234. Perl 6 == 
 Perl 5 minus Warts plus Awesome