メソッドの抽出をすると、リファクタリングしやすくなることがあります。
ここでは、簡単に実践可能なリファクタリングを紹介します。
適用前と適用後の違いを見比べてみてください。
目的を正しく表すように、変数やメソッドの名前を変更する
適用前
boolean osFlag = platform.toUpperCase().indexOf(“WINDOWS”) > -1;
boolean ieFlag = browser.toUpperCase().indexOf(“IE”) > -1;
if (osFlag && ieFlag) {
// 省略
}
適用後
boolean isWindows = platform.toUpperCase().indexOf(“WINDOWS”) > -1;
boolean isIEBrowser = browser.toUpperCase().indexOf(“IE”) > -1;
if (isWindows && isIEBrowser) {
// 省略
}
長すぎるメソッドや、コメントが無ければ理解できないメソッドに対して、その断片をメソッド化し、目的をあらわすような名前をつける
適用前
if (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)) {
// 省略
}
適用後
if (isLeapYear(year)) {
// 省略
}
-----------------------------------------------------------------------
private boolean isLeapYear(int year) {
return year % 4 == 0 && (year % 100 != 0 || year % 400 == 0);
}
式の結果、または部分的な結果をその目的を説明する名前をつけた一時変数に代入する
適用前
if ((platform.toUpperCase().indexOf(“WINDOWS”) > -1) && (browser.toUpperCase().indexOf(“IE”) > -1)) {
// 省略
}
適用後
final boolean isWindows = platform.toUpperCase().indexOf(“WINDOWS”) > -1;
final boolean isIEBrowser = browser.toUpperCase().indexOf(“IE”) > -1;
if (isWindows && isIEBrowser) {
// 省略
}
メソッドの出口を複数にし、制御フラグを削除する
適用前
// 省略
String[] languages = {“C”, “C++”, “Java”, “Perl”};
// 省略
boolean found = false;
for (int i = 0; i < languages.length; i++) {
if (languages[i].indexOf(“Java”) > -1) {
found = true;
break;
}
if (languages[i].indexOf(“C++”) > -1) {
found = true;
break;
}
}
if (found) System.out.println(“OOP language Found ...”);
// 省略
「メソッドの抽出」適用後
// 省略
String[] languages = {“C”, “C++”, “Java”, “Perl”};
// 省略
if (isOOPLanguage(languages)) System.out.println(“OOP language Found ...”);
// 省略
------------------------------------------------------------------------------
private boolean isOOPLanguage(String[] languages) {
boolean found = false;
for (int i = 0; i < languages.length; i++) {
if (languages[i].indexOf(“Java”) > -1) {
found = true;
break;
}
if (languages[i].indexOf(“C++”) > -1) {
found = true;
break;
}
}
return found;
}
「制御フラグの削除」適用後
// 省略
String[] languages = {“C”, “C++”, “Java”, “Perl”};
// 省略
if (isOOPLanguage(languages)) System.out.println(“OOP language Found ...”);
// 省略
------------------------------------------------------------------------------
private boolean isOOPLanguage(String[] languages) {
for (int i = 0; i < languages.length; i++) {
if (languages[i].indexOf(“Java”) > -1) return true;
if (languages[i].indexOf(“C++”) > -1) return true;
}
return false;
}
ルートが不明確な条件付振る舞いを整理し、ルートを明確にする
適用前
String number = “12345”;
// 省略
boolean isAnswerNumber = false;
if (number == null) {
isAnswerNumber = false;
} else {
if (number.length() == 4) {
if (number.getBytes().length == 4) {
isAnswerNumber = true;
} else {
isAnswerNumber = false;
}
} else {
isAnswerNumber = false;
}
}
if (!isAnswerNumber) System.out.println(“Answer is incorrect ...”);
// 省略
「メソッドの抽出」適用後
String answerNumber = “12345”;
// 省略
if (!isAnswerNumber(answerNumber)) System.out.println(“Answer is incorrect ...”);
// 省略
-----------------------------------------------------------------------
private boolean isAnswerNumber(String number) {
boolean isAnswerNumber = false;
if (number == null) {
isAnswerNumber = false;
} else {
if (number.length() == 4) {
if (number.getBytes().length == 4) {
isAnswerNumber = true;
} else {
isAnswerNumber = false;
}
} else {
isAnswerNumber = false;
}
}
return isAnswerNumber;
}
「制御フラグの削除」適用後
String answerNumber = “12345”;
// 省略
if (!isAnswerNumber(answerNumber)) System.out.println(“Answer is incorrect ...”);
// 省略
-----------------------------------------------------------------------
private boolean isAnswerNumber(String number) {
if (number == null) {
return false;
} else {
if (number.length() == 4) {
if (number.getBytes().length == 4) {
return true;
} else {
return false;
}
} else {
return false;
}
}
}
「入れ子条件記述の置き換え」適用 その1
String answerNumber = “12345”;
// 省略
if (!isAnswerNumber(answerNumber)) System.out.println(“Answer is incorrect ...”);
// 省略
-----------------------------------------------------------------------
private boolean isAnswerNumber(String number) {
if (number == null) return false;
if (number.length() == 4) {
if (number.getBytes().length == 4) {
return true;
} else {
return false;
}
} else {
return false;
}
}
「入れ子条件記述の置き換え」適用 その2
String answerNumber = “12345”;
// 省略
if (!isAnswerNumber(answerNumber)) System.out.println(“Answer is incorrect ...”);
// 省略
-----------------------------------------------------------------------
private boolean isAnswerNumber(String number) {
if (number == null) return false;
if (number.length() != 4) return false;
if (number.getBytes().length == 4) {
return true;
} else {
return false;
}
}
「入れ子条件記述の置き換え」 適用後
String answerNumber = “12345”;
// 省略
if (!isAnswerNumber(answerNumber)) System.out.println(“Answer is incorrect ...”);
// 省略
-----------------------------------------------------------------------
private boolean isAnswerNumber(String number) {
if (number == null) return false;
if (number.length() != 4) return false;
if (number.getBytes().length != 4) return false;
return true;
}