Refactoring with Bad Design or Natural Design Evolution

Refactoring for Bad Design? 英語は良く分からないけど、、、リファクタリングの話。
Natural Design Evolution は、わざわざうそ臭い英語で書いてみたけど、設計の自然な進化、という雰囲気。


いつ(あるいは、どのような動機で)リファクタリングを適用 した かによって、リファクタリングでも微妙な違いが現れると思う。この違いは、違いでないかもしれないし、違いだとしても、実際には深く考える意味はないかもしれない。でも、一応考えてみたいと思う。


まず、リファクタリングをする第一の動機としては、悪い設計のソフトウェアをクリーンな設計にして、ソフトウェアのメンテナンスを容易にしたり、新しい要求に対して素早く対応できたりすることにあると思う。


たとえば Strategy パターンを導入すること になる、理由としては、条件文のロジックとかが分かりにくいからだと思う。


class Context {

public void contextInterface() {
if (..) {
// 何かする

} else if (..) {
// 他の何かする

} else {
// さらに何か
}
}
}

こういうコードが複雑だと思ったら Strategy の出番になる:

interface Strategy {
public void perform();
}
class ConcreteStrategyA implements Strategy {
public void perform() { /* 何かする */ }
}
class ConcreteStrategyB implements Strategy {
public void perform() { /* 他の何かする */ }
}
class ConcreteStrategyC implements Strategy {
public void perform() { /* さらに何か */ }
}
class Context {

private Strategy strategy;

public void contextInterface() {
strategy.perform();
}

public void setStrategy(Strategy strategy) {
this.strategy = strategy;
}
}

この場合 は、リファクタリングだと思う。でも、以下のような流れだとしたら?


当初は、複雑な分岐になると思っていなかったので、以下のようなコーディングを行った:


class Context {

public void contextInterface() {
// 何かする
}
}

その後、実行内容を分岐させる必要があったので、
選択肢 1: Strategy を導入した
選択肢 2: if 文で済ました


さらに、新しい分岐をする必要がでてきたので、
「選択肢 1」を選んだ場合には: 新しい ConcreteStrategy を導入した
「選択肢 2」を選んだ場合には: さらに if 文を追加した。そのため、(最初の例でみたように)Strategy パターンを導入することによるリファクタリングを行った。


僕が気になるのは、選択肢 1 を選んだ場合 にも、最終的には、選択肢 2 を選んだ場合にリファクタリングを行った結果になりうる、ということ。


もちろん、二個目の分岐の要件がなければ、結果は異なる。「選択肢 1」を選んだ場合には、Strategy を導入したことは、やりすぎの設計で、逆にソフトウェアを複雑にしてしまったかもしれない。


とはいえ、最終的に到達するコードは同じでも、どういう設計上の決断をしたか(早い目に Strategy を導入するか vs まだそれほど複雑じゃないので if で済ます)、によって、リファクタリング した か、あるいは、しなかった か、の違いがでるように思える。


なぜこの違いに関心があるのか?


この例でみたように、どういう設計上の決断をしたかによって、リファクタリングであったかどうかの違いが出るとするなら、上手に設計する人であれば、リファクタリング行っていない、ということになるのではないか、と思ってしまう。


そう、自分は、リファクタリングを行っているのだろうか? それとも、設計と要件の自然な流れにより、コードを変更していっているだけだろうか?


関連:

Joshua Kerievsky
Refactoring to Patterns
http://www.amazon.com/exec/obidos/tg/detail/-/0321213351/