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

モダンPerlリファクタリング #yapcasia

B4afc7d853d7f1cb6a253d3c7183c05a?s=47 Naoya Ito
September 20, 2013

モダンPerlリファクタリング #yapcasia

YAPC Asia 2013

B4afc7d853d7f1cb6a253d3c7183c05a?s=128

Naoya Ito

September 20, 2013
Tweet

Transcript

  1. Ϟμϯ1FSMϦϑΝΫλϦϯά !OBPZB@JUP

  2. None
  3. .BSLEPXO5P*OBP NEJOBP 

  4. #  Hello,  World     *  list  1   *

     list  2 ▪Hello,  World   ・list  1   ・list  2
  5. None
  6. ߏ଄తʹػೳΛ͚ͭՃ͑ʹ͍͘ϓϩ άϥϜʹ৽نػೳΛ௥Ճ͠ͳ͚Ε͹ͳ Βͳ͍৔߹ʹ͸ɺ·ͣػೳ௥Ճ͕؆୯ ʹͳΔΑ͏ʹϦϑΝΫλϦϯάΛͯ͠ ͔Β௥ՃΛߦ͏͜ͱɻ 1  ʰϦϑΝΫλϦϯάϓϩάϥϛϯάͷମ࣭վળςΫχοΫʱ ϚʔνϯɾϑΝ΢ϥʔ

  7. "'5&3 package  Text::Md2Inao::Builder::Inao;   use  parent  qw/Text::Md2Inao::Builder/;   use  Text::Md2Inao::Builder::DSL;

        case  default  =>  sub  {          my  ($c,  $h)  =  @_;          fallback_to_html($h);   };     case  a  =>  sub  {          my  ($c,  $h)  =  @_;          my  $url      =  $h-­‐>attr('href');          my  $title  =  $h-­‐>as_trimmed_text;          if  ($url  and  $title)  {                  return  sprintf  "%s◆注/◆%s◆/注◆",  $title,  $url;          }  else  {                  return  fallback_to_html($h);          }   };     ...  
  8. લఏ

  9. ಓ۩ •  $BSUPO DQBOpMF •  (JUIVC •  ςετ •  $*ɺ(VBSE

  10. ϦϑΝΫλϦϯάͷྲྀΕ •  Լ४උ –  σΟϨΫτϦΛ੔͑ͯ(JUIVCʹ –  $1"/Ϟδϡʔϧચ͍ग़͠ •  શମΛϞδϡʔϧԽͯ͠"1*ఆٛ • 

    &OEUP&OEͷςετ •  ҎԼ܁Γฦ͠ –  ࡉ͔͍ςετ –  ϦϑΝΫλϦϯά •  ճؼςετΛཷΊΔ
  11. Լ४උ

  12. σΟϨΫτϦΛ੔͑ͯ(JUIVC΁ •  $1"/Ϟδϡʔϧͱಉ͡σΟϨΫτϦϨΠ Ξ΢τʹ͢Δ – ֤छπʔϧͷԸܙʹ༩Δ •  QSPWFɺ$BSUPOɺ(VBSEɺ5SBWJT$*

  13. None
  14. $1"/Ϟδϡʔϧચ͍ग़͠ •  $BSUPO DQBOpMF •  ΑΓϙʔλϒϧʹ #  cpanfile   requires

     'Text::Markdown';   requires  'HTML::TreeBuilder';   requires  'Unicode::EastAsianWidth';   requires  'Pod::Usage';   ...  
  15. DBSUPOFYFD %  carton  install   %  carton  exec  perl  bin/md2inao.pl

      •  ϥΠϒϥϦΛϩʔΧϧύεલఏʹ ີ෧ػೳ  –  ʮଞͰೖΕͨϞδϡʔϧͰಈ͍ͯͨʯΛճආ •  ґଘϞδϡʔϧͷόʔδϣϯΛݫີʹݻఆ DBSUPOFYFD͠ͳ͕Β଍Γͳ͍ϞδϡʔϧΛ DQBOpMFʹ௥ه˰͋ΒෆࢥٞɺϞδϡʔϧҰཡ ͷͰ͖͕͋Γ
  16. ͍͟ϦϑΝΫλϦϯά

  17. શମΛͻͱͭͷϞδϡʔϧʹ my  $inao  =  Text::Md2Inao-­‐>new({      default_list    

                     =>  'disc',      max_list_length                =>  63,      max_inline_list_length  =>  55,   });     print  $inao-­‐>parse($markdown)  
  18. package  Text::Md2Inao;     sub  parse  {      my

     $markdown  =  shift;      ...      return  $inao;   }   ·ͣ͸ͬ͘͟Γ෴͏
  19. ςετ͕ॻ͚Δ use  Test::More;     my  $inao  =  Text::Md2Inao-­‐>new  

    my  $out  =  $inao-­‐>parse("#  Hello,  World");   is  $out,  "▪Hello,  World";     done_testing;  
  20. %  carton  exec  -­‐Ilib  -­‐-­‐  prove  t/01_api.t   t/01_api.t  ..

     ok   All  tests  successful.   Files=1,  Tests=1,    0  wallclock  secs  (  0.02  usr     0.00  sys  +    0.09  cusr    0.00  csys  =    0.11  CPU)   Result:  PASS  
  21. ϦϑΝΫλϦϯάΛ։࢝͢Δͱ͖ɺ ࠷ॳʹ͢Δ͜ͱ͸ৗʹಉ͡Ͱ͢ɻର৅ ͱͳΔίʔυʹ͍͖ͭͯͪΜͱͨ͠ς ετ܈Λ࡞Γ্͛Δ͜ͱͰ͢ 1  ʰϦϑΝΫλϦϯάϓϩάϥϛϯάͷମ࣭վળςΫχοΫʱ ϚʔνϯɾϑΝ΢ϥʔ

  22. جຊઓུ •  ࣮ߦ؀ڥͱΞϓϦέʔγϣϯΛ෼཭͢Δ – $6*ͳΒ45%*/45%065ͷ*0 – 8FCΞϓϦͳΒ)551αʔόʔ  •  ෼཭ͨ͠ΞϓϦέʔγϣϯଆͷҰ൪େ͖ ͳ"1*ͷςετΛॻ͘ – ͜Ε͕&OEUP&OEͷςετ

  23. &OEUP&OEͷςετ͔Β࢝ΊΔ •  ·ͣ͸֎ଆͷʮৼΔ෣͍ʯΛอূ – ͦͷͨΊͷ֎෦"1*ͬ͘͟ΓϞδϡʔϧԽ

  24. ϦϑΝΫλϦϯά ໊ࢺ ֎෦͔Β ݟͨͱ͖ͷৼΔ෣͍Λอͪͭͭɺཧղ ΍मਖ਼͕؆୯ʹͳΔΑ͏ʹɺιϑτ ΢ΣΞͷ಺෦ߏ଄ΛมԽͤ͞Δ͜ ͱɻ 1  ʰϦϑΝΫλϦϯάϓϩάϥϛϯάͷମ࣭վળςΫχοΫʱ

    ϚʔνϯɾϑΝ΢ϥʔ
  25. NEJOBPͰ͸5FTU#BTF use  Test::Base;     use  Text::Md2Inao;     plan

     tests  =>  1  *  blocks;     run_is  in  =>  'expected';     sub  md2inao  {  Text::Md2Inao-­‐>new-­‐>parse($_)  }     __END__   ===   -­‐-­‐-­‐  in  md2inao   #  見出し1(大見出し、節)     -­‐-­‐-­‐  expected   ▪見出し1(大見出し、節)     ===   -­‐-­‐-­‐  in  md2inao   ##  見出し2(中見出し、項)     -­‐-­‐-­‐  expected   ▪▪見出し2(中見出し、項)  
  26. 8FCΞϓϦέʔγϣϯͷ৔߹ •  1MBDLԽͯ͠1MBDL5FTUͳͲ use  Test::More;   use  Plack::Test;    

    ...     #  $app  :  PSGI  application   test_psgi  $app,  sub  {        like  shift-­‐>(GET  "/amazlet/")-­‐>content,  qr/<!-­‐-­‐  locale:  jp  -­‐-­‐>/     };  
  27. $(*ͳΜͰ͚͢Ͳŋŋŋ •  1MBDL"QQ8SBQ$(*Ͱ1MBDLԽ͢Δ use  Plack::Builder;   use  Plack::App::WrapCGI;    

    builder  {      mount  "/cgi-­‐bin/amazlet.cgi"  =>  Plack::App::WrapCGI-­‐>new(          script  =>  './htdocs/amazlet.cgi',  execute  =>  1      )-­‐>to_app;   };  
  28. ࣮ߦ؀ڥ͕ີ݁߹ͨ͠ ಠࣗ'8ͳΜͰ͚͢Ͳŋŋŋ •  IFBEMFTTϒϥ΢βͰ&&ςετ͢Δ – DBQZCBSBXFCLJU IFBEMFTTͱ͔  – ͦͷޙɺ1MBDLԽͯ͠'8Λ෼཭ 3VCZ͚ͩͲͳ

  29. ͋ͱ͸ɺҎԼ܁Γฦ͠ •  ΑΓཻ౓ͷࡉ͔͍ςετΛ௥Ճ – ࡉ͔͍σʔλͰͷ&OEUP&OE – ಺෦ϞδϡʔϧͷϢχοτςετ •  ϦϑΝΫλϦϯάΛਐΊΔ ςετ͑͋͞Ε͹ɺͲΜͳʹϨΨ γʔͰ΋ϦϑΝΫλϦϯά͸೉͘͠ ͳ͍ɻ

  30. όάϨϙʔτΛड͚औͬͨΒɺ·ͣ ͦͷόάΛ໌Β͔ʹ͢ΔͨΊͷ୯ମς ετΛॻ͚ɻ 1  ʰϦϑΝΫλϦϯάϓϩάϥϛϯάͷମ࣭վળςΫχοΫʱ ϚʔνϯɾϑΝ΢ϥʔ

  31. ճؼςετΛཷΊࠐΉ %  ls  t/99_rt_*  |  cat   t/99_rt_blockquote_id.t   t/99_rt_bold.t

      t/99_rt_indent.t   t/99_rt_list.t   t/99_rt_list_id.t   t/99_rt_list_in_column.t   t/99_rt_nested_parentheses.t   t/99_rt_paragraph.t   t/99_rt_quotes.t   t/99_rt_ruby_in_footnote.t   t/99_rt_table_indent.t   ...   •  όάൃݟˠճؼςετॻ͘ˠςετ௨͢
  32. ίπ

  33. ςετ͸͜·Ίʹճͦ͏

  34. ςετΛසൟʹͤΑɻίϯύΠϧ࣌ ʹ͸ςετΛہॴԽͯ͠ɺ೔ʹ࠷௿ ౓͸͢΂ͯͷςετΛ࣮ߦͤ Αɻ 1  ʰϦϑΝΫλϦϯάϓϩάϥϛϯάͷମ࣭վળςΫχοΫʱ ϚʔνϯɾϑΝ΢ϥʔ

  35. ܧଓతΠϯςάϨʔγϣϯ 5SBWJT$*

  36. (VBSE HVBSEUBQ h"p://hitode909.hatenablog.com/entry/2013/05/11/190623

  37. ςετ͸ແཧͤͣ ʮ΄Ͳ΄Ͳʯఔ౓ʹ

  38. ෆ׬શͳςετͰ΋ɺॻ͍࣮ͯߦ͢ Δํ͕ɺ࣮ߦͰ͖ͳ͍׬શͳςετ ΑΓ΋·ͩ͠ɻ 1  ʰϦϑΝΫλϦϯάϓϩάϥϛϯάͷମ࣭վળςΫχοΫʱ ϚʔνϯɾϑΝ΢ϥʔ

  39. %))΋͜͏ݴ͍ͬͯΔ •  ʮΧόϨοδ͸Λ໨ࢦ͞ͳ͍ʯ •  ʮ࡞ۀͷ൒෼Ҏ্͕ςετɺ͸͓͔͍͠ʯ •  ʮςετϑΝʔετʹͩ͜ΘΒͳ͍ʯ – ͕ςετϑΝʔετͰ͕ςετΞ ϑλʔ h"p://37signals.com/svn/posts/3159-­‐tes@ng-­‐like-­‐the-­‐tsa

  40. ςετ͸ɺ͍͍ͩͨͰɻ Ͱ΋සൟʹ࣮ߦ •  ·ͣ͸ϦϑΝΫλϦϯά͕ා͘ͳ͍ఔ౓ʹς ετ͕͋Ε͹͍͍ –  ϦϑΝΫλϦϯά͕ਐΉͱςετ͕ॻ͖΍͘͢ –  ࣗવͱΧόϨοδ͸্͕Δ • 

    ϦϑΝΫλϦϯάதʹݟ͚ͭͨόάͷճؼς ετΛཷΊΑ͏ –  ࣗવͱݎ࿚ʹͳ͍ͬͯ͘ •  ࡞ͬͨςετ͸ͪΐͬͱߋ৽ͷ౓ɺසൟʹ࣮ ߦ͠Α͏
  41. (PPE+PC package  Text::Md2Inao::Builder::Inao;   use  parent  qw/Text::Md2Inao::Builder/;   use  Text::Md2Inao::Builder::DSL;

        case  default  =>  sub  {          my  ($c,  $h)  =  @_;          fallback_to_html($h);   };     case  a  =>  sub  {          my  ($c,  $h)  =  @_;          my  $url      =  $h-­‐>attr('href');          my  $title  =  $h-­‐>as_trimmed_text;          if  ($url  and  $title)  {                  return  sprintf  "%s◆注/◆%s◆/注◆",  $title,  $url;          }  else  {                  return  fallback_to_html($h);          }   };     ...