今日見たコード。(単語は適当に無難なものに差し替えた)
def func(filename)
category="(cat1|cat2)"
ver2="(\d+)\.(\d+)"
ver3="(\d+)\.(\d+)\.(\d+)"
targz="\.tar\.gz"
case filename
when /pfxTypeA-#{category}-(.*)-#{ver3}-(.*)#{targz}/
[ :TypeA, Regexp.last_match[1], Regexp.last_match[6],
Regexp.last_match[3],
Regexp.last_match[4],
Regexp.last_match[5], ]
when /pfxTypeB-#{category}-(.*)-#{ver3}-(.*)#{targz}/
[ :TypeB, Regexp.last_match[1], Regexp.last_match[6],
Regexp.last_match[3],
Regexp.last_match[4],
Regexp.last_match[5], ]
when /pfxTypeC-#{ver2}-(.*)#{targz}/
# 以下略
end
end
特定のフォーマットにしたがって命名されたファイル名を要素毎に分解するrubyのコードだけど、最初のwhen節を読み終わるまでに視線がが上下に2,3往復、キャプチャの括弧と後方参照の対応を指差し確認すること2回程。いやはや読みづらい。
読みづらい以外にいくつか問題もある。(正常には動いているのでバグではないのだけど)
- 正規表現の部品が文字列 -> 文法エラーが入り込むと正規表現文字列として展開・処理されるまでエラーがわからない.
- -> 部品も正規表現オブジェクトにすべき
- 正規表現の部品にも展開先の正規表現文字列にもキャプチャ付き括弧が入っているため、括弧と後方参照の番号の対応を確認するのがめんどくさい
- -> なるべく部品にキャプチャ付き括弧は使用しない
- ファイル名の検査なので、無駄な処理を避けるためにも
\A, \Zを使用すべき(ひょっとするとディレクトリ付きで入ってくるかもしれないので、せめて\Zだけでも) - 正規表現に表れない仕様
- 実は
(.*)の部分は、空文字にマッチか'-'に続く任意の文字列だったりする
- 実は
- 似たようなコードが並んでる。
- きな臭い。
- 最初の
when節と2個目のwhen節の違いはわずかにTypeA/TypeBだけ
Regexp.last_matchは 長い- せっかくあるんだから
$~を使いましょうや
- せっかくあるんだから
以上を踏まえて、自分で書き直してみたらどうなるかというと
def func(filaname)
category=/(?:cat1|cat2)/
ver2=/\d+\.\d+/
ver3=/\d+\.\d+\.\d+/
anytag=/(?:-.+|)/
case filename
when /pfx(TypeA|TypeB)-(#{category})#{anytag}-(#{ver3})(#{anytag})#{targz}\Z/
[ $~[1].to_sym,
$~[2],
$~[4].sub(/\A-/,''),
$~[3].split('.') ].flatten
when /pfxTypeC-(#{ver2})(#{anytag})#{targz}\Z/
# 以下略
end
end
あるぇ~?(・3・ 読みやすいか?これ?




