リファクタリングは何故必要か

言葉遣いはやや辛辣ですが、内容自体は非常に共感できるので応援も兼ねて一言言っておくことにします。

気軽に「リファクタリングした」って言うな。

リファクタリング」という言葉はプログラマ以外は絶対に知らないであろう非常にニッチな言葉であるにも関わらず、時折誤用されることがあります。バズワードと呼ぶにはあまりに使う人たちが限定的ですが、本来の意味を超えて広く使われてしまっているという意味では似たようなものかもしれません。

本来の「リファクタリング」という言葉は非常にシンプルで

  • 外部への振る舞いを変更しない
  • 内部の構造を(通常はよりよい構造へ)変更する

の2つを満たす行為のことです。 そして、通常は一点目の条件である外部への振る舞いが変わってないことを確かめる方法が自動化されたテストなのですが、この言葉が時折誤用されていると僕が感じる理由は、テストがない状態やテストで保護できているレベルを超えた範囲のコード修正をリファクタリングと呼んでしまっている場合があるからです。

マーティン・ファウラー「リファクタリング」では安全なリファクタリングをするにはどうすればいいかという問いに対して、以下のように述べています。

  • 自分のコーディング能力を信じる
  • コンパイラが自分の見落としたエラーを捕捉してくれると信じる
  • テストスイートが自分とコンパイラの見落としたエラーを捕捉してくれると信じる
  • コードレビューが自分とコンパイラとテストスイートが見落としたエラーを捕捉してくれると信じる

コンパイルを通さないスクリプト言語においてはテストこそが唯一のよりどころですし、テストコードがないとコードレビューの効果も下がる*1ので、外部から見たときの振る舞いを変えてないことを確かめる手段がほぼ皆無となります。これは「リファクタリング」とは呼べません。

リファクタリングの必要性

そもそもリファクタリングとは何故必要なのでしょうか? 「外部に対する振る舞いを変更しないのならユーザに対して何の価値もないじゃないか!時間の無駄だ!」という人もいるそうです。確かにこの意見は極めて限定的な状況下においては一理あります。すなわち「将来にわたってそのソフトウェアを変更しない場合」です。リファクタリングによって内部構造を変更するのはソースコードの可読性の向上のためであり、すなわちソフトウェアの保守性を向上するためですので、変更の予定がないのであればリファクタリングは必要とされません。ただ、昨今、このような状況は少なくなってきているのではないでしょうか。

いつリファクタリングするか

上述したマーティン・ファウラー「リファクタリング」にはリファクタリングのタイミングについて以下が挙げられています。

いずれも納得感はありますし、実際僕も新たに機能を追加する時や実装ができてコミットをする直前にリファクタリングをすることが多いです。 ただ、ひとつ強調しておきたいのは「リファクタリングのために特別に時間を設けるべきではない」ということです。先述した通り、コードに変更がないのであればリファクタリングは不要ですし、コードに変更が入る場合でも該当箇所が十分にリーダブルで容易に変更が可能なのであればリファクタリングの必要はないでしょう。通常は機能変更が必要になったタイミングでコードを見て、現状の設計のままで変更を行うことが困難であるということに気づくものです。

冒頭のエントリの『気軽に「リファクタリングした」って言うな。』の一番本質的な(そしておそらく本人も意図していない)メッセージはそこなのではないかと僕は思います。リファクタリングはそれが単体で作業として成立するものではなく*2、ほぼ必ず振る舞いの変更を伴うコード変更の前段階の作業として位置づけられます。したがって、わざわざ「リファクタリングした」というほどのものではないし、むしろユーザに影響する振る舞いの変更のほうが興味があるということなのではないでしょうか。

息を吸って吐くようにコードを書く

僕たちプログラマは毎日コードを書いています。 コードを書くということはほとんどの場合リファクタリングを伴います。クラス名を考え、メソッド名を考え、引数リストを考え、変数名を考え、そして実装をするわけですが、実装してみたあとにもう一度見直してみると意外に読みづらく、変数名を変えてみたり、メソッドを別のクラスに移動してみたりした経験は誰にでもあるのではないでしょうか。 日常的にコードを書くプログラマである以上、その一部にリファクタリングという営みは含まれます。それはまるで生物が呼吸をするように自然に、本人すら意識しない程度のものでしょう。

リファクタリングしたよ」ってわざわざ報告するようなものではなく、「あ、このメソッド、こっちに移動したんだね。なるほど。」といったカジュアルな会話ができるプロジェクトチームは素敵だと思いますし、そういったチームでコードを書きたいと常々思っています。

*1:プロダクトコードのみより、その使い方を記載したテストコードも一緒であるほうがレビュワーにコードの意図が伝わりやすいため

*2:それこそ「ユーザに何の価値もない」と言われてしまうでしょう(苦笑