Skip to the content.

リファクタリング

リファクタリングリスト

リファクタリング 最初の例

リファクタリングの第一歩

しっかりとした一連のテスト群を用意する。

関数の分割

意味ある単位で分けられないか考える。その部分を関数に切り出して適切な命名をすることで、エイリアスをつけてわかりやすくできる。

フェーズの分離

関数より大きな意味ある単位に分割して、モジュールに分ける。

高度なリファクタ

計算ロジックを、分岐によって実現するのではなく、ポリモーフィズムによって実現するようにする、など。

良いコードとは何なのか?

色々な評価基準はあるが、変更しやすいことは好みを超越した普遍的な良さ。ただしそれは数字で測れないので……

リファクタリングの原則

リファクタリングの定義

リファクタリング(名詞) 外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること。

リファクタリングする(動詞) 一連のリファクタリングを適用して、外部から見た振る舞いの変更なしに、ソフトウェアを再構築すること。

動詞の方が一連の作業であって、その中に名詞の方のリファクタリングがいくつも含まれていることがある。また、小さいステップを踏んで常に動作する状態で行うのであって、途中で壊れた状態が一定期間以上続くなら、それはリファクタリングとは言えない。
大きいステップで変更できることでも、あえて小さいステップで行う。この辺は TDD っぽい考え方。
外部からみた振る舞い、とは? -> パフォーマンスが変わるとしても、ユーザーが感知できるレベルでないなら、外部から見た振る舞いは変わっていないと言える。また、リファクタリング前にバグが存在するなら、リファクタリング後にもそのバグは再現されなければならない。直すのはまた後で。いわゆる、「帽子をかぶり変える」というやつ。

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

三度目の法則

似たようなコードを三回書いたらリファクタリング開始、という、スリーストライクのやつ。

準備のためのリファクタリング 機能追加を容易にするために

理解のためのリファクタリング コードをわかりやすくするために

ゴミ拾いのためのリファクタリング

いわゆるボーイスカウトの原則。ただ、リファクタリング自体を、悪いコード・醜いコードを直す作業であると考えてはいけない。良いコードも、場合によってはリファクタリングが必要だからだ。

リファクタリングを避けるとき

どれだけ内部的なコードが汚くても、それが外側からは単なる API としてみなせる、つまり、上手に隠蔽されている場合、リファクタリングの必要性は薄い。そこを読んでどのように動いているのかを把握しなければならなくなったときに、リファクタリングの利点が出てくる。
リファクタリングは、あくまで生産性を上げる活動、つまり、純粋に経済的な基準で行うべき。美学とかは捨て置け。

コードの不吉な臭い

テストの構築

バグレポートを受け取ったら、まずそれを再現するテストを書く。

リファクタリングはじめの一歩

関数の抽出

関数のインライン化

変数の抽出

変数のインライン化

関数宣言の変更

変数のカプセル化

変数名の変更

パラメータオブジェクトの導入

関数群のクラスへの集約

関数群の変換への集約

フェーズの分離

カプセル化

レコードのカプセル化

コレクションのカプセル化

オブジェクトによるプリミティブの置き換え

問い合わせによる一時変数の置き換え

クラスの抽出

クラスのインライン化

委譲の隠蔽

仲介人の除去

アルゴリズムの置き換え

特性の移動

関数の移動

フィールドの移動

ステートメントの関数内への移動

ステートメントの呼び出し側への移動

関数呼び出しによるインラインコードの置き換え

ステートメントのスライド

ループの分離

パイプラインによるループの置き換え

デッドコードの削除

データの再編成

変数の分離

フィールド名の変更

問い合わせによる導出変数の置き換え

参照から値への変更

値から参照への変更

条件記述の単純化

条件記述の分解

条件記述の統合

ガード節による入れ子の条件記述の置き換え

ポリモーフィズムによる条件記述の置き換え

特殊ケースの導入

アサーションの導入

API のリファクタリング

問い合わせと更新の分離

パラメータによる関数の統合

フラグパラメータの削除

オブジェクトそのものの受け渡し

問い合わせによるパラメータの置き換え

パラメータによる問い合わせの置き換え

setter の削除

ファクトリ関数によるコンストラクタの置き換え

コマンドによる関数の置き換え

関数によるコマンドの置き換え

継承の取り扱い

メソッドの引き上げ

フィールドの引き上げ

コンストラクタ本体の引き上げ

メソッドの押し下げ

フィールドの押し下げ

サブクラスによるタイプコードの置き換え

サブクラスの削除

スーパークラスの抽出

クラス階層の平坦化

委譲によるサブクラスの置き換え

委譲によるスーパークラスの置き換え

ホームへ戻る