入れ子構造を分解するPerl Beginners #5 LT
高橋メソッド大好きな  ytnobodyが
高橋メソッドでお送りします。
さて
こういうコードに出くわしたことは
ありませんか?
sub register {  my ( $name, $mail ) = @_;  if ( $name ) {      if ( length $name > 1 ) {          if ( length $name <= 12 ...
読む気が失せましたよね
コード内の入れ子構造(ネスト)が     多すぎる
まずロジックを整理。
やりたいこと
$mailは$nameがない旨                 メアドとして       $mailがメアドでは を警告し終了      $nameがある                  ない旨を警告し終了                  ...
だいぶ煩雑
シンプルにできないか。
条件を統合・省略してみよう
$nameが       $nameが短すぎる1文字~12文字        旨を警告し終了   $mailは      $mailがメアドでは  メアドとして       ない旨を警告し終了    正しい$nameと$mailを名前とメアドと...
コードに起こしてみる
sub register {  my ( $name, $mail ) = @_;  if ( length $name > 1 && length $name <= 12 ) {  }  else {     die “name is 1 t...
多少マシになった
でもまだ荒い。
条件に合致しなかったときにだけ    エラーを吐こう
sub register {  my ( $name, $mail ) = @_;  unless ( length $name > 1 && length $name <= 12 ) {     die “name is 1 to 12 ch...
まあまあよくなった
でもまだ問題が。
例えば、$nameのチェック部分や   $mailのチェック部分
ほかの場所でも同じような チェックをする場合
どうする・・・
チェック部分を別の関数として切り出そう
sub validate_name {  my $name = shift;  return length $name > 1 && length $name <= 12 ;}sub validate_mail {  my $mail = sh...
一見冗長
だけど、validate_name() やvalidate_mail() を呼ぶだけでチェックができるようになった
でも冗長
後置条件にしてみる
sub validate_name {  my $name = shift;  return length $name > 1 && length $name <= 12 ;}sub validate_mail {  my $mail = sh...
ちょっとスッキリした。
dieとか毎回書くの億劫
チェック側にdieもやらせよう
sub validate_name {  my $name = shift;  die “name is 1 to 12 characters longer” unless     length $name > 1 && length $nam...
さらに$nameのチェックと$mailのチェックを   まとめる
sub validate_name {  my $name = shift;  die “name is 1 to 12 characters longer” unless     length $name > 1 && length $nam...
ほかの場所からでも$validateを呼ぶだけで  $nameと$mailを   チェックできる
うわあ!仕様変更だ!
単純にprintしていただけの箇所をDB登録するようにしろ、だって?!
よし!
その部分をほかのヤツに   やらせよう
そのためにprintしているところは 関数にしておこう
sub validate_name {  my $name = shift;  die “name is 1 to 12 characters longer” unless     length $name > 1 && length $nam...
まとめ
何が言いたかったのか●   関数内の入れ子(ネスト)が深くなったなら、それは    よくない。    ●        入れ子の部分を別の関数に切り出そう        –   でかい関数1個よりも、小さい関数の組み合わせで。        –...
何が言いたかったのか●   関数内の行数が長くなってきたら、それはよくな    い。    ●        入れ子になって無くても、大抵は別の関数として切り出        せる場所がある。        –   関数内のコードが10行超えた...
何が言いたかったのか●   関数の処理を、簡単な関数名で表現できないのは    よくない。    ●        大体関数内のコードが長い場合に起こる。        –   どこか切り出すべき処理があるはず。
何が言いたかったのか●   小さい関数に切り出すことで、仕様変更に強くな    れ!    ●        使いまわしがきくようになる    ●   テストもしやすい
ありがとうございました
Upcoming SlideShare
Loading in …5
×

入れ子構造を分解する

1,264 views

Published on

入れ子構造を分解する

  • Be the first to comment

  • Be the first to like this

入れ子構造を分解する

  1. 1. 入れ子構造を分解するPerl Beginners #5 LT
  2. 2. 高橋メソッド大好きな ytnobodyが
  3. 3. 高橋メソッドでお送りします。
  4. 4. さて
  5. 5. こういうコードに出くわしたことは
  6. 6. ありませんか?
  7. 7. sub register { my ( $name, $mail ) = @_; if ( $name ) { if ( length $name > 1 ) { if ( length $name <= 12 ) { } else { die “name is too long”; } } else { die “name is too short”; } } else { die “name is required”; } if ( $mail ) { if ( $mail =~ /^.+@.+..+$/ ) { } else { die “specified mail is not legal”; } } else { die “mail is required”; } if ( $name && $mail ) { print “name: $namenmail: $mailn”; }}
  8. 8. 読む気が失せましたよね
  9. 9. コード内の入れ子構造(ネスト)が 多すぎる
  10. 10. まずロジックを整理。
  11. 11. やりたいこと
  12. 12. $mailは$nameがない旨 メアドとして $mailがメアドでは を警告し終了 $nameがある ない旨を警告し終了 正しい$nameが短すぎる $nameが $nameと$mailを 旨を警告し終了 1文字より長い 名前とメアドとして 出力する$nameが長すぎる $nameが 旨を警告し終了 12文字以内$mailがない旨 $mailがある を警告し終了
  13. 13. だいぶ煩雑
  14. 14. シンプルにできないか。
  15. 15. 条件を統合・省略してみよう
  16. 16. $nameが $nameが短すぎる1文字~12文字 旨を警告し終了 $mailは $mailがメアドでは メアドとして ない旨を警告し終了 正しい$nameと$mailを名前とメアドとして 出力する
  17. 17. コードに起こしてみる
  18. 18. sub register { my ( $name, $mail ) = @_; if ( length $name > 1 && length $name <= 12 ) { } else { die “name is 1 to 12 characters longer”; } if ( $mail =~ /^.+@.+..+$/ ) { } else { die “specified mail is not legal”; } print “name: $namenmail: $mailn”;}
  19. 19. 多少マシになった
  20. 20. でもまだ荒い。
  21. 21. 条件に合致しなかったときにだけ エラーを吐こう
  22. 22. sub register { my ( $name, $mail ) = @_; unless ( length $name > 1 && length $name <= 12 ) { die “name is 1 to 12 characters longer”; } unless ( $mail =~ /^.+@.+..+$/ ) { die “specified mail is not legal”; } print “name: $namenmail: $mailn”;}
  23. 23. まあまあよくなった
  24. 24. でもまだ問題が。
  25. 25. 例えば、$nameのチェック部分や $mailのチェック部分
  26. 26. ほかの場所でも同じような チェックをする場合
  27. 27. どうする・・・
  28. 28. チェック部分を別の関数として切り出そう
  29. 29. sub validate_name { my $name = shift; return length $name > 1 && length $name <= 12 ;}sub validate_mail { my $mail = shift; return $mail =~ /^.+@.+..+$/;}sub register { my ( $name, $mail ) = @_; unless ( validate_name( $name ) ) { die “name is 1 to 12 characters longer”; } unless ( validate_mail( $mail ) ) { die “specified mail is not legal”; } print “name: $namenmail: $mailn”;}
  30. 30. 一見冗長
  31. 31. だけど、validate_name() やvalidate_mail() を呼ぶだけでチェックができるようになった
  32. 32. でも冗長
  33. 33. 後置条件にしてみる
  34. 34. sub validate_name { my $name = shift; return length $name > 1 && length $name <= 12 ;}sub validate_mail { my $mail = shift; return $mail =~ /^.+@.+..+$/;}sub register { my ( $name, $mail ) = @_; die “name is 1 to 12 characters longer” unless validate_name( $name ); die “specified mail is not legal” unless validate_mail( $mail ); print “name: $namenmail: $mailn”;}
  35. 35. ちょっとスッキリした。
  36. 36. dieとか毎回書くの億劫
  37. 37. チェック側にdieもやらせよう
  38. 38. sub validate_name { my $name = shift; die “name is 1 to 12 characters longer” unless length $name > 1 && length $name <= 12 ;}sub validate_mail { my $mail = shift; die “specified mail is not legal” unless $mail =~ /^.+@.+..+$/ ;}sub register { my ( $name, $mail ) = @_; validate_name( $name ); validate_mail( $mail ); print “name: $namenmail: $mailn”;}
  39. 39. さらに$nameのチェックと$mailのチェックを まとめる
  40. 40. sub validate_name { my $name = shift; die “name is 1 to 12 characters longer” unless length $name > 1 && length $name <= 12 ;}sub validate_mail { my $mail = shift; die “specified mail is not legal” unless $mail =~ /^.+@.+..+$/ ;}sub validate { my ( $mail, $name ); validate_name( $name ); validate_mail( $mail );}sub register { my ( $name, $mail ) = @_; validate( $name, $mail ); print “name: $namenmail: $mailn”;}
  41. 41. ほかの場所からでも$validateを呼ぶだけで $nameと$mailを チェックできる
  42. 42. うわあ!仕様変更だ!
  43. 43. 単純にprintしていただけの箇所をDB登録するようにしろ、だって?!
  44. 44. よし!
  45. 45. その部分をほかのヤツに やらせよう
  46. 46. そのためにprintしているところは 関数にしておこう
  47. 47. sub validate_name { my $name = shift; die “name is 1 to 12 characters longer” unless length $name > 1 && length $name <= 12 ;}sub validate_mail { my $mail = shift; die “specified mail is not legal” unless $mail =~ /^.+@.+..+$/ ;}sub validate { my ( $mail, $name ); validate_name( $name ); validate_mail( $mail );}sub register { my ( $name, $mail ) = @_; validate( $name, $mail ); insert_to_db( $name, $mail );}sub insert_to_db { print “name: $namenmail: $mailn”; ### ここにDBへの登録ロジックを書いてくれたまえ!}
  48. 48. まとめ
  49. 49. 何が言いたかったのか● 関数内の入れ子(ネスト)が深くなったなら、それは よくない。 ● 入れ子の部分を別の関数に切り出そう – でかい関数1個よりも、小さい関数の組み合わせで。 – 入れ子が3階層になったら、ちょっとヤバ目。 ● 人によっては2階層で、という方も居るし、共感できます。 ● まとめれるif文はどんどんまとめよう
  50. 50. 何が言いたかったのか● 関数内の行数が長くなってきたら、それはよくな い。 ● 入れ子になって無くても、大抵は別の関数として切り出 せる場所がある。 – 関数内のコードが10行超えたら、個人的にはちょっとよくない と思い始める。 ● でも仕事のコードで10行超えの関数がちょいちょいある。 ● 自戒。
  51. 51. 何が言いたかったのか● 関数の処理を、簡単な関数名で表現できないのは よくない。 ● 大体関数内のコードが長い場合に起こる。 – どこか切り出すべき処理があるはず。
  52. 52. 何が言いたかったのか● 小さい関数に切り出すことで、仕様変更に強くな れ! ● 使いまわしがきくようになる ● テストもしやすい
  53. 53. ありがとうございました

×