1. 简介
名字:Extract Method(提炼函数)
页码:110
1.1. 概要
你有一段代码可以被组织在一起并独立出来。
将这段代码放进一个独立函数中,并让函数名称解释该函数的用途
1.2. 动机
- 函数过长
- 需要注释才能看得懂的函数
- 短小的函数被复用的机会多
- 读函数名如读注释(不要在意函数名长度)
1.3. 做法
- 创造一个新函数,根据这个函数的意图来命名(以“做什么”来命名)
- 将提炼出的代码从源函数复制到新建的目标函数中
- 检查变量的作用域
- 检查是否有“仅用于被提炼代码段”的临时变量。如果有,在目标函数中将它们声明为临时变量
- 检查是否有任何局部变量的值被它改变(1. 将被改变的值作为函数返回值。2. 使用Split Temporary Variable(128)。3. 使用Replace Temp with Query(120)。)
- 将被提炼代码段中需要读取的局部变量,当做参数传递给目标函数
- 在源函数中,将被提炼代码替换为对目标函数的调用
- 编译,测试
2. 范例
// 1. =========================================================
// 原代码
void printOwing(double amount){
printBanner();
// print details
System.out.println("name: " + _name);
System.out.println("amount" + amount);
}
// --------------------------------------------------------
// 优化后
void printOwing(double amount){
printBanner();
printDetails(amount);
}
void printDetails(double amount){
System.out.println("name: " + _name);
System.out.println("amount" + amount);
}
// 2. =========================================================
// 无局部变量
// 原函数
void printOwing(){
Enmeration e = _orders.elements();
double outstanding = 0.0;
// print banner
System.out.println("*************************");
System.out.println("***** Customer Owes *****");
System.out.println("*************************");
// calculate outstanding
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
// print details
System.out.println("name: " + _name);
System.out.println("amount" + outstanding);
}
// --------------------------------------------------------
// 优化后
void printOwing(){
Enmeration e = _orders.elements();
double outstanding = 0.0;
// print banner
printBanner();
// calculate outstanding
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
// print details
System.out.println("name: " + _name);
System.out.println("amount" + outstanding);
}
void printBanner(){
System.out.println("*************************");
System.out.println("***** Customer Owes *****");
System.out.println("*************************");
}
// 3. =========================================================
// 有局部变量
// 原函数
void printOwing(){
Enmeration e = _orders.elements();
double outstanding = 0.0;
// print banner
printBanner();
// calculate outstanding
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
// print details
System.out.println("name: " + _name);
System.out.println("amount" + outstanding);
}
// --------------------------------------------------------
// 优化后
void printOwing(){
Enmeration e = _orders.elements();
double outstanding = 0.0;
// print banner
printBanner();
// calculate outstanding
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
// print details
printDetails(outstanding);
}
void printDetails(double outstanding){
System.out.println("name: " + _name);
System.out.println("amount" + outstanding);
}
// 4. =========================================================
// 对局部变量再赋值
// 如果原函数的参数被赋值,应该使用Remove Assignments to Parameters(131)
// 1. 如果练市变量只在被提炼代码中使用,则在被提炼代码中重新声明
// 2. 被提炼代码之外也使用这个临时变量
// 1. 在提炼代码之后未被使用,则作为参数传入提炼代码
// 2. 在提炼代码之后继续被使用,则传入参数后,最后作为返回值
// 原函数
void printOwing(){
Enmeration e = _orders.elements();
double outstanding = 0.0;
// print banner
printBanner();
// calculate outstanding
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
// print details
printDetails(outstanding);
}
// 4.1 --------------------------------------------------------
// 提炼优化后
void printOwing(){
// print banner
printBanner();
// calculate outstanding
double outstanding = getOutStanding();
// print details
printDetails(outstanding);
}
double getOutStanding(){
Enmeration e = _orders.elements();
double outstanding = 0.0;
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
return outstanding;
}
// 4.2 --------------------------------------------------------
// 命名优化后
double getOutStanding(){
Enmeration e = _orders.elements();
double result = 0.0;
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
result += each.getAmount();
}
return result;
}
// 5. =========================================================
// 对局部变量再赋值
// 在提炼代码之后继续被使用,则传入参数后,最后作为返回值
// 原函数
void printOwing(double previousAmount){
Enmeration e = _orders.elements();
double outstanding = previousAmount * 1.2;
// print banner
printBanner();
// calculate outstanding
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
outstanding += each.getAmount();
}
// print details
printDetails(outstanding);
}
// 5.1 --------------------------------------------------------
// 提炼优化后
void printOwing(double previousAmount){
double outstanding = previousAmount * 1.2;
// print banner
printBanner();
// calculate outstanding
outstanding = getOutStanding(outstanding);
// print details
printDetails(outstanding);
}
double getOutStanding(double initialVale){
double result = initialVale;
Enmeration e = _orders.elements();
while (e.hasMoreElements()){
Order each = (Oder) e.nextElement();
result += each.getAmount();
}
return result;
}
// 5.2 --------------------------------------------------------
// 初始化优化后
void printOwing(double previousAmount){
// print banner
printBanner();
// calculate outstanding
double outstanding = getOutStanding(previousAmount * 1.2);
// print details
printDetails(outstanding);
}