― Web Technology and Life ―

Perlで生でrand関数をごちゃごちゃ使うコードはもう嫌だ

2011-12-25
Hachioji.pm#12で発表したネタです。Data::WeightedRoundRobin使ったら、rand使うようなコードが、いい感じにすっきり見やすくかけましたよーという話です。

嫌なコードの概要

要件

「以下のような感じで、実行する処理をランダムで変更してよ!」って要件がたまにありますね。

  • 3割の確率でhogeを実行
  • 3割の確率でmogeを実行
  • 2割の確率でfooを実行
  • 1割の確率でbarを実行
  • 1割の確率でjarを実行

ファクトリーメソッドパターン的な実装ですね。

ごにょごにょするとこんな感じの実装に

my $rand = rand();

my $method;
if($rand < 0.3){
    $method = 'hoge';#3割
}elsif($rand >= 0.3 && $rand < 0.6){
    $method = 'moge';#3割
}elsif($rand >= 0.6 && $rand < 0.8){
    $method = 'foo';#2割
}elsif($rand >= 0.8 && $rand < 0.9){
    $method = 'bar';#1割
}elsif($rand >= 0.9){
    $method = 'jar';#1割
}

my $value = $method($args);

嫌なところ

  • なんかぱっとみわかりづらいから、割合をコメントで書く
  • なんかrandとかカッコ悪い
  • なんか条件の比較文でミスってそう

とにかく、プログラムッチクというとなにかとランダムという要件が多いし、こんなコードばかりグチャグチャ書くのはもういやですね。

解決方法の発見

私は自宅でHokkaido.pm#06のUstを見ていたときのことです、そのとき、Data::WeightedRoundRobinなるモジュールが紹介されていたのでした!!!
いわく、
「重み付けされた値をベストエフォートな感じでラウンドロビンしてくれるモジュール」

というのを、Hachioji.pm#12に行く電車の中で思い出したのです。
「あれ?なんかこれ使えば、あのださいコードかっこ良くなるんじゃない?」というように。

Data::WeightedRoundRobinを使った解決コード

use Data::WeightedRoundRobin;

my $wrr = Data::WeightedRoundRobin->new([
    { value => 'hoge', weight => 30 },
    { value => 'moge', weight => 30 },
    { value => 'foo',  weight => 20 },
    { value => 'bar',  weight => 10 },
    { value => 'jar',  weight => 10 },
]);

my $method = $wrr->next;

my $value = $method($args);

今回のケースに合わせてよりシンプルにしたコード

use Data::WeightedRoundRobin;

my $method = Data::WeightedRoundRobin->new([
    { value => 'hoge', weight => 30 },
    { value => 'moge', weight => 30 },
    { value => 'foo',  weight => 20 },
    { value => 'bar',  weight => 10 },
    { value => 'jar',  weight => 10 },
])->next;

my $value = $method($args);

感想

Data::WeightedRoundRobin使うと、マジでみやすいですねー。

  • コメントいらない
  • ifのわけわからない条件文でバグることない
  • 行数少ない

という感じで、今後も使っていきます!

Perl hachioji.pm update_at : 2011-12-25T15:02:29
hirobanex.netの更新情報の取得
 RSSリーダーで購読する   
blog comments powered by Disqus