sifue's blog

プログラマな二児の父の日常 ポートフォリオは www.soichiro.org

Scalaでの切り出したい処理が処理の中間にあるメソッド同士の重複行排除のやり方

最近Scalaを書く人が増えてきたこともあっていろいろ教える機会も増えてきたのですが、その中でよくScala初心者がつまづきやすいポイントである、切り出したい処理が、処理の中間にあるメソッド同士の重複行排除のリファクタリングの例を書こうと思います。

 

重複のあるサンプルコードとしてはこのような感じになります。

例として、ランダムに文字列のテンプレートを選択してその中にメッセージを埋め込んだあと、そのバイト数と内容を出力するメソッドと、その文字数と内容を出力するメソッドを用意してみます。

切り出したい処理が処理の中間にあるメソッド

RandomTemplateProviderはテンプレートをランダムに渡すオブジェクトです。2つのメソッドは見ての通り仕様をそのまま実行していますが、printByteLengthAndContentメソッドとprintCharLengthAndContentメソッドには4行の重複行が含まれています。

 

こういう切り出したい処理が処理の真ん中に挟まっている場合の重複行排除は、関数を第一級オブジェクトでかけるScalaではこのようになります。

切り出したい処理が処理の中間にあるメソッド同士の重複行排除の例

 

関数をオブジェクトとして扱うことに慣れない方は、一瞬ん?とおもうかもしれませんが、このコードでは、printTargetLengthAndContentというメソッドを最下部で新たに定義し、そこでは、targetLengthProviderという関数を受け取って実行するという処理をしています。

 

この渡すtargetLengthProvider関数の中に切り出したい関数を元々のメソッドに設定すればよく、Scalaで簡単に匿名関数を作ることができる{}という記法を用いて上記のように表現してやることができます。これで見た目もわかりやすく存在していた重複行を排除することができました。

 

これでCPDなどのチェッカーなどに引っかかった時も柔軟に対応することができます。実際の業務のコードではこの重複行の長さが10行を超えるものである場合がほとんどですが、ぜひ応用にチャレンジしてみてください。

 

ちなみに、Java8になったことで、このような関数オブジェクトを使った重複行排除のリファクタリングが、Javaでもずいぶん書きやすくなっています。その例はまたの機会に。