
Page | 1 | 2 |
誰でもわかる リファクタリング入門
|
|
皆さんは,リファクタリング(refactoring)という言葉を聞いたことがあるでしょうか?実生活では,ほとんど聞いたことのない言葉ですよね(注1)。一言で言えば「プログラムの外部仕様(入力と出力)を変えずに,内部構造を安全に改善するテクニック」がリファクタリングです(図1)。その目的はプログラムを理解しやすい状態に維持し,拡張性や再利用性を高めること。「こまめに手入れをしてプログラムを長持ちさせるテクニック」と言ってもいいでしょう。
![]() (図1) |
![]() (写真1) |
テクニックと言うくらいですから,リファクタリングは単なる「改善のススメ」といったコンセプトではありません。リファクタリングが必要となる状況「コードの不吉なにおい(bad smell)」や,実際の改善手順,サンプル・コードなどが具体的にまとめられ,そのものずばり「リファクタリング:プログラミングの体質改善テクニック」(写真1)(注2)という書籍に,カタログのように整理されています。
しかし皆さんの中には,「リファクタリングはデバッグやチューニングと何が違うの?」と思う方がいらっしゃるかもしれません。実はプログラムの修正という行為は「デバッグ」「機能拡張」「パフォーマンス改善(チューニング)」「リファクタリング」の四つに大きく分類できるのです。これらの中でリファクタリングは,どういう位置付けにあるのでしょう。
まず四つを「どの状態のプログラムを修正するのか」という視点で分類すると,デバッグと残り三つに分かれます。デバッグは,正常に動かないプログラムを修正することですね(注3)。一方,機能拡張,パフォーマンス改善,リファクタリングは,正常に動いているプログラムに対して行う修正です。機能拡張は,できあがったプログラムに新しい機能を加えたり,使い勝手を良くしたりする修正ですし,パフォーマンス改善は,実行速度が遅かったり,システムのリソース(メモリーやディスクの容量)を必要以上に消費していたりする場合に施す修正です。リファクタリングも,動作そのものには問題ないプログラムに対して行う修正です。
しかしこの四つを「修正をすると恩恵を受けるのは誰か」という視点で分類すると,リファクタリングが他の三つと比べて異なる点が明確になってきます(図2)。それは最初の三つが,プログラムを動かして使う人(ユーザー)のために行う修正であるのに対し,リファクタリングはプログラムを直す人(つまりプログラマ)のための修正であるという点です。ここで言うプログラマには,将来そのプログラムを直す他人だけでなく,自分自身(注4)も含まれています。つまり,リファクタリングは誰のためでもなく,プログラマ自身のために行う作業というわけです。「じゃあリファクタリングなんて,しょせんプログラマの自己満足なの?」――いいえ。プログラムの構造がわからなくなって,デバッグや機能拡張が滞ってしまえば,最終的に困るのはユーザーです。結局,リファクタリングを行うことはユーザーにとっても間接的なメリットがあると言えるのです。

リファクタリングを安全に行うコツ
しかし,リファクタリングには危険もあります。何しろ正しく動いているプログラムを直すのですから,新たなバグを作り込んでしまう可能性があります。頭の中で「こうすればうまくいく」と思っても、いざ試してみると思い通りにならないことがあったり,単純な間違いをしてしまったり,ということもあるでしょう。リファクタリングの過程でバグを作り込んでしまい,それを取り除くために一生懸命デバッグをしなければならないようでは本末転倒です。修正した後で,書き直したプログラムを元に戻せなくなってしまう危険もあります。
そこで大切になってくるのが,いかにリファクタリングを安全に行うかというコツでしょう。以下の五つが挙げられます。
リファクタリングと他の作業を分離する
プログラムに機能追加をするときに,リファクタリングをすることがよくあります。ただし両方の修正をまとめてやってはいけません。異なる種類の修正をまとめて行うと,間違いが起きたときにどこが原因かを調べるのが大変になるからです。それに,まとめて修正すると元に戻すことも難しくなってしまいます。
リファクタリングの前後で必ずテストをする
|
リファクタリングはプログラムの外部仕様を変えないため,プログラムの実行結果も変わりません。したがって,リファクタリングの前後では必ずテストを行い,バグを作り込んでいないことを確認する必要があります。テストは,極力簡単に行えるようにするのがポイントです。一般に,リファクタリングをする場合には,まずそのプログラムの正常動作を確認するためのテスト・プログラムを書き,リファクタリングの前後で実行しながら作業を進める方法が推奨されています。テスト・プログラムを簡単に作るため,xUnit(注5)と呼ばれるオープンソースのテスティング・フレームワークもあります(図3)。 |
![]() (図3) |
1回の作業を極力小さくする
メソッドの名前を変える,if文などの条件記述を変更する,といった小さな修正を行い,そのたびにテストを行うようにしましょう(注6)。こうした小さな単位での修正と確認を積み上げる方法をとることで,仮に間違ってしまった場合でも原因を特定しやすくなります。
既存のロジックへの影響を少なくする
コードをガラッと書き換えはいけません。すでに正しく動いている既存のコードをできるだけ残して,徐々に進めていきましょう。
必ずバックアップをとっておく
どんなに慎重に進めても,人間のやることに間違いはつきものです。したがって,いつでも元に戻せるように細かくバックアップを保存しておくことが大切です。同じファイルをバージョン別に保存できる構成管理ツール(注7)を使うことも考えましょう。
リファクタリングのカタログ
以上五つのコツを読んで,なんだか面倒くさそうな感じがしてきた方はいませんか? 安心してください。リファクタリングは比較的新しいテクニックですが,そのノウハウは確立しています。それがリファクタリングの「カタログ」です。前述の「リファクタリング」書籍には,全部で68個のカタログがあり,大きく六つに分類されています(表1)。もしメソッドの構成についてリファクタリングを行いたければ,9個のカタログの中から最適な手順を探せばいいでしょう(注8)。 一つひとつのカタログには,名前,要約,動機,手順,サンプル・コードがありますから,何をどうすればいいか,すぐにわかります。例えば,代表的なリファクタリングである「メソッドの抽出」の手順を抜粋してみましょう。
1. 適切な名前の新しいメソッドを作る
2. 抽出したいロジックを新しいメソッドにコピーする
3. 抽出されたロジック中のローカル変数を新しいメソッドに適合するように変更する
(メソッドの引数や一時変数,戻り値に変更する)
4. コンパイルしてテストする
5. 元のメソッドを新しいメソッドを呼び出すように変更する
6. コンパイルしてテストする
このようにカタログには,非常に細かい作業内容が具体的に書いてあり,さらに細かい注意点やサンプル・コードも紹介されています。リファクタリングのテクニックは,実際にプログラムを直そうとするときのハンドブックとして使えるわけです。
表1●リファクタリング・カタログの6分類
| 分 類 | 説 明 | カタログの数 |
| メソッドの構成 | ロジックを適切な単位のメソッドにまとめる | 9 |
| オブジェクト間での特性の移動 | クラスの役割分担を適切にする | 8 |
| データの再編成 | データ操作の方法を適切にする | 16 |
| 条件記述の単純化 | 条件記述(if文など)を単純化する | 8 |
| メソッド呼び出しの単純化 | メソッドの呼び出し方を適切にする | 15 |
| 継承の取り扱い | 継承の使い方を適切にする | 12 |
(注1)確かに,リファクタリングと言う言葉を一般の辞書で引いても見つからない。因数分解などを意味するfactoringをもじった造語らしい。もし語源をご存知の方がいたら教えてほしい。
(注2)リファクタリング:プログラミングの体質改善テクニック」,マーチン・ファウラー著,児玉 公信,友野 晶夫,平澤 章,梅澤 真史訳,ピアソン・エデュケーション発行。著者のWebサイト(http://www.refactoring.com/)では,新しいカタログなどの最新情報が公開されている。
(注3)英語でデバッグ(debug)は「欠陥を除去する」の意味。
(注4)数カ月後に自分で作ったプログラムを修正するとき,細かいロジックまで覚えているとは限らない。
(注5)xUnitは主にプログラムの単体(ユニット)テストを支援するテスティング・フレームワークの総称で,Java用のJUnit,C++用のCppUnit,Visual Basic用のVBUnitなど,さまざまなプログラミング言語用のフレームワークがある。ちなみに,xUnitがなければリファクタリングを行ってはならない,ということはない。
(注6)前述の書籍「リファクタリング」も,非常に小さな修正の単位でまとめられている。
(注7)構成管理ツールとしては,オープンソース・ソフトウエアのCVS,マイクロソフトのVisual SourceSafeなどがある。
(注8)リファクタリングのカタログを学ぶことは,新規にプログラムを作るときの参考にもなる。
Page | 1 | 2 |



