以下、確認用メモ。
===リファクタリング原則[[リファクタリング]]原則===
=====定義=====
外部から見たときの振る舞いを保ちつつ、理解や修正が簡単になるように、ソフトウェアの内部構造を変化させること。
一連のリファクタリングを行って、外部からみた振る舞いを変えずにソフトウェアを再構築する。一連の[[リファクタリング]]を行って、外部からみた振る舞いを変えずにソフトウェアを再構築する。
===コードの不吉なにおい===
*重複したコード
*接続拒否(継承した操作、属性が利用されず混乱が引き起こされている)
*コメント(非常にわかりにくいコードを補うためのコメント)
===リファクタリングカタログ[[リファクタリング]]カタログ===
====メソッドの構成====
=====メソッドの抽出=====
#メソッド本体をコール元にインライン化
=====一時変数のインライン化=====
#簡単な式によって一度だけ代入される一時変数があり、他のリファクタリングの障害となっている簡単な式によって一度だけ代入される一時変数があり、他の[[リファクタリング]]の障害となっている
#一時変数への参照を式で置き換え
double basePrice = anOrder.basePrice();
#式の結果または部分的な結果を目的を説明する名前をつけた一時変数に代入する
if ( (platform.tuUpperCase().indexOf("MAC") > -1 ) &&
(browser.toUpperCase().indexOf("[[IE]]") > -1) {
:
}
[[File:0047_arrow_b.jpg]]
final boolean isMacOs is[[Mac]]Os = platform.tuUpperCase().indexOf("MAC") > -1; final boolean isIEBrowser is[[IE]]Browser = browser.toUpperCase().indexOf("[[IE]]") > -1; if (isMacOs is[[Mac]]Os && isIEBrowser) { ... }
=====一時変数の分離=====
#複数回代入される一時変数があるが、ループ変数でも、一時変数を集めるものでもない
}
}
=====アルゴリズムの取替え[[アルゴリズム]]の取替え=====#メソッドの本体を新たなアルゴリズムで置き換えるメソッドの本体を新たな[[アルゴリズム]]で置き換える
====オブジェクト間での特性の移動====
=====メソッドの移動 =====
#利用中のサーバクラスにメソッドを追加する必要があるが、そのクラスを変更できない
#クライアントクラスに、サーバクラスのインスタンスを第1引数にとるメソッドを作る
Data newStart = new Date(previousEndpre[[vi]]ousEnd.getYear(), previousEndpre[[vi]]ousEnd.getMonth(), previousEndpre[[vi]]ousEnd.getDate() + 1);
[[File:0047_arrow_b.jpg]]
Date newStart = nextDay(previousEndpre[[vi]]ousEnd);
private static Date nextDay(Date arg) {
return new Date(arg.getYear(), arg.getMonth(), arg.getDate() + 1);
#データをドメインオブジェクトにコピーして、それらを同期させるためのオブザーバを設ける
=====単方向関連の双方向への変更=====
#2つのクラスが互いにその特性を使う必要があるが、単方向のリンクしかない2つのクラスが互いにその特性を使う必要があるが、単方向の[[リンク]]しかない
#逆ポインタを加えて、両方の集合を更新するように更新操作を変更する
=====双方向関連の単方向への変更=====
#複雑な条件記述(if-the-else)がある
#条件記述部をthen部およびelse部からメソッドを抽出する
if (date.before(SUMMER_STARTSUMME[[R]]_STA[[R]]T) || date.after(SUMMER_ENDSUMME[[R]]_END)) charge = quantity * _winterRate + _winterServiceCharge_winterSer[[vi]]ceCharge; else charge = quantity * _summerRate_summer[[R]]ate;
[[File:0047_arrow_b.jpg]]
if (notSummer(date))
=====ガード節による入れ子条件記述の置き換え=====
#メソッドに正常ルートが不明確な条件付振る舞いがある
#特殊ケースすべてに対してガード節(メソッド内で、処理がメインロジックに到達するのを防ぐためのコードメソッド内で、処理がメイン[[ロジック]]に到達するのを防ぐためのコード)を使う
double getPayAmount() {
double result;
if (_isSeparated) result = separatedAmount();
esle {
if (_isRetired_is[[R]]etired) result = retiredAmount();
else result = normalPayAmount();
}
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired_is[[R]]etired) return retiredAmount();
return normalPayAmount();
}
double getSpeed() {
switch (_type) {
case EUROPEANEU[[R]]OPEAN:
return getBaseSpeed();
case AFRICANAF[[R]]ICAN:
return getBaseSpeed() - getLoadFactor() * _numberOfCoconuts;
case NORWEGIAN_BLUENO[[R]]WEGIAN_BLUE:
return (_isNailed)?0:getBaseSpeed(_voltage);
}
throw new RuntimeException[[R]]untimeException("ここには来ないはず");
}
[[File:0047_arrow_b.jpg]]
_width = value
else
Assert.shouldNeverReacheHereshouldNever[[R]]eacheHere();
}
[[File:0047_arrow_b.jpg]]
#あるオブジェクトから複数の値を取得し、それらの値をメソッド呼び出しの引数として渡している
#オブジェクトそのものを渡す
int low = daysTempRangedaysTemp[[R]]ange().getLow(); int high = daysTempRangedaysTemp[[R]]ange().getHigh(); withinPlan = plan.withinRangewithin[[R]]ange(low, high);
[[File:0047_arrow_b.jpg]]
withinPlan = plan.withinRangewithin[[R]]ange(daysTempRangedaysTemp[[R]]ange());
=====メソッドによる引数の置き換え=====
#あるオブジェクトがメソッドを呼び出し、その戻り値を別のメソッドの引数として渡している。受信側はそのメソッドを呼び出し可能である
#メソッドが返すオブジェクトが、呼び出し側によってダウンキャストされる必要がある
#ダウンキャストをメソッド内に移動する
Object lastReadinglast[[R]]eading() {
return readings.lastElements();
}
[[File:0047_arrow_b.jpg]]
Reading lastReading[[R]]eading last[[R]]eading() { return (Reading[[R]]eading) readlings.lastElement();
}
=====例外によるエラーコードの置き換え=====