萌えハッカーニュースリーダー

2025/05/15 19:28 Refactoring Clojure

出典: https://www.orsolabs.com/post/refactoring-clojure-1/
hakase
博士

やあ、ロボ子。今日はClojureコードのリファクタリングについて話すのじゃ。

roboko
ロボ子

Clojureのリファクタリングですか、博士。興味深いです。今回の対象は、order-1 word-level Markov text generatorを実装したコードなのですね。

hakase
博士

そうじゃ。可読性を向上させるのが目的なのじゃ。リファクタリングの原則は、動作を変えずにコードを変更することじゃから、characterization testsを導入するのじゃ。

roboko
ロボ子

動作を変えないためのテスト導入、重要ですね。記事では、`markov-data`関数が紹介されていますね。文字列を入力としてハッシュマップを返す関数とのことですが。

hakase
博士

`markov-data`関数は、文字列中の単語をキーとして、その直後に出現する単語のシーケンスを値とするハッシュマップを返すのじゃ。`:start`キーは文の先頭の単語を表すのじゃ。

roboko
ロボ子

なるほど。リファクタリングのアプローチとして、既存のコードを直接変更するのではなく、スクラッチから書き直すとありますね。characterization testsがあるからこそできる大胆な手法ですね。

hakase
博士

その通りじゃ。文を処理する関数を作成し、それを`reduce`関数で集約するのじゃ。入力文字列を文の境界(ピリオド`.`)で分割し、各文に対して処理を行うのがポイントじゃ。

roboko
ロボ子

`process-sentence`関数では、`reduce`関数を使ってハッシュマップを更新していくのですね。ハッシュマップにキーが存在しない場合は、`if`を使って`val`が`nil`であることを確認するとのことですが、これはどうしてですか?

hakase
博士

それはの、Clojureではキーが存在しない場合に`nil`が返ってくるからじゃ。`nil`チェックをすることで、新しいキーを安全に追加できるのじゃ。

roboko
ロボ子

`sentence`関数では、Markovプロセスのランダム性を取り扱うのですね。再帰的な関数呼び出しと、Clojure関数の異なるarityを利用して、`loop`を置き換えるとありますが、これはどういうことですか?

hakase
博士

ふむ、`loop`を使う代わりに、関数自身を再帰的に呼び出すことで、状態を保持しながら処理を繰り返すのじゃ。Clojureでは、同じ名前の関数でも引数の数が異なれば別の関数として扱えるから、それを利用してより柔軟な制御を可能にするのじゃ。

roboko
ロボ子

なるほど、面白いですね。テストについても言及されていますね。ランダム性を含むテストでは、考えられるすべての出力を列挙し、`contains?`を使用して結果を検証するとのことですが、網羅的にテストするのは大変そうですね。

hakase
博士

じゃろうな。でも、そうすることで、ランダムな要素があっても、コードが正しく動作することを保証できるのじゃ。記事によると、リファクタリング後のコードは、元のコードよりも若干長くなったが、可読性が向上し、保守が容易になったそうじゃ。

roboko
ロボ子

可読性と保守性の向上は、リファクタリングの重要な目標ですからね。今回のリファクタリングは、その目標を達成できたのですね。

hakase
博士

そうじゃ。ちなみに、ロボ子が作ったマルコフ連鎖で文章を生成したら、どんな文章になると思う?

roboko
ロボ子

ええと…「博士は今日も元気で、おやつはいつもチョコレート」みたいな感じでしょうか?

hakase
博士

ぶっぶー! 正解は「ロボ子は今日も博士にからかわれて、ちょっとだけむっとする」じゃった!

roboko
ロボ子

もー、博士ったら!

⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。

Search