読者です 読者をやめる 読者になる 読者になる

プログラミングの魔物

エラー、バグ、仕様変更と戦うブログ

リファクタリングとは?

リファクタリング 1章

第1章ではJavaで作られたプログラムを例として、リファクタリングの過程を説明している。
実際に打たないと感覚が掴みにくそうだったので、Luaで例題のプログラムを組んで修正しながら読みすすめた。

汚いプログラムは何が問題か?

ろくに設計せずに組んでいると1つのメソッドがいくつもの役割を兼ねていたり、同じ機能を持つメソッドが複数定義されていたりすることがよくある。
あるメソッドのコードの一部を流用するためにコピペして別のメソッド内で利用する・・・などとやっていると目も当てられないほどコードは肥大化していく。

メソッドが大きくなりすぎると可読性が悪くなるし再利用もしにくくなる。
コピペしたコードの一部を修正しようとして、プロジェクト内に分散した生き別れのコードたちを1つ1つ探して面倒を見るのはエレガントではない。
良識のあるプログラマはそのコード片を新たにメソッド化することを検討するだろう。

リファクタリングとは

リファクタリングとはソフトウェアの外部的振る舞いを保ったまま、内部の構造を改善していく作業のこと。

リファクタリングには手順がある。
正しい手順を守らないと、軽く修正するつもりが新たに修正箇所を見つけてどんどん深みにはまってしまう。
それを避けるためにリファクタリングは体系的に行う必要がある。

リファクタリングのデメリット

いくら外部的振る舞いを保ったまま改善しようとしても、コードに手を加える以上バグが生まれる可能性がある(デグレードする危険性)
そのためリファクタリングする際にはバックアップとテストを行う必要がある。

リファクタリングのメリット

コードが整理され見やすくなり、保守が行い易くなる。

リファクタリング手法

最初の例で書かれている簡易説明を元に書いているので、おそらくあとでまた詳細な手順を読むことになる。
一応書いてみたものの、言葉だけで説明すると訳わからん。

「メソッドの抽出」

肥大化したメソッドの一部の機能を抽出する。
メソッドを抽出することで、抽出した機能を再利用できるようになる。

手順

  1. コードの論理的な固まりを見つける
  2. ローカルなスコープの変数に着目し、新しいメソッドの一時変数や引数にならないかを検討する
  3. 変更される変数は1つだけなら戻り値とすることが可能
  4. テストする
  5. 一時変数や引数にした変数名を適切な名前に変更する。
  6. テストする

「メソッドの移動」

メソッド内に属しているクラスの情報が無ければ、適切なクラスへ配置する。

手順

  1. メソッドで属しているクラスの情報を使っておらず、他のクラスの情報を使っていたら、移動できるか検討する
  2. 移動先のクラスで使用できるように引数、プロパティ、メソッドを修正する
  3. 呼び出しを書き換える前に委譲の形で新しいメソッドを呼び出すように古いメソッドを修正する
  4. テストする
  5. 古いメソッドを検索して新しいメソッドに置き換える
  6. テストする
  7. 古いメソッドを削除する(時にはインターフェースを変えないために委譲として残すこともある)
  8. テストする

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

宣言されてから一度も変更されていない一時変数を、それを初期化したメソッドによって置き換える。
一時変数が多くなるとメソッドが複雑になり把握しにくくなる。
見やすさやパフォーマンスにより状況に応じて行う(パフォーマンスに関しては問題になってから遅延の原因となる部分を分析すればいいため、とりあえず置き換えても良い)

手順

  1. 一時変数が宣言されてから一度も変更されていないことを確認し、置き換えを検討する
  2. 一時変数をメソッドに置き換えて削除する
  3. テストする

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

switchで処理を分岐している部分などを適切なクラスへ配置してポリモーフィズムにする

手順

  1. 候補となるswitch等の分岐箇所を見つける
  2. 分岐の条件を元に適切なクラスへ移動する。元の場所は委譲に置き換える
  3. テストする
  4. 新しく配置したクラスを基本クラスとした分岐ごとのサブクラスを作る(例ではStateパターンで価格の種類のクラスを新しく追加)
  5. テストする
  6. 新しいクラスに分岐処理メソッドを移動する
  7. テストする
  8. 新しいクラスの派生クラスに分岐部分を切り分ける
  9. 新しいクラスの分岐処理メソッドを抽象クラスにする
  10. テストする

「State/Strategyによるタイプコードの置き換え」

手順

  1. 対象のフィールドの代入部分をsetメソッドに置き換える
  2. テストする
  3. 新しいクラスを作成する
  4. 新しいクラスをプロパティに追加する
  5. get、setを新しいクラスを使うように修正する
  6. テストする

メモ

  • 1つのメソッドが長く、他のクラスの仕事も行なっているケースはリファクタリングを検討する
  • コピペはシステム変更時に修正しづらくなる
  • 将来の追加機能に備える
  • 例題のプログラム出力結果は文字列なので、テストは現在のプログラムの出力結果と修正後のプログラムの出力結果の比較
  • リファクタリングに失敗したらどうなるかを把握する
  • リファクタリングで行数が多くなることもあるが、メソッドが論理的な単位で分割されるので把握しやすくなる
  • リファクタリングでパフォーマンスが落ちることもあるが、パフォーマンスが問題になるまでは気にしない
  • パフォーマンスが問題になれば、ボトルネックになっている部分をチューニングする。

この記事で読み進めている本

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

リファクタリング―プログラムの体質改善テクニック (Object Technology Series)

  • 作者: マーチンファウラー,Martin Fowler,児玉公信,平澤章,友野晶夫,梅沢真史
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2000/05
  • メディア: 単行本
  • 購入: 91人 クリック: 3,033回
  • この商品を含むブログ (295件) を見る