南極の図書館

ペンギンが寝ていた…。

「リファクタリング」の完全読破。その6、第6章後半。

前回は「第6章 メソッドの構成」から『総論と「メソッドの抽出(P110) 」「説明用変数の導入(P124)」』について書いたので、今回は残りの項目を。
大きなものは「メソッドオブジェクトによるメソッドの置き換え」くらいで、あとは項目名のとおりという印象。
(※下記のコード片は、本書の例を元に短縮等を行ったもの。)

第6章 メソッドの構成

「メソッドのインライン化(P117)」

不要な間接化、つまり委譲のみ行っているようにみえたら行う。単純な場合にのみ行い、複雑な場合は避ける。

return (moreThanFive()) ? 10 : 0;
boolean moreThanFive(){ return _preAmount > 5; }
↓
return (_preAmount >5) ? 10 : 0;
「一時変数のインライン化(P119)」「問い合わせによる一時変数の置き換え(P120)」

「一時変数のインライン化(P119)」は、よく「問い合わせによる一時変数の置き換え(P120)」の一部として使う。
先に変数をfinalにしてみるのがコツ。エラーがなければ一度しか代入されていないことがわかる。
これらも、一度だけ代入されるか副作用がない場合に行う。
複数回代入されるなら「一時変数の分離(P128) 」、副作用があるなら「問い合わせと更新の分離(P279)」を適用することを考える。

//一時変数のインライン化
double todayPrice = anOrder.getTodayPrice();
return (todayPrice > 1000);
↓
return (anOrder.getTodayPrice() > 1000);

//問い合わせによる一時変数の置き換え
double basePrice = _quantity * _itemPrice;
return basePrice * 3;
↓
return basePrice() *3;
private double basePrice() {
  return nowPrice * quantity;
}
「一時変数の分離(P128)」

複数回代入される一時変数は、代入ごとに別の一時変数に分ける。
複数回設定されるのは、複数の責任を担っていることを示す。 複数の責任を担う変数は、コードを読む人を混乱させる。

double temp = 2 * (_height + _width);
System.out.println(temp);
temp = _height * _width;
↓
final double perimeter = 2 * (_height + _width);
System.out.println(perimeter);
final double area = _height * _width;
「パラメータへの代入の除去(P131)」
int discount(int inputVal)
 if(inputval > 50) inputVal -= 2;
↓
int discount(int inputVal)
  int result = inputval;
  if(inputval > 50) result -= 2;

//代入が悪いだけで、メソッドの使用はなんら悪いことではない。
void aMehod(Object foo)
  foo.modifyInSomeWay(); //OK
  foo.setBar();          //OK
  foo = anotherObject;   //NG

この項目で重要なのは、上記の例よりも ”Javaは、厳密にはすべて値渡しを使っている””本質的に、オブジェクトへの参照は値渡し”ということ。

「メソッドオブジェクトによるメソッドの置き換え(P135)」

メソッドの分解を困難にするのはローカル変数である。Method Objectパターンを使う。
ちょっとこれは大きいので、無意識に出来るようになるまで何度か本書を読み直した方が良さそう。

class Account
 int gamma(int a, int b, int c){
   int value1 = (a * b ) + delta();
   int value2 = (a * c) +100;
   if ( (c - value1) >100 )
     value2 -=20;
   int value3 = value2 *7;
   return value3 - 2 * value1;
 }
↓
class Account
 int gamma(int a, int b, int c){
   return new Gamma(this, a, b, c,).compute();
}

TDDの調子で、抽出したGammaクラスとcomputeメソッドを書く。
これでリファクタリングの対象はGamma.compute()になる。というテクニック。

「アルゴリズムの取り替え(P139)」

文字通り、よりよいアルゴリズムに変更する。項目として必要なのはわかるんだけど、内容はタイトル以上のものでもないので割愛。


以上で第6章は終了。