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. 2.
  2. 6.
  3. 7.

    /me

  4. 8.
  5. 9.
  6. 12.

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

    Aaron Burr Sure! -- Alexander Hamilton
  7. 15.
  8. 16.

    • Algorithms • Data structures • Patterns • Idiomatic coding

    • Code smells • Automated Testing • Commit workflow • Coding standards • Hiring • Language selection • API design • Theory of Programming Languages
  9. 18.
  10. 25.
  11. 26.

    
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  12. 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)
  13. 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)
  14. 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)
  15. 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)
  16. 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)
  17. 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)
  18. 33.

    
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  19. 34.

    
 Forces Surrounding Code Code 
 Inertia
 Respect
 Fear Easy

    to write Standard form Ease of change Easy to read Performance Boundaries of Responsibility
  20. 35.

    
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  21. 36.
  22. 41.

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

    # Array `packed` is ['hat', 'glasses', 'socks'] last_one = packed[-1]
  23. 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]
  24. 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]
  25. 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()
  26. 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()
  27. 47.

    
 Forces Surrounding Code Code Easy to write Standard form


    (Pattern, Idiom, Standards, Vocab) Ease of change Easy to read Performance Boundaries of Responsibility
  28. 51.

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

    =~ /sketchy/ ) { $suspect = $p; last; } }
  29. 52.

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

    =~ /sketchy/ ) { $suspect = $p; last; } } use List::Util qw<first>; my $suspect = first { /sketchy/ } @people;
  30. 55.
  31. 62.

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

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

    sub should_log ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; }
  33. 64.

    sub should_log ( $department ) { return 1 if $audits{$department};

    return 1 if $department eq 'IA'; return 0; }
  34. 65.
  35. 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;
  36. 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;
  37. 68.

    
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  38. 69.

    
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  39. 70.

    Rules Of Optimization wiki.c2.com First Rule Of Optimization - Don't.

    Second Rule Of Optimization - Don't... yet. Profile Before Optimizing
  40. 72.

    
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance Boundaries of Responsibility
  41. 76.

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

    @sorted_cars = sort @cars; for my $car (@sorted_cars) { }
  42. 78.

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

    whiffle() burble() snicker-snack() galumph()
  43. 79.

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

    whiffle() burble() snicker-snack() galumph()
  44. 82.
  45. 83.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    keys @soldiers ) { my $s = $soldiers[$i]; if ( $s->valor ) { $medals += 2; if ( !$promote ) { $promote = $s; } }
  64. 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; }
  65. 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; }
  66. 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; }
  67. 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; }
  68. 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; }
  69. 117.

    my @transfers; for my $i ( keys @soldiers ) {

    my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  70. 118.

    my @transfers; for my $i ( keys @soldiers ) {

    my $s = $soldiers[$i]; push @transfers, $i if $s->wants_change_of_station; }
  71. 119.

    my @transfers; for my $i ( keys @soldiers ) {

    push @transfers, $i if $soldiers[$i]->wants_change_of_station; }
  72. 120.

    my @transfers; for my $i ( keys @soldiers ) {

    push @transfers, $i if $soldiers[$i]->wants_change_of_station; }
  73. 121.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  74. 122.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  75. 123.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  76. 124.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  77. 125.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  78. 126.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  79. 127.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  80. 128.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  81. 129.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; }
  82. 130.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } @target = grep { CONDITION } @source;
  83. 131.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { CONDITION } @source;
  84. 132.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { CONDITION } keys @soldiers;
  85. 133.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { CONDITION } keys @soldiers;
  86. 134.

    my @transfers; for ( keys @soldiers ) { push @transfers,

    $_ if $soldiers[$_]->wants_change_of_station; } my @temp = grep { $soldiers[$_]->wants_change_of_station } keys @soldiers;
  87. 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);
  88. 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);
  89. 137.

    my @transfers; for ( keys @soldiers ) { push @transfers,

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

    my @transfers; for ( keys @soldiers ) { push @transfers,

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

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

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

    my ( $promote, $medals ); for my $i ( @soldiers

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

    my ( $promote, $medals ); for my $i ( @soldiers

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

    my ( $promote, $medals ); for my $s ( @soldiers

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

    my ( $promote, $medals ); for my $s ( @soldiers

    ) { if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  96. 156.

    my ( $promote, $medals ); for my $s ( @soldiers

    ) { if ( $s->valor ) { $medals += 2; $promote = $s if !$promote; } }
  97. 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; } }
  98. 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; } }
  99. 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; } }
  100. 160.

    use List::Util qw<sum first>; my $medals; for ( @soldiers )

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

    use List::Util qw<sum first>; my $medals; for ( @soldiers )

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

    use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote; for ( @soldiers ) { if ( $_->valor ) { $promote = $_ if !$promote; } }
  103. 163.

    use List::Util qw<sum first>; my $medals = sum map {

    $_->valor ? 2 : 0 } @soldiers; my $promote = first { $_->valor } @soldiers;
  104. 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;
  105. 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;
  106. 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;
  107. 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;
  108. 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;
  109. 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;
  110. 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;
  111. 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;
  112. 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; } }
  113. 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;
  114. 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
  115. 175.
  116. 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
  117. 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
  118. 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
  119. 179.

    def factorial(n): fact = [ 1, 1, 2, 6, 24,

    120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000] return fact[n]
  120. 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]
  121. 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
  122. 188.
  123. 191.

    Q&A

  124. 193.
  125. 194.
  126. 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/

  127. 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)
  128. 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
  129. 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.
  130. 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

  131. 201.
  132. 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 ]++; }
  133. 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 );
  134. 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 );
  135. 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 );
  136. 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 );
  137. 209.

    $machine->print( $format, $start ); $machine->reset( $init_value ); $machine->confuse( $level, $ray

    ); $register->print(); $register->reset(); $register->amend( $new_value );
  138. 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 );
  139. 211.

    $machine->print( $format, $start ); $machine->reset( $init_value ); $machine->confuse( $level, $ray

    ); $register->print(); $register->reset(); $register->amend( $new_value );
  140. 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 );
  141. 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
  142. 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 ],
  143. 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 ],
  144. 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 ],
  145. 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] ⋮
  146. 226.
  147. 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);
  148. 230.

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

    max(range(i, n), key = lambda x: abs(m[x][i]))
  149. 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
  150. 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