近年、リファクタリング(Refactoring)という言葉を耳にする機会が多くなってきたかと思います。ただ、リファクタリング(Refactoring)という言葉は、言葉の定義が曖昧で、何をしすることなのか、よくわからないといった声を聞くことがありました。

今回は、改めてリファクタリングについてまとめてみようかと思います。

リファクタリングとは?

リファクタリングという言葉を大きく広めたのは、Martin Fowler先生の「ファクタリング : プログラミングの体質改善テクニック」という本であったと思います。ソフトウェアエンジニアとしてのキャリアを歩みだしたころ、先輩のススメで読んだのがこの本でした。当時は、「実装した後に、設計をする」という感覚や、コードの匂いという部分にはてなマークがつきながら、とにかく1回読んだのを記憶しています。この初版本の出版から、約18年たった現在もリファクリングという言葉は、エンジニアの中で使わない人はいなぐらい利用されています。ソフトウェア業界の中で、10年以上話題に上がり続けるのは、珍しいのですが、それだけ必要な技術ということだと感じています。

リファクタリングとは、ソフトウェアの外部の振る舞いを保ったままで、内部構造を改善していく作業のことです。挙動に問題がなくても、内部のコードが最適な状態とは限りません。無駄なコードが多く、分かりにくい構造になっていることがあります。この状態は、長く保守運用しているコードにはありがちなことです。リファクタリングでは、このようなコードを整理して洗練された状態に変更していくということを行います。よく誤解されるのですが、機能追加やバグの修正は、リファクタリングではありません。外部からみたときのソフトウェアの挙動を変更してしまうからです。

似たような言葉にプログラムのパフォーマンス・チューニングという言葉があります。こちらは、外部的な振る舞いを変更することなくプログラムの速度を向上するような取り組みをすることです。一般的にパフォーマンス・チューニングをするとコードは読みにくくなります。リファクタリングは、コードを読みやすくする対応をする中でパフォーマンスを犠牲にするということも厭わない変更をします。リファクタリングよりもパフォーマンスが重要である場合は、コードが扱いにくくなることを厭わない変更も許容すべきです。

リファクタリングを行う目的とは?

普段、開発者がやっている作業は、コードを書くことよりもコードを読む時間の方が圧倒的に多いです。簡単な機能追加やバグだと思っていたのに、いつまでたっても完了しないってことは、結構あると思います。そのようなことを減らすのにもリファクタリングは有効なのです。

1. コードを理解しやすくする

普段、開発者がやっている作業は、コードを書く時間よりもコードを読んで理解することに使う時間が圧倒的に多いです。
他の人が書いたコードであれば、理解がしづらいですし、過去の自分が書いたコードでも1ヶ月もすれば、わからなくなることがあります。
このコードを読む作業時間を減らすことができれば、機能追加や障害対応、引き継ぎのときの苦労が軽減されます。 また、リファクタリングの過程で、動作や挙動についての深い理解を得ることができるという恩恵があります

2. 劣化しにくくなる

機能追加、不具合修正を繰り返すと気づかないうちにコードが複雑になるものです。また、いろいろなところに似たようなロジックが散らばり、バグや対応漏れといったことが多く発生するようになります。 リスクや技術的な負の遺産が大きくなる前に改善していくというのがリファクタリングになります。

3. 開発速度が上がる

コードを理解しやすくなるで説明した恩恵の人で、「動作や挙動についての深い理解を得ることができる」ということを説明しました。 普段から、コードに触っているとリファクタリングの中で把握した知識などをつかいながら、自然と開発速度があるものです。

リファクタリングでは、具体的に何を行うのか

1. テストできるようにする

テストコードがない場合にも必ずここから始めます。リファクタリングの前提は、リファクタリング前後で”挙動を変えない”ことです。レガシーコードなどでは、テスト方法が確立していないケースがありますので、まずは、既存のコードの挙動を把握するためにも、テストできるようにしましょう。

2. コードをシンプルにする

  • まとまった処理をメソッドとして重複部分を減らす
    コードは重複部分が多いと読みにくくなります。また、ロジック変更時には重複部分がすべて対象になるため負担が大きくなります。分岐条件が追加される際は、各ケースに重複部分があれば、さらに重複部分が増えてしまいます。
  • ネスト(入れ子)を浅くする
    ネストが深いと条件が分かりづらく、テスト時に漏れが生じるかもしれません。条件の順番を入れ替える、一部をメソッドとして抽出するなどしてネストを浅くしましょう。
  • 変数や関数の名称をシンプルにする
    名称が内容を簡潔に表現できていれば理解が円滑化します。他者に誤解される名称は避けましょう。また、これらの作業を円滑化するにはツールの利用が有効です。リファクタリングをサポートする機能が備わった開発ツールを使えば、リファクタリングの手間と人為的ミスを減らせます。

リファクタリングの注意点

普段、開発者がやっている作業は、コードを書くことよりもコードを読む時間の方が圧倒的に多いです。簡単な機能追加やバグだと思っていたのに、いつまでたっても完了しないってことは、結構あると思います。そのようなことを減らすのにもリファクタリングは有効なのです。

1. 不具合、機能追加を一緒にやらない

やりがちなことですが、リファクタリングの前提は、リファクタリング前後で”挙動を変えない”ことですので、そこは分けて作業しましょう。バージョン管理ツールなどをうまく使って、リファクタリング中は、リファクタリングに専念する。これを守らないと失敗します。ちなみに、「テスト駆動開発」で有名なKent Beck氏は、これを2つの帽子というような表現をしています。

2. テストできるようにしてから作業する

リファクタリングは前後でソフトウェアの挙動が変わってはいけません。そのため、リファクタリング後には必ずテストし、挙動が変わっていないことを確認する必要があります。そのため、リファクタリングの作業は細かく分割して行うことが推奨されています。広範囲にわたるコードを一息にリファクタリングし、テストにパスできなくなると、どこに問題が生じたのか分かりづらいためです。


ここまで”リファクタリングの基本的なご紹介”から、”リファクタリングを行う目的”、”リファクタリングの注意点な”どについてご紹介してきました。次回は、リファクタリングを行った過去の事例なども交え、リファクタリングに着手する時期などについてご紹介できればと思います。