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

Refactoring and Readability

Refactoring and Readability

Refactoring is:

worth practicing as a discrete skill
bound to an implied value judgement of "better" code
best served with a separate commit workflow
unsafe without automated testing

Readability is:

crucial to code quality
best achieved by "switching hats" during refactoring
to be prioritized over premature optimization.
beneficial to more than just technical debt

Bruce Gray

June 14, 2019
Tweet

More Decks by Bruce Gray

Other Decks in Programming

Transcript

  1. /me

  2. sub foo { die if @_ != 3; my ($x,

    $y, $z) = @_; ⋮ }
  3. # Assume all my Perl 5 code begins with: use

    strict; use warnings; use 5.020; use experimental qw<signatures>;
  4. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance (Speed) Boundaries of Responsibility (Slicing)
  5. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance (Speed) Boundaries of Responsibility
  6. sub should_log ( $department ) { my $r; if (

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

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

    return 1 if $department eq 'IA'; return 0; }
  9. 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;
  10. 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;
  11. 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; perl -d pgm c should_log n p $department n p $r $r = 0 c
  12. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance (Speed) Boundaries of Responsibility
  13. 
 Forces Surrounding Code Code Easy to write Standard form

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

    Second Rule Of Optimization - Don't... yet. Profile Before Optimizing
  15. 
 Forces Surrounding Code Code Easy to write Standard form

    Ease of change Easy to read Performance (Speed) Boundaries of Responsibility
  16. 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 );
  17. 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 );
  18. 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 );
  19. 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 );
  20. $machine->print( $format, $start ); $machine->reset( $init_value ); $machine->confuse( $level, $ray

    ); $register->print( $register ); $register->reset( $register ); $register->amend( $register, $new_value );
  21. 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 );
  22. 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 ]++; }
  23. 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
  24. 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
  25. 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
  26. def factorial(n): fact = [ 1, 1, 2, 6, 24,

    120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 87178291200, 1307674368000] return fact[n]
  27. @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]
  28. 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
  29. [ 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 ],
  30. [ 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 ],
  31. [ 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 ],
  32. 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] ⋮
  33. # 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);
  34. k = i + argmax( m[i:n], i ) k =

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

  38. 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/
  39. Links • The original book, for Java. Now also for

    Ruby and JS
 https://refactoring.com/ • Book: Refactoring JavaScript
 http://refactoringjs.com/ • http://wiki.c2.com/?RulesOfOptimization • http://wiki.c2.com/?ProfileBeforeOptimizing
  40. History • v 0.99 2019-06-06
 Presented at Atlanta Perlmongers (shelved)

    • v 1.01 2019-06-14
 Presented at Southeast LinuxFest