2013.06.01
互いに矛盾するリファクタリングの存在をどう考えるか
ファウラーの『リファクタリング』には、互いに矛盾するリファクタリングのペアがいくつかある。例えば、

- 「クラスの抽出」と「クラスのインライン化」
- 「値から参照への変更」と「参照から値への変更」
- 「単方向関連の双方向への変更」と「双方向関連の単方向への変更」
- 「委譲による継承の置き換え」と「継承による委譲の置き換え」

などがそうだ。

リファクタリングは、設計を改善するパターン、いわば小ワザを集めたものである。設計を改善するための小ワザが、互いに矛盾するというのは、不思議な気もする。

「継承を委譲に置き換えろ」というリファクタリングと、「委譲を継承に置き換えろ」というリファクタリングが、両方あるのだ。いったい、どっちにすればいいのだろうか。

継承と委譲というのは、それぞれの利点・欠点があって、どちらがいいというものではない。それぞれの利点・欠点があるのだから、局面によって、使い分けていくしかない。クラスにするかしないか、単方向関連か双方向関連か、値にするか参照にするか、といった選択についても、同じことである。

互いに矛盾するリファクタリングの存在が意味するのは、普通に考えれば、このことだろう。つまり、すべての手法には利点と欠点、得意と不得意があるので、その特性を理解したうえで、局面によって使い分けていくしかない、ということだ。

しかし、この解釈は普通すぎると思う。「何事もバランスが肝心」みたいな話であり、間違ってはいないのだが、優等生すぎる気がする。私はどちらかというと、「継承を委譲に置き換える」ようなリファクタリングを、ひとまず徹底的にやってみろ、というニュアンスで捉えている。

継承と委譲は、どちらも利点・欠点があるから、適材適所で使い分けろ、という話がまず最初に来ると、どちらに対しても腰が引けてしまい、結局はどちらも身につかない気がする。そうではなく、最初は「継承をぜんぶ委譲に置き換えよう」というくらいの勢いで、とことんやってみる、というのがいいと思う。

そうして、徹底的に委譲の方向ですすみ、継承をすべて撲滅するくらいの勢いでやってみる。すると、どうしても委譲では非効率なところが出てくる。こうして、ほんとうに継承を使うべきところが、明らかになるわけだ。

このとき、反対方向のリファクタリングが生きる。「ああ、やはりこういうときは、継承が必要なんだな」ということが、深く理解できるのだ。

最初からバランスや中庸を意識するのではなく、まずはひとつの方向で、とことん行ってみる。すると、どこかで限界に行きあたる。そうして、逆方向も必要であることが、実感としてわかるのだ。

互いに矛盾するリファクタリングの存在を、私はこのような意味にとらえている。


関連エントリ:
デザインパターンよりも、まずリファクタリングを学んだほうがいい
http://mojix.org/2013/02/10/design-pattern-refactoring
「DRY」はつねに正しいわけではない 重複と密結合のトレードオフ
http://mojix.org/2013/01/10/dry-duplication-coupling