特集

.NET開発者のためのリファクタリング入門

− プログラミングの生産性をアップするリファクタリングとは −

株式会社ピーデー 川俣 晶
2004/12/08

Page1 Page2 Page3 Page4

 

 ちょっとそこのお客さん。ずいぶん浮かない顔をしていますね。え、仕事はプログラマ? そして評価が高く実績もあるプログラムのメンテナンスの仕事を任された? それはおめでとうございます。

 え、めでたくない? それはいったいどうしてですか? ほほう。つまり、ユーザー・インターフェイスはすごく格好よいのに、ソース・コードがぐちゃぐちゃで何が何やら分からないと。それなのに、評価の高いソフトだからと機能追加の要求がいくつも発生していると。何が何やら分からないソース・コードを修正して、その要求に対応しなければならないわけですか。それは難儀ですな。すぐにやれといわれても、できるわけがない。

 え、それは問題ではない? もう時間がかかることは了承させた? それは結構なことで。それなのに、どうして浮かない顔をなさっているので? ははぁ、時間をかけて書き直したとしても、その書き換えが正しいのか自信が持てないと。どこか、思いも寄らないところで書き換えの悪影響が出るのではないかと心配されているのですな。

 そんなお客さんに、とっておきの良いものを紹介しましょう。リファクタリングというものなんですがね。いまならお安くしておきますよ。

 最近、プログラム開発技法などの話題で、「リファクタリング」という言葉をしばしば見掛けることがある。特に、エクストリーム・プログラミング(XP)やテスト駆動開発においては必須の手法として取り上げられるが、それらの一部というわけではなく、単独で話題になる場合もある。しかし、リファクタリングとは何かに関しては、十分に理解されていなかったり、誤解されていたりすることが多いようである。そこで、本稿ではあらためてリファクタリングの基本中の基本を解説し、「リファクタリングって何?」という疑問に対して答えることを試みてみたい。

 さて、リファクタリングの具体的な内容は、マーチン・ファウラー氏の名著、『リファクタリング プログラミングの体質改善テクニック』(ピアソン・エデュケーション刊)に示されている。この書籍がリファクタリングという言葉を使った最初のものではないようだが、リファクタリングに関する集大成としてバイブル的に扱われており、リファクタリングとは何かを考えるよりどころにこの書籍を持ってくることは間違いではないと思う。

 もちろん、この書籍は読みやすく、しかもこの短い記事よりもはるかに詳細であるから、「この本を読め。以上!」と書いて終わりにしてもよいぐらいである。しかし、あえてこの記事をここに書いてみたい。その最大の理由は、この書籍のサンプル・コードが主にJavaで書かれていて、Visual Basicプログラマにはなじみにくいということにある。この記事では、サンプル・コードをJavaではなくVisual Basic .NETで示しつつ話を進めたい。

リファクタリングの目的

 前置きはそれぐらいにして、本題に入ろう。そもそも、リファクタリングとは何だろうか。上記書籍の副題「プログラミングの体質改善テクニック」というのがその答えになるだろう。しかし、プログラミングの体質改善といわれても、ピンとこない読者も多いだろう。そもそも、プログラミングに体質などというものがあるのだろうか。あったとして、それは改善できるものなのだろうか。

 ここでは、イメージしにくいプログラミングの「体質」という言葉は忘れて、もっとざっくばらんに分かりやすい言葉で語る方がよいだろう。それが冒頭の文章である。つまり、手に負えない汚いソース・コードに対処できる画期的なテクニックがリファクタリングということである。

−POINT−
 リファクタリングは手に負えない汚いソース・コードに対処することができるテクニック

 では、自分はいつもきれいなコードを書くことを心掛けているからリファクタリングは必要ない、と思ってよいかというと、そうではない。なぜなら、どんなにきれいなソース・コードを書こうと心掛けていても、修正を加え続けると、いつかは手に負えない汚いソース・コードに堕落してしまうケースが多いためである。

 手に負えなくなってからリファクタリングを実施するという選択もあるが、それよりも、手に負えなくなる前に汚さの萌芽を摘み取ってしまう方が楽である。複雑怪奇にソース・コードが絡まり合う前に、問題が起こりそうな個所を刈り取ってしまうのである。そのような刈り取りにもリファクタリングは利用できる。

−POINT−
 リファクタリングは手に負えない汚いソース・コードに堕落しないために使用することができるテクニック

 以上のような話から、もう一度、リファクタリングの目的を考えてみよう。リファクタリングの目的は直接的には手に負えない汚いソース・コードに対処することではあるが、もちろんそれが最終目的ではない。汚いソース・コードに対処する力を得ることは、プログラミングの苦労を軽減することにつながる。つまり、プログラマは楽ができる。作業が楽になれば、より短い時間で完了できる。そしてつまり、プログラミングの生産性が向上するわけである。故に、以下のようにいい直すことも可能だろう。

−POINT−
 リファクタリングはプログラマが楽をするためのテクニック

−POINT−
 リファクタリングは生産性を改善するためのテクニック

■理解できないソース・コードを扱うことはできるか?

 さて、ここまでの説明で、いくつも「本当か?」「ウソくさい」と思える話が出てきたと思う。筆者が思い付く範囲内にあるそれらの疑問については、できるだけここで1つ1つ説明を加えていきたいと思う。

 なお、ここでは抽象的な説明で、単にリファクタリングするなら知らなくてもよいことを語る。面倒だと思ったら、ここは読み飛ばしても構わない。後述している具体的なリファクタリング・カタログの紹介から先に読んで、釈然としなかった場合に戻ってきて読んでもよい。読み方は読者の自由である。

 最初に、手に負えない汚いソース・コードに対処する、などということが本当に可能か? ということを考えたい。これは当然の疑問といえる。このようなソース・コードは、最初から書き直した方が早いと評価されることも多い。ソース・コードを理解するために時間を費やすぐらいなら、同じものをゼロから書いた方が早い、という意見である。

 このような主張が正しい事例は、経験的にいくつもある。経験的に正しい対処方法の1つといってよかろう。しかし、リファクタリングはその正しい経験則に逆らう主張をしているかのように見えるはずだ。果たして、経験則の逆転などということが可能なのだろうか?

 もうちょっと具体的に、この疑問を説明しよう。

 例えば、クラスやモジュールを記述する場合(よほど行き当たりばったりでもない限り)、それらには「役割」が与えられている。もし在庫管理クラスを作ったのならば、そのクラスは在庫管理の機能だけを含めるべきであって、給与計算の機能を含めるのは正しい選択ではない。そのようなソース・コードは、プログラマを混乱させるだけである。給与計算のコードを調べるために在庫管理クラスを見る必要があるなどとは誰も思わないだろうし、在庫管理のコードを調べているところに、いきなり給与計算のコードが出てきては在庫管理を理解する妨げになる。これをはっきりと示したものに、オブジェクト指向の世界では、「単一責任の原則(Single Responsibility Principle)」という用語もある。

 このように考えると、理解できないソース・コードとは、それぞれのクラスやモジュールが持っている「役割」が理解できないソース・コードということになる。

 例えば、在庫管理の機能をいくつかのクラスやモジュールによって処理していたとしよう。それらの間の役割の分担もはっきり分からない状態で、在庫を追加するメソッドをどのクラスやモジュールに追加するのが正しいのかを判断できるだろうか? それは判断できるわけがない、と考えるのが妥当な態度だろう。判断できない状態で、エイヤッと適当にコードを追加すれば、ソース・コードの理解不能度はさらにレベルアップしてしまう。どのクラスやモジュールに存在するかという根拠がない機能が増えるためである。それだけならまだしも、理解できないソース・コードに機能を追加しても、それが正常に動作するか、誰も保証できないのである。これでは、とても胸を張って「手に負えない汚いソース・コードに対処した」とはいえない。

 さて、ここまで読み進んだ読者で、そろそろこの記事を読むのをやめようかと思った方がいるかもしれない。とても、リファクタリングなどという実用のテクニックが存在するとは信じられない気持ちになっていると思うからだ。

 しかし、リファクタリングは実在していて、しかもその有用性が経験的に確かめられているテクニックである。いったいこのギャップはどこからくるのだろうか。これに答えることは、人によっては天動説から地動説に置き換わるほど大きな驚きとなるかもしれない。この答えを決して認めたくない、というプログラマも、読者の中にはいるかもしれない。逆に、なんだそんな当たり前のことかと平然と受け止める読者もきっといるだろう。

■理解できないソース・コードを扱うことができる理由

 では「理解できないソース・コードを扱うことはできるか?」という問いに対する答を書こう。それは「可能」である。なぜ可能なのか。その理由は次のとおりである。

−POINT−
 ソース・コードには理解せずとも扱える部分が存在する

 といっても、何が何やらさっぱり分からないだろう。実際に、理解できないソース・コードを扱う簡単な事例を紹介しよう。

 以下は、とあるモジュールの、とあるメソッドの一部である。これを、フラグ変数を使わない形に書き換えることができるだろうか(ちなみに、この書き換えは、リファクタリングでは「制御フラグの除去」と呼ばれる)。

Dim flag As Boolean

Do
  Dim s As String = reader.ReadLine()
  If s Is Nothing Then
    flag = True
  Else
    writer.WriteLine(s)
  End If
Loop Until flag
リスト1 とあるモジュールの、とあるメソッドの一部
このコードをフラグ用の変数「flag」を使わない形に書き換えることができるだろうか。

 これは、さほど難しい話ではないだろう。以下のように書き換えられる。

Do
  Dim s As String = reader.ReadLine()
  If s Is Nothing Then Exit Do
  writer.WriteLine(s)
Loop
リスト2 リスト1のコードをフラグを使わない形に書き換えたもの

 さて、この書き換えを行うために、このコードを含むメソッドの機能や、メソッドを含むクラスの役割を理解している必要はない。筆者としては、このコードがどのような役割を持っているかを読者に伝えてはいないが、それでも書き換えは可能だろう。

 もちろん読者が上記コードの役割が分からないのは筆者がそれを伝えなかったからだ。しかし、これがソース・コードが手に負えないほど汚いケースでも「役割がよく分からない」という状況は同じである。だとすれば、このような書き換えを、そのような汚いソース・コードにも適用できるはずだ。つまり、理解できないソース・コードを扱うことはできるのである。

 

 INDEX
  [特集] プログラミングの生産性をアップするリファクタリング入門
  1.リファクタリングの目的
    2.何のためにソース・コードを書き換えるのか?
    3.リファクタリング・カタログ(1)
    4.リファクタリング・カタログ(2)/リファクタリングとツール
 


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間