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

Perlの静的解析入門とPerlリファクタリングツールApp::PRTのご紹介

hitode909
August 30, 2014

 Perlの静的解析入門とPerlリファクタリングツールApp::PRTのご紹介

YAPC::Asia Tokyo 2014で発表しました

hitode909

August 30, 2014
Tweet

More Decks by hitode909

Other Decks in Technology

Transcript

  1. ։ԋ·Ͱͷؒ
    ژ౎ͷࣸਅΛ
    ָ͓͠Έ͍ͩ͘͞
    IUUQQIPUPTBOPHSBQIJYOFU
    14೥8݄30೔౔༵೔

    View Slide

  2. IUUQQIPUPTBOPHSBQIJYOFU
    ։ԋ·Ͱͷؒ
    ژ౎ͷࣸਅΛ
    ָ͓͠Έ͍ͩ͘͞
    14೥8݄30೔౔༵೔

    View Slide

  3. IUUQQIPUPTBOPHSBQIJYOFU
    ։ԋ·Ͱͷؒ
    ژ౎ͷࣸਅΛ
    ָ͓͠Έ͍ͩ͘͞
    14೥8݄30೔౔༵೔

    View Slide

  4. IUUQQIPUPTBOPHSBQIJYOFU
    ։ԋ·Ͱͷؒ
    ژ౎ͷࣸਅΛ
    ָ͓͠Έ͍ͩ͘͞
    14೥8݄30೔౔༵೔

    View Slide

  5. IUUQQIPUPTBOPHSBQIJYOFU
    ։ԋ·Ͱͷؒ
    ژ౎ͷࣸਅΛ
    ָ͓͠Έ͍ͩ͘͞
    14೥8݄30೔౔༵೔

    View Slide

  6. IUUQQIPUPTBOPHSBQIJYOFU
    ։ԋ·Ͱͷؒ
    ژ౎ͷࣸਅΛ
    ָ͓͠Έ͍ͩ͘͞
    14೥8݄30೔౔༵೔

    View Slide

  7. 1FSMͷ੩తղੳ
    ೖ໳ͱ1FSM
    ϦϑΝΫλϦϯά
    πʔϧ
    "QQ135
    ͷ͝঺հ
    IJUPEF
    14೥8݄30೔౔༵೔

    View Slide

  8. IJUPEF
    झຯ͸ϚϦϯεϙʔπͰ͢
    14೥8݄30೔౔༵೔

    View Slide

  9. 14೥8݄30೔౔༵೔

    View Slide

  10. 14೥8݄30೔౔༵೔

    View Slide

  11. ΋͘͡
    14೥8݄30೔౔༵೔

    View Slide

  12. ΋͘͡
    ϦϑΝΫλϦϯάʹ͍ͭͯ
    1FSMͷϦϑΝΫλϦϯά
    ੩తղੳೖ໳
    ੩తղੳ࿅श
    ϦϑΝΫλϦϯάπʔϧͷ঺հ
    ϦϑΝΫλϦϯά࿅श
    ࣄྫ঺հ
    14೥8݄30೔౔༵೔

    View Slide

  13. 4&&"-40
    14೥8݄30೔౔༵೔

    View Slide

  14. Perl::Lint - Yet
    Another Perl
    Source Code
    Linter
    14೥8݄30೔౔༵೔

    View Slide

  15. ΋͘͡
    ϦϑΝΫλϦϯάʹ͍ͭͯ
    1FSMͷϦϑΝΫλϦϯά
    ੩తղੳೖ໳
    ੩తղੳ࿅श
    ϦϑΝΫλϦϯάπʔϧͷ঺հ
    ϦϑΝΫλϦϯά࿅श
    ࣄྫ঺հ
    14೥8݄30೔౔༵೔

    View Slide


  16. 14೥8݄30೔౔༵೔

    View Slide

  17. ΋͘͡
    ϦϑΝΫλϦϯάʹ͍ͭͯ
    1FSMͷϦϑΝΫλϦϯά
    ੩తղੳೖ໳
    ੩తղੳ࿅श
    ϦϑΝΫλϦϯάπʔϧͷ঺հ
    ϦϑΝΫλϦϯά࿅श
    ࣄྫ঺հ
    14೥8݄30೔౔༵೔

    View Slide

  18. ϦϑΝΫλϦϯά
    14೥8݄30೔౔༵೔

    View Slide

  19. 14೥8݄30೔౔༵೔

    View Slide

  20. ϦϑΝΫλϦϯάͱ͸ɺι
    ϑτ΢ΣΞͷ֎෦తৼΔక
    ͍Λอͬͨ··Ͱɺ಺෦ͷ
    ߏ଄Λվળ͍ͯ͘͠࡞ۀΛ
    ࢦ͠·͢ɻ
    14೥8݄30೔౔༵೔

    View Slide

  21. ৼ෣͍Λม͑ͣʹ
    ίʔυΛ͖Ε͍ʹ
    14೥8݄30೔౔༵೔

    View Slide

  22. ѱ໊͍લΛม͑Δ
    14೥8݄30೔౔༵೔

    View Slide

  23. ࣮૷Λྑ͍৔ॴʹҠ͢
    14೥8݄30೔౔༵೔

    View Slide

  24. ࡞ઓߟ͑Δͷ͸೉͍͠
    ࡞ۀࣗମ͸؆୯
    14೥8݄30೔౔༵೔

    View Slide

  25. ϦϑΝΫλϦϯάࣗମͷ
    ࿩͸͠·ͤΜ
    14೥8݄30೔౔༵೔

    View Slide

  26. 14೥8݄30೔౔༵೔

    View Slide

  27. δϟό
    14೥8݄30೔౔༵೔

    View Slide

  28. IUUQTUBDLPWFSqPXDPNRVFTUJPOTDIBOHFOBNFPGBQBDLBHFBGUFSJGJUJTDSFBUFEBOEIBWFDMBTTFTJOFDMJQTFQPT
    14೥8݄30೔౔༵೔

    View Slide

  29. 1FSMͷ৔߹
    14೥8݄30೔౔༵೔

    View Slide

  30. 1FSMͷ৔߹
    ͕Μ͹Δ
    14೥8݄30೔౔༵೔

    View Slide

  31. ιʔείʔυΛΤσΟλͰ
    ॻ͖׵͑Δ
    ݺͼग़͠ݩ΋ॻ͖׵͑Δ
    ςετ͋Ε͹࣮ߦ
    ಈ͚͹ϥοΩʔ
    14೥8݄30೔౔༵೔

    View Slide

  32. ͳΜ͔ͳͷ͍ͷ͔
    14೥8݄30೔౔༵೔

    View Slide

  33. 1BESF UIF1FSM*%&
    1FSM༻ͷ*%&
    ม਺໊มߋͰ͖Δ
    ͏·͘ಈ͔ͳ͔ͬͨ
    ͙͢Ϋϥογϡ͢Δ
    14೥8݄30೔౔༵೔

    View Slide

  34. %FWFM3FGBDUPS
    my $refactory = Devel::Refactor->new;
    $refactory->rename_subroutine(
    './path/to/dir',
    'oldSubName','newSubName'
    );
    ೥ͷϞδϡʔϧ
    αϒϧʔνϯͷϦωʔϜ
    14೥8݄30೔౔༵೔

    View Slide

  35. %FWFM3FGBDUPS
    my $regex1 = '(\W)(' . $old_name . ')(\W)';
    my $regex2 = "^$old_name(" . '\W)';
    while (<$fh>) {
    $line_number++;
    if (/$regex1/o or /$regex2/o) {
    my $new_line = $_;
    $new_line =~ s/$regex1/$1$new_name$3/g;
    $new_line =~ s/$regex2/$new_name$1/;
    ਖ਼نදݱͰஔ׵
    14೥8݄30೔౔༵೔

    View Slide

  36. %FWFM3FGBDUPS
    sub _syntax_check{
    my $self = shift;
    my $tmp;
    my $eval_stmt = "my (". join ', ', @{$self->{parms}};
    $eval_stmt .= ");\n";
    $eval_stmt .= $self->get_sub_call();
    $eval_stmt .= $self->get_new_code();
    $self->{eval_code} = $eval_stmt;
    eval " $eval_stmt ";
    if ([email protected]) {
    $self->{eval_err} = [email protected];
    FWBMͯ͠੒ޭ͔ͨ͠ݟΔ
    ͱʹ͔͘ϫΠϧυ
    14೥8݄30೔౔༵೔

    View Slide

  37. "QQ&EJUPS5PPMT
    &NBDT7JN༻ϓϥάΠϯίϚϯυ
    ϑΝΠϧ໊͔ΒQBDLBHF໊ਪଌͯ͠ೖྗ
    ม਺໊มߋ
    બ୒ൣғΛม਺ʹ͘͘Γग़͠
    ͳ͔ͳ͔Α͍͚Ͳ΋͏ͪΐͬͱ
    14೥8݄30೔౔༵೔

    View Slide

  38. 5SZJOHUPSFGBDUPS
    1FSMDPEF
    14೥8݄30೔౔༵೔

    View Slide

  39. ͦ΋ͦ΋
    ϦϑΝΫλϦϯά
    ͢Δʹ͸
    14೥8݄30೔౔༵೔

    View Slide

  40. TFE
    14೥8݄30೔౔༵೔

    View Slide

  41. 14೥8݄30೔౔༵೔

    View Slide

  42. จࣈྻૢ࡞Ͱ͸ਫ਼౓ѱ͍
    14೥8݄30೔౔༵೔

    View Slide

  43. 14೥8݄30೔౔༵೔

    View Slide

  44. TFE͸ਫ਼౓௿͍
    my $blog = shift;
    print $blog->{id};
    print $blog->{user_id};
    my $blog = shift;
    print $blog->{article_id};
    print $blog->{user_article_id};
    sed -e “s/id/article_id/”
    14೥8݄30೔౔༵೔

    View Slide

  45. ͦ͜Ͱ੩తղੳ
    14೥8݄30೔౔༵೔

    View Slide

  46. ੩తղੳ
    ϓϩάϥϜΛ࣮ߦͤͣʹௐ΂Δ
    ࣮ߦ͢ΔͱಈతղੳʹͳΔ
    14೥8݄30೔౔༵೔

    View Slide

  47. ͍ͭ੩తղੳ͢Δͷ
    γϯλοΫεϋΠϥΠτ
    ߏจνΣοΫ
    ίʔσΟϯάن໿ʹԊͬͯΔ͔
    ੬ऑੑΛ୳͢
    ϦϑΝΫλϦϯά
    14೥8݄30೔౔༵೔

    View Slide

  48. ࡶͳ੩తղੳ
    ϓϩάϥϜΛ࣮ߦͤͣʹ
    ϓϩάϥϜͷੑ࣭Λௐ΂͍ͯΔ
    DBUMJC1MBDLQNcXDM

    14೥8݄30೔౔༵೔

    View Slide

  49. ؆୯Ͱ͠ΐ
    ߦ਺͡Όͳ໋ͯ͘ྩ਺஌Γ͍ͨ
    14೥8݄30೔౔༵೔

    View Slide

  50. ;ͭ͏ͷ੩తղੳ
    14೥8݄30೔౔༵೔

    View Slide

  51. ;ͭ͏ͷ੩తղੳ
    ߏจ໦Λ࡞ͬͯௐ΂Δ
    14೥8݄30೔౔༵೔

    View Slide

  52. print (1 * 2) + 3;
    ߏจ໦
    14೥8݄30೔౔༵೔

    View Slide

  53. ‘;’
    ߏจ໦
    ‘print’ ‘ ‘ List ‘ ‘ ‘ ‘
    ‘1’ ‘ ‘ ‘*’ ‘ ‘ ‘2’
    ‘+’ ‘3’
    Statement
    Document
    print (1 * 2) + 3;
    14೥8݄30೔౔༵೔

    View Slide

  54. ߏจ໦
    print "(1 * 2) + 3";
    14೥8݄30೔౔༵೔

    View Slide

  55. ‘;’
    ߏจ໦
    ‘print’ ‘ ‘
    Statement
    Document
    print "(1 * 2) + 3";
    ‘"(1 * 2) + 3"’
    14೥8݄30೔౔༵೔

    View Slide

  56. ͜ΕͳΒ҆৺
    14೥8݄30೔౔༵೔

    View Slide

  57. ߏจ໦Ͳ͏΍ͬͯ࡞Δͷ
    14೥8݄30೔౔༵೔

    View Slide

  58. 11*
    14೥8݄30೔౔༵೔

    View Slide

  59. 11*
    1FSMղੳͯ͘͠ΕΔϞδϡʔϧ
    1FSM%PDVNFOU0CKFDU.PEFM
    1FSMύʔε͢Δͷ͸೉͍͠ͷͰ͍͢͝
    14೥8݄30೔౔༵೔

    View Slide

  60. ࡶஊ
    $PNQJMFS-FYFS͍ͬͯ͏
    ଎͍ͷ΋͋Δ͚Ͳͦͷ࿩͸͠·ͤΜ
    ࡢ೔ͷNP[OJPOͷൃදݟͯ
    14೥8݄30೔౔༵೔

    View Slide

  61. 11*Ͱ༡΅͏
    14೥8݄30೔౔༵೔

    View Slide

  62. 11*Ͱߏจ໦ݟ͍ͨ
    print (1 * 2) + 3;
    11*%PDVNFOU
    11*4UBUFNFOU
    11*5PLFO8PSEQSJOU
    11*5PLFO8IJUFTQBDF
    11*4USVDUVSF-JTU

    11*4UBUFNFOU&YQSFTTJPO
    11*5PLFO/VNCFS
    11*5PLFO8IJUFTQBDF
    11*5PLFO0QFSBUPS
    11*5PLFO8IJUFTQBDF
    11*5PLFO/VNCFS
    11*5PLFO8IJUFTQBDF
    11*5PLFO0QFSBUPS
    11*5PLFO8IJUFTQBDF
    11*5PLFO/VNCFS
    11*5PLFO4USVDUVSF
    11*5PLFO8IJUFTQBDFaO
    use PPI;
    use PPI::Dumper;
    my $document = PPI::Document->new($ARGV[0]);
    my $dumper = PPI::Dumper->new($document);
    $dumper->print;
    14೥8݄30೔౔༵೔

    View Slide

  63. ‘;’
    Ͱ͖ͨ
    ‘print’ ‘ ‘ List ‘ ‘ ‘ ‘
    ‘1’ ‘ ‘ ‘*’ ‘ ‘ ‘2’
    ‘+’ ‘3’
    Statement
    Document
    print (1 * 2) + 3;
    14೥8݄30೔౔༵೔

    View Slide

  64. 11*Ͱ໋ྩ਺ݟ͍ͨ
    my $document = PPI::Document->new($ARGV[0]);
    my $statements = $document->find('PPI::Statement');
    my $statement_count = @$statements;
    say "count: $statement_count";
    14೥8݄30೔౔༵೔

    View Slide

  65. 11*Ͱ'J[[#V[[Λഁյ͍ͨ͠
    use PPI;
    my $path = $ARGV[0];
    my $document = PPI::Document->new($path);
    my $tokens = $document->find('PPI::Token');
    for my $token (@$tokens) {
    if (ref $token eq 'PPI::Token::Number') {
    $token->set_content($token->content * 2);
    }
    }
    $document->save("broken-$path");
    14೥8݄30೔౔༵೔

    View Slide

  66. 11*Ͱ'J[[#V[[Λഁյ͍ͨ͠
    use PPI;
    my $path = $ARGV[0];
    my $document = PPI::Document->new($path);
    my $tokens = $document->find('PPI::Token');
    for my $token (@$tokens) {
    if (ref $token eq 'PPI::Token::Number') {
    $token->set_content($token->content * 2);
    }
    }
    $document->save("broken-$path");
    ਺ࣈΛݟ͚ͭͨΒ
    ͱΓ͋͑ͣഒʹ͢Δ
    14೥8݄30೔౔༵೔

    View Slide

  67. ͜Ε͕
    use strict;
    use warnings;
    for my $i (1..20) {
    my $message = "";
    $message .= "Fizz" unless $i % 3;
    $message .= "Buzz" unless $i % 5;
    $message = $i unless $message;
    print "$message\n";
    }
    14೥8݄30೔౔༵೔

    View Slide

  68. ͜͏
    use strict;
    use warnings;
    for my $i (2..40) {
    my $message = "";
    $message .= "Fizz" unless $i % 6;
    $message .= "Buzz" unless $i % 10;
    $message = $i unless $message;
    print "$message\n";
    }
    14೥8݄30೔౔༵೔

    View Slide

  69. -(5.

    'J[[



    #V[[

    'J[[





    'J[[

    #V[[



    'J[[





    'J[[#V[[





    'J[[

    14೥8݄30೔౔༵೔

    View Slide

  70. 'J[[#V[[ʹݶΒͣ
    ഁյͰ͖Δ
    14೥8݄30೔౔༵೔

    View Slide

  71. ΢ΣϒΞϓϦέʔγϣϯΛഁյ
    14೥8݄30೔౔༵೔

    View Slide

  72. my $app = sub {
    return [
    200,
    [ 'Content-Type' => 'text/plain' ],
    [ 'Hello World' ] ];
    };
    14೥8݄30೔౔༵೔

    View Slide

  73. my $app = sub {
    return [
    400,
    [ 'Content-Type' => 'text/plain' ],
    [ 'Hello World' ] ];
    };
    14೥8݄30೔౔༵೔

    View Slide

  74. my $app = sub {
    return [
    400,
    [ 'Content-Type' => 'text/plain' ],
    [ 'Hello World' ] ];
    };

    14೥8݄30೔౔༵೔

    View Slide

  75. ϙΠϯτ
    14೥8݄30೔౔༵೔

    View Slide

  76. ϙΠϯτ
    ߏจ໦Λॻ͖׵͑ͯอଘ
    14೥8݄30೔౔༵೔

    View Slide

  77. ศརͳྫ
    14೥8݄30೔౔༵೔

    View Slide

  78. HJUHSFQͷ͍͍΍ͭ
    14೥8݄30೔౔༵೔

    View Slide

  79. HJUHSFQͷ͍͍΍ͭ
    "QQ(JU(SFQ1FSM4UBUFNFOU
    git grep-perl-statement finalize t/
    τʔΫϯ୯ҐͰݕࡧ
    εςʔτϝϯτ୯ҐͰදࣔ
    14೥8݄30೔౔༵೔

    View Slide

  80. HJUHSFQͷ͍͍΍ͭ
    HJUHSFQͰϑΝΠϧ୳͢
    Ϛονͨ͠ϑΝΠϧͷߏจ໦࡞Δ
    TUBUFNFOUΛݸͣͭݟΔ
    TUBUFNFOU͕୳ͯ͠ΔUPLFOΛؚΊ͹දࣔ
    14೥8݄30೔౔༵೔

    View Slide

  81. งғؾ
    my $doc = PPI::Document->new($file);
    my $statements = $doc->find('PPI::Statement');
    grep {
    my $tokens = [ $_->children ];
    any {
    $_ eq $self->word;
    } @$tokens;
    } @$statements;
    14೥8݄30೔౔༵೔

    View Slide

  82. ίʔσΟϯάελΠϧ
    ௐ΂Δ΍ͭ
    14೥8݄30೔౔༵೔

    View Slide

  83. 1FSM$SJUJD
    ίʔσΟϯάελΠϧௐ΂ͯ͘ΕΔ
    νʔϜ಺ͰελΠϧ౷Ұ͢Δͷʹศར
    14೥8݄30೔౔༵೔

    View Slide

  84. Ұൠతͳ1FSMϞδϡʔϧ
    ͷελΠϧΛνΣοΫͯ͠
    Έ·͠ΐ͏
    14೥8݄30೔౔༵೔

    View Slide

  85. package Antipop;
    use strict;
    use warnings;
    our $VERSION = '0.01';
    sub talk {
    return q{ҿΈʹߦͧ͘!!1};
    }
    !!1;
    __END__
    14೥8݄30೔౔༵೔

    View Slide

  86. QFSMDSJUJD"OUJQPQQN
    14೥8݄30೔౔༵೔

    View Slide

  87. QFSMDSJUJD"OUJQPQQN
    .PEVMFEPFTOPUFOEXJUIBUMJOF DPMVNO
    .VTUFOEXJUIBSFDPHOJ[BCMFUSVFWBMVF
    4FWFSJUZ

    14೥8݄30೔౔༵೔

    View Slide

  88. QFSMDSJUJD"OUJQPQQN
    .PEVMFEPFTOPUFOEXJUIBUMJOF DPMVNO
    .VTUFOEXJUIBSFDPHOJ[BCMFUSVFWBMVF
    4FWFSJUZ

    !!1;
    14೥8݄30೔౔༵೔

    View Slide

  89. 1FSM$SJUJD1PMJDZ.PEVMFT3FRVJSF&OE8JUI0OF
    sub violates {
    my ( $self, $elem, $doc ) = @_;
    # Last statement should be just "1;"
    my @significant = grep { _is_code($_) }
    $doc->schildren();
    my $match = $significant[-1];
    return if !$match;
    return if ((ref $match) eq 'PPI::Statement' &&
    $match =~ m{\A 1 \s* ; \z}xms );
    # Must be a violation...
    return $self->violation( $DESC, $EXPL, $match );
    }
    14೥8݄30೔౔༵೔

    View Slide

  90. ੩తղੳͰ
    ͠ΐ΅͍෺͔Β
    ෳࡶͳ෺·Ͱ
    14೥8݄30೔౔༵೔

    View Slide

  91. ੩తղੳͷ࿩͓ΘΓ
    14೥8݄30೔౔༵೔

    View Slide

  92. ϦϑΝΫλϦϯάπʔϧͷ࿩
    14೥8݄30೔౔༵೔

    View Slide

  93. "QQ135
    14೥8݄30೔౔༵೔

    View Slide

  94. "QQ135
    1FSM
    3FGBDUPSJOH
    5PPM
    14೥8݄30೔౔༵೔

    View Slide

  95. "QQ135
    1FSM
    3FGBDUPSJOH
    5PPM
    ࡞ͬͯ·͢
    14೥8݄30೔౔༵೔

    View Slide

  96. ϦϑΝΫλϦϯά͍ͨ͠ͱ
    ͖ʹ͋ΔΑ͋͘Δૢ࡞Λ·
    ͱΊͨπʔϧ
    14೥8݄30೔౔༵೔

    View Slide

  97. ίϚϯυϥΠϯ͔Β࣮ߦ
    ιʔείʔυॻ͖׵͑ͯอଘ
    14೥8݄30೔౔༵೔

    View Slide

  98. Ͱ͖Δ͜ͱ
    14೥8݄30೔౔༵೔

    View Slide

  99. Ͱ͖Δ͜ͱ
    τʔΫϯͷஔ׵
    ΫϥεͷϦωʔϜ
    ωʔϜεϖʔεͷϦωʔϜ
    ϝιουͷ࡟আ
    ΫϥεϝιουͷҠಈ
    14೥8݄30೔౔༵೔

    View Slide

  100. ࿅श
    14೥8݄30೔౔༵೔

    View Slide

  101. ࿅श༻ʹ༻ҙͨ͠
    ΫιίʔυΛ
    ϦϑΝΫλϦϯά
    ͯ͠Έ·͠ΐ͏
    14೥8݄30೔౔༵೔

    View Slide

  102. ͓Έ͘͡ΞϓϦέʔγϣϯ
    ͷϦϑΝΫλϦϯά
    IUUQTHJUIVCDPNIJUPEFPNJLVKJ
    14೥8݄30೔౔༵೔

    View Slide

  103. QFSMPNJLVKJQM
    த٢
    QFSMPNJLVKJQM
    த٢
    QFSMPNJLVKJQM
    େ٢
    [email protected]
    ޕ
    [email protected]

    14೥8݄30೔౔༵೔

    View Slide

  104. 0NJLVKJ
    VSBOBV
    VSBOBXBOBJ
    0NJLVKJ%PVCVUV
    VSBOBV
    0NJLVKJ6UJM
    DIPJTF
    MVDLZ
    ˚
    ܧঝ
    ར༻
    14೥8݄30೔౔༵೔

    View Slide

  105. VSBOBVϝιουΛ
    ϦωʔϜͯ͠ΈΔ
    prt replace_token
    uranau tell
    14೥8݄30೔౔༵೔

    View Slide

  106. prt replace_token uranau tell
    ίϚϯυ
    αϒίϚϯυ
    Ҿ਺
    14೥8݄30೔౔༵೔

    View Slide

  107. 0NJLVKJ
    UFMM
    VSBOBXBOBJ
    0NJLVKJ%PVCVUV
    UFMM
    0NJLVKJ6UJM
    DIPJTF
    MVDLZ
    ˚
    ܧঝ
    ར༻
    14೥8݄30೔౔༵೔

    View Slide

  108. 0NJLVKJ6UJMMVDLZϝιουΛ
    -VDLZΫϥεʹҠಈͯ͠ΈΔ
    prt move_class_method
    ‘Omikuji::Util#lucky’
    ‘Omikuji::Lucky#get_lucky’
    14೥8݄30೔౔༵೔

    View Slide

  109. 0NJLVKJ
    UFMM
    VSBOBXBOBJ
    0NJLVKJ%PVCVUV
    UFMM
    0NJLVKJ6UJM
    DIPJTF
    ˚
    ܧঝ
    ར༻
    0NJLVKJ-VDLZ
    [email protected]
    14೥8݄30೔౔༵೔

    View Slide

  110. 0NJLVKJ6UJMΫϥεΛ
    0NJLVKJ-JTUΫϥεʹ
    ϦωʔϜ
    prt rename_class
    Omikuji::Util
    Omikuji::List
    14೥8݄30೔౔༵೔

    View Slide

  111. 0NJLVKJ
    UFMM
    VSBOBXBOBJ
    0NJLVKJ%PVCVUV
    UFMM
    0NJLVKJ-JTU
    DIPJTF
    ˚
    ܧঝ
    ར༻
    0NJLVKJ-VDLZ
    [email protected]
    14೥8݄30೔౔༵೔

    View Slide

  112. 0NJLVKJΫϥεΛ
    -PUΫϥεʹϦωʔϜ
    prt rename_class
    Omikuji
    Lot
    14೥8݄30೔౔༵೔

    View Slide

  113. -PU
    UFMM
    VSBOBXBOBJ
    0NJLVKJ%PVCVUV
    UFMM
    0NJLVKJ-JTU
    DIPJTF
    ˚
    ܧঝ
    ར༻
    0NJLVKJ-VDLZ
    [email protected]
    14೥8݄30೔౔༵೔

    View Slide

  114. 0NJLVKJҎԼΛશͯ
    -PUʹϦωʔϜ
    prt rename_name_space
    Omikuji
    Lot
    14೥8݄30೔౔༵೔

    View Slide

  115. -PU
    UFMM
    VSBOBXBOBJ
    -PU%PVCVUV
    UFMM
    -PU-JTU
    DIPJTF
    ˚
    ܧঝ
    ར༻
    -PU-VDLZ
    [email protected]
    14೥8݄30೔౔༵೔

    View Slide

  116. ϦϑΝΫλϦϯά੒ޭ
    14೥8݄30೔౔༵೔

    View Slide

  117. ΋͏ͪΐͬͱ
    େ͖͍ΞϓϦέʔγϣϯͰ
    ࿅श
    14೥8݄30೔౔༵೔

    View Slide

  118. 1MBDL3FRVFTUΛ
    1MBDL,VEBTBJʹ
    14೥8݄30೔౔༵೔

    View Slide

  119. prt rename_class Plack::Request Plack::Kudasai
    14೥8݄30೔౔༵೔

    View Slide

  120. ϦϑΝΫλϦϯά੒ޭ
    14೥8݄30೔౔༵೔

    View Slide

  121. ໊લΛؾܰʹ
    ͋ͱ͔Βม͑ΒΕΔͷ͸
    ศར
    14೥8݄30೔౔༵೔

    View Slide

  122. ϦϥοΫεͰ͖Δ
    14೥8݄30೔౔༵೔

    View Slide

  123. ͏·͘࢖͏ίπ
    14೥8݄30೔౔༵೔

    View Slide

  124. ର৅ϑΝΠϧΛߜΔ
    prt rename_token foo bar $(git grep --name-only foo)
    ର৅ϑΝΠϧ͕ݮΔͱ଎͍ͧ
    14೥8݄30೔౔༵೔

    View Slide

  125. ςετ௨͔ͯ͠Βίϛοτ
    ςετ௨͔ͬͯΒ
    ίϛοτ͢Δͱ҆৺Ͱ͖Δͧ
    14೥8݄30೔౔༵೔

    View Slide

  126. ϦϑΝΫλϦϯά͠΍͘͢อͭ
    ϝλϓϩάϥϛϯάΛආ͚Δ
    จࣈྻ࿈݁ͰQBDLBHF໊࡞Δͱ೉͍͠
    KPJObz b0NJLVKJ` b6UJM`
    14೥8݄30೔౔༵೔

    View Slide

  127. ࣄྫ঺հ
    14೥8݄30೔౔༵೔

    View Slide

  128. ࣄྫ঺հ
    ͸ͯͳϒϩάશࣗಈϦϑΝΫλϦϯά
    14೥8݄30೔౔༵೔

    View Slide

  129. എܠ
    4FSWJDFΫϥεʹ
    DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠
    Service::User->find_user_by_name($r, $name);
    14೥8݄30೔౔༵೔

    View Slide

  130. എܠ
    4FSWJDFΫϥεʹ
    DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠
    EC͚ͩ౉͢ͱ͜Ζ΋
    Service::User->find_user_by_name($r, $name);
    Service::Blog->find_blog_by_uri($r->db, $uri);
    14೥8݄30೔౔༵೔

    View Slide

  131. എܠ
    4FSWJDFΫϥεʹ
    DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠
    EC͚ͩ౉͢ͱ͜Ζ΋
    ౷Ұ͞Εͯͳͯ͘ΧΦε
    ΫϥεɼݸҎ্ͷϝιου
    Service::User->find_user_by_name($c, $name);
    Service::Blog->find_blog_by_uri($c->db, $uri);
    14೥8݄30೔౔༵೔

    View Slide

  132. എܠ
    4FSWJDFΫϥεʹ
    DPOUFYUΦϒδΣΫτΛ౉ͯͨ͠
    EC͚ͩ౉͢ͱ͜Ζ΋
    ౷Ұ͞Εͯͳͯ͘ΧΦε
    ΫϥεɼݸҎ্ͷϝιου
    खͰͪ·ͪ·௚ͦ͏ͱ͢Δ΋࠳ં
    Service::User->find_user_by_name($c, $name);
    Service::Blog->find_blog_by_uri($c->db, $uri);
    14೥8݄30೔౔༵೔

    View Slide

  133. શࣗಈνϟϯε
    14೥8݄30೔౔༵೔

    View Slide

  134. ΍Γ͍ͨ͜ͱ
    14೥8݄30೔౔༵೔

    View Slide

  135. Service::User->find_user_by_name($r, $name);
    sub find_user_by_name {
    my ($class, $r, $name) = @_;
    $r->db->select(..., $name);
    }
    CFGPSF
    14೥8݄30೔౔༵೔

    View Slide

  136. Service::User->find_user_by_name($r->db, $name);
    sub find_user_by_name {
    my ($class, $db, $name) = @_;
    $db->select(..., $name);
    }
    BGUFS
    14೥8݄30೔౔༵೔

    View Slide

  137. ࡞ઓ
    14೥8݄30೔౔༵೔

    View Slide

  138. Service::User->find_user_by_name($r->db, $name);
    sub find_user_by_name {
    my ($class, $db, $name) = @_;
    $db->select(..., $name);
    }
    ݺͼग़͠ݩͰ $r → $r->db
    ݺͼग़͠ઌͰ $r → $db
    $r->db → $db
    14೥8݄30೔౔༵೔

    View Slide

  139. ॻ͖׵͑ͯ͸͍͚ͳ͍৔߹
    14೥8݄30೔౔༵೔

    View Slide

  140. sub aaa {
    my ($class, $r = @_;
    AnotherService->bbb($r);
    $r->db->select(..., $user->name);
    }
    ΄͔ͷϝιουʹS౉ͯ͠Δ
    14೥8݄30೔౔༵೔

    View Slide

  141. sub aaa {
    my ($class, $r) = @_;
    AnotherService->bbb($r->db);
    $r->db->select(..., $user->name);
    }
    ΄͔ͷϝιουʹS౉ͯ͠Δ
    ઌʹ"OPUIFS4FSWJDFΛ
    ϦϑΝΫλϦϯά
    14೥8݄30೔౔༵೔

    View Slide

  142. sub aaa {
    my ($class, $db) = @_;
    AnotherService->bbb($db);
    $db->select(..., $user->name);
    }
    ΄͔ͷϝιουʹS౉ͯ͠Δ
    ઌʹ"OPUIFS4FSWJDFΛ
    ϦϑΝΫλϦϯά
    ϝιου಺͕શͯSECͳΒॻ͖׵͑ΒΕΔ
    14೥8݄30೔౔༵೔

    View Slide

  143. sub aaa {
    my ($class, $r) = @_;
    my $user = $r->user;
    $r->db->select(..., $user->name);
    }
    ECҎ֎΋࢖ͬͯΔ
    14೥8݄30೔౔༵೔

    View Slide

  144. sub aaa {
    my ($class, $r, $user) = @_;
    $r->db->select(..., $user->name);
    }
    ECҎ֎΋࢖ͬͯΔ
    VTFS΋ड͚औΔ
    ͜Ε͸ػցతʹ͸Ͱ͖ͳ͍ͷͰख࡞ۀ
    14೥8݄30೔౔༵೔

    View Slide

  145. ࡞ઓ
    wιʔείʔυશϑΝΠϧॱ൪ʹݟΔ
    wSΛड͚औͬͯΔϝιουΛ୳͢
    w҆શʹॻ͖׵͑ΒΕΔ
    wϝιουఆٛΛॻ͖׵͑ˠݺͼग़͠ݩ΋ॻ͖׵͑
    wมߋՕॴͷςετ࣮ߦ
    w௨ͬͨΒDPNNJUQVTIͯ͠࠷ॳʹ໭Δ
    wམͪͨΒεΫϦϓτऴྃͯ͠ਓؒΛݺͿ
    w҆શ͡Όͳ͔ͬͨΒ࣍ͷϝιουʹߦ͘
    wԿ΋ॻ͖׵͑ͣશϑΝΠϧݟऴΘͬͨΒਓؒΛݺͿ
    14೥8݄30೔౔༵೔

    View Slide

  146. ݟͲ͜Ζ
    14೥8݄30೔౔༵೔

    View Slide

  147. ࢦఆ͞ΕͨϑΝΠϧ
    ॱ൪ʹݟΔ
    sub replace_all {
    for my $file (@ARGV) {
    my $document = PPI::Document->new($file);
    my $package = $document->find_first(
    'PPI::Statement::Package'
    );
    my $package_name = $package->namespace;
    my $methods = $document->find(
    'PPI::Statement::Sub'
    );
    for my $method (@$methods) {
    my $document = PPI::Document->new($file);
    ...;
    }
    }
    }
    14೥8݄30೔౔༵೔

    View Slide

  148. SECΛECʹஔ׵
    sub r_db_to_db {
    my ($statement) = @_;
    my $tokens = [$statement->children];
    for my $token (@$tokens) {
    if ($token eq '$r') {
    if ($token->next_token eq '->') {
    if ($token->next_token->next_token eq 'db') {
    $token->set_content('$db');
    $token->next_token->set_content('');
    $token->next_token->next_token->set_content('');
    } else {
    die "->@{[ $token->next_token->next_token ]}";
    }
    } else {
    die "@{[ $token->next_token ]}";
    }
    }
    }
    }
    14೥8݄30೔౔༵೔

    View Slide

  149. ݺͼग़͠ݩͷมߋ
    $command = 'prt replace_token \'' .
    $package_name . '->' . $method_name .
    '($r\' \'' . $package_name . '->' .
    $method_name . '($r->db\' --in-
    statement ' . $method_name . ' $(git
    grep --name-only ' . $method_name .
    ')';
    system $command;
    14೥8݄30೔౔༵೔

    View Slide

  150. Ϋϥε಺Ͱͷݺͼग़͠มߋ
    $command = 'prt replace_token
    \'$class' . '->' .
    $method_name . '($r\'
    \'$class' . '->' .
    $method_name . '($r->db\' --in-
    statement ' . $method_name . '
    ' . $file;
    system $command;
    14೥8݄30೔౔༵೔

    View Slide

  151. มߋՕॴΛςετͯ͠ίϛοτ
    if (`git diff --name-only t/**.t`) {
    system('carton exec -- prove $(git diff --
    name-only t/**.t)') and die "test failed";
    } else {
    warn 'skip test';
    }
    system "git commit -am '$package_name\ͷ
    $method_name\Λ\$db Λड͚औΔΑ͏ʹมߋ'";
    system "git push";
    14೥8݄30೔౔༵೔

    View Slide

  152. ॻ͖׵͑ଓ͚Δ
    my $success = 1;
    while($success) {
    $success = replace_all();
    }
    14೥8݄30೔౔༵೔

    View Slide

  153. ൒೔ޙ
    14೥8݄30೔౔༵೔

    View Slide

  154. 250+ Commits
    281 Files changed
    +2,004 −1,927
    14೥8݄30೔౔༵೔

    View Slide

  155. ϦϑΝΫλϦϯά੒ޭ
    14೥8݄30೔౔༵೔

    View Slide

  156. ஌ݟ
    14೥8݄30೔౔༵೔

    View Slide

  157. ஌ݟ
    ҙ֎ͱͳΜͱ͔ͳΔ
    14೥8݄30೔౔༵೔

    View Slide

  158. ஌ݟ
    ҙ֎ͱͳΜͱ͔ͳΔ
    ϨϏϡϫʔ͔Θ͍ͦ͏
    14೥8݄30೔౔༵೔

    View Slide

  159. ஌ݟ
    ҙ֎ͱͳΜͱ͔ͳΔ
    ϨϏϡϫʔ͔Θ͍ͦ͏
    ௕೥ͷٕज़తෛ࠴Λٕज़Ͱղܾͨ͠
    14೥8݄30೔౔༵೔

    View Slide

  160. Ҏ্
    14೥8݄30೔౔༵೔

    View Slide

  161. ·ͱΊ
    ϦϑΝΫλϦϯάʹ͍ͭͯ
    1FSMͷϦϑΝΫλϦϯά
    ੩తղੳೖ໳
    ੩తղੳ࿅श
    ϦϑΝΫλϦϯάπʔϧͷ঺հ
    ϦϑΝΫλϦϯά࿅श
    ࣄྫ঺հ
    14೥8݄30೔౔༵೔

    View Slide

  162. ׬
    14೥8݄30೔౔༵೔

    View Slide

  163. ҰॹʹϦϑΝΫλϦϯά͠·͠ΐ͏
    ʲॕʳTPOHNV͞Μೖࣾ
    14೥8݄30೔౔༵೔

    View Slide