《重构 改善既有代码的设计》
重构方法速查表,通过示例来快速回忆出对应重构方法的内容,并给出中文第2版书中对应的页码。😜
格式:章节号 重构方法名称( 重构方法英文名称)[页码]
第6章 第一组重构
6.1 提炼函数(Extract Function)[106]
function printOwing(invoice) {
printBanner();
let outstanding = calculateOutstanding();
//print details
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
}
👇
function printOwing(invoice) {
printBanner();
let outstanding = calculateOutstanding();
function printDetails(outstanding) {
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
}
}
6.2 内联函数(Inline Function)[115]
function getRating(driver) {
return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}
function moreThanFiveLateDeliveries(driver) {
return driver.numberOfLateDeliveries > 5;
}
👇
function getRating(driver) {
return (driver.numberOfLateDeliveries > 5) ? 2 : 1;
}
6.3 提炼变量(Extract Variable)[119]
return order.quantity * order.itemPrice -
Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +
Math.min(order.quantity * order.itemPrice * 0.01, 100);
👇
const basePrice = order.quantity * order.itemPrice;
const quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;
const shipping = Math.min(order.quantity * order.itemPrice * 0.01, 100);
return basePrice - quantityDiscount + shipping;
6.4 内联变量(Inline Variable)[123]
let basePrice = anOrder.basePrice;
return (basePrice > 1000);
👇
return anOrder.basePrice > 1000;
6.5 改变函数签名(Change Function Declaration)[124]
把“声明”改为了“签名”
function circum(radius) {... }
👇
function circumference(radius) {... }
6.6 封装变量(Encapsulate Variable)[132]
let defaultOwner = { firstName: "Martin", lastName: "Fowler" };
👇
let defaultOwnerData = { firstName: "Martin", lastName: "Fowler" };
export function defaultOwner() { return defaultOwnerData; }
export function setDefaultOwner(arg) { defaultOwnerData = arg; }
6.7 提炼函数(Rename Variable)[137]
let a = height * width;
👇
let area = height * width;
6.8 引入参数对象(Introduce Parameter Object)[140]
function amountInvoiced(startDate, endDate) {... }
function amountReceived(startDate, endDate) {... }
function amountOverdue(startDate, endDate) {... }
👇
function amountInvoiced(aDateRange ) {... }
function amountReceived(aDateRange ) {... }
function amountOverdue(aDateRange ) {... }
6.9 函数组合成类(Combine Functions into Class)[144]
function base(aReading) {... }
function taxableCharge(aReading) {... }
function calculateBaseCharge(aReading) {... }
👇
class Reading {
base(aReading) {... }
taxableCharge(aReading) {... }
calculateBaseCharge(aReading) {... }
}
6.10 函数组合成变换(Combine Functions into Transform)[149]
function base(aReading) {... }
function taxableCharge(aReading) {... }
👇
function enrichReading(argReading) {
const aReading = _.cloneDeep(argReading);
aReading.baseCharge = base(aReading);
aReading.taxableCharge = taxableCharge(aReading);
return aReading;
}
6.11 拆分阶段(Split Phase)[154]
const orderData = orderString.split(/\s+/);
const productPrice = priceList[orderData[0].split("-")[1]];
const orderPrice = parseInt(orderData[1]) * productPrice;
👇
const orderRecord = parseOrder(order);
const orderPrice = price(orderRecord, priceList);
function parseOrder(aString) {
const values = aString.split(/\s+/);
return ({
productID: values[0].split("-")[1],
quantity: parseInt(values[1]),
});
}
function price(order, priceList) {
return order.quantity * priceList[order.productID];
}
第7章 封装
7.1 封装记录(Encapsulate Record)[162]
organization = {name: "Acme Gooseberries", country: "GB"};
👇
class Organization {
constructor(data) {
this._name = data.name;
this._country = data.country;
}
get name() {return this._name;}
set name(arg) {this._name = arg;}
get country() {return this._name;}
set country(arg) {this._country = arg;}
}
7.2 封装集合(Encapsulate Collection)[170]
class Person {
get courses() {this._courses;}
set courses() {this._courses;}
}
👇
class Person {
get courses() {this._courses.slice();}
addCourse(aCourse) {...}
removeCourse(aCourse) {...}
}
7.3 以对象取代基本类型(Replace Primitive with Object)[174]
orders.filter(o => "high" === o.priority
|| "rush" === o.priority);
👇
orders.filter(o => o.priority.higherThan(new Priority("normal")))
7.4 以查询取代临时变量(Replace Temp with Query)[178]
const basePrice = this._quantity * this._itemPrice;
if (basePrice > 1000)
return basePrice * 0.95;
else
return basePrice * 0.98;
👇
get basePrice() { this._quantity * this._itemPrice;}
...
if (this.basePrice > 1000)
return this.basePrice * 0.95;
else
return this.basePrice * 0.98;
7.5 提炼类(Extract Class)[182]
class Person {
get officeAreaCode() {return this._officeAreaCode;}
get officeNumber() {return this._officeNumber;}
}
👇
class Person {
get officeAreaCode() {
return this._telephoneNumber.areaCode;
}
get officeNumber() {
return this._telephoneNumber.number;
}
}
class TelephoneNumber {
get areaCode() {return this._areaCode;}
get number() {return this._number;}
}
7.6 内联类(Inline Class)[186]
class Person {
get officeAreaCode() {
return this._telephoneNumber.areaCode;
}
get officeNumber() {
return this._telephoneNumber.number;
}
}
class TelephoneNumber {
get areaCode() {return this._areaCode;}
get number() {return this._number;}
}
👇
class Person {
get officeAreaCode() {return this._officeAreaCode;}
get officeNumber() {return this._officeNumber;}
}
7.7 隐藏委托关系(Hide Delegate)[189]
member = aPerson.department.manager;
👇
manager = aPerson.manager;
class Person {
get manager() {this._department.manager;}
}
7.8 移出中间人(Remove Middle Man)[192]
manager = aPerson.manager;
class Person {
get manager() {this._department.manager;}
}
👇
member = aPerson.department.manager;
7.9 替换算法(Substitute Algorithm)[195]
function foundPerson(people) {
for (let i = 0; i < people.length; i++) {
if (people[i] === "Don") {
return "Don";
}
if (people[i] === "John") {
return "John";
}
if (people[i] === "Kent") {
return "Kent";
}
}
return "";
}
👇
function foundPerson(people) {
const candidates = [];
return people.find(p => candidates.includes(p)) || '';
}
第8章 搬移特性
8.1 搬移函数(Move Function)[198]
class Account {
get overdraftCharge() {...}
}
👇
class AccountType {
get overdraftCharge() {...}
}
8.2 搬移字段(Move Field)[207]
class Customer {
get plan() {return this._plan;}
get discountRate() {return this._discountRate;}
}
👇
class Customer {
get plan() {return this._plan;}
get discountRate() {return this.plan.discountRate;}
}
8.3 搬移语句到函数(Move Statements into Function)[213]
result.push(`<p>title:${person.photo.title}</p>`);
result.concat(photoData(person.photo));
function photoData(aPhoto) {
return [
`<p>location:${aPhoto.location}</p>`,
`<p>date:${aPhoto.date.toDateString}</p>`
];
}
👇
result.concat(photoData(person.photo));
function photoData(aPhoto) {
return [
`<p>title:${`<p>title:${person.photo.title}</p>`.title}</p>`,
`<p>location:${aPhoto.location}</p>`,
`<p>date:${aPhoto.date.toDateString}</p>`
];
}
8.4 搬移语句到函数(Move Statements into Callers)[217]
result.concat(photoData(person.photo));
function photoData(aPhoto) {
return [
`<p>title:${`<p>title:${person.photo.title}</p>`.title}</p>`,
`<p>location:${aPhoto.location}</p>`,
`<p>date:${aPhoto.date.toDateString}</p>`
];
}
👇
result.push(`<p>title:${person.photo.title}</p>`);
result.concat(photoData(person.photo));
function photoData(aPhoto) {
return [
`<p>location:${aPhoto.location}</p>`,
`<p>date:${aPhoto.date.toDateString}</p>`
];
}
8.5 以函数调用替代内联代码(Replace Inline Code with Function Call)[222]
let appliesToMass = false;
for(const s of states) {
if (s === 'MA') appliesToMass = true;
}
👇
appliesToMass = states.includes("MA");
8.6 移动语句(Slide Statements)[223]
const pricingPlan = retrievePricingPlan();
const order = retreiveOrder();
let charge;
const chargePerUnit = pricingPlan.unit;
👇
const pricingPlan = retrievePricingPlan();
const order = retreiveOrder();
const chargePerUnit = pricingPlan.unit;
let charge;
8.7 拆分循环(Split Loop)[227]
let averageAge = 0;
let totalSalary = 0;
for(const p of people) {
averageAge += p.age;
totalSalary += p.salary;
}
averageAge = averageAge / people.length;
👇
let averageAge = 0;
for(const p of people) {
totalSalary += p.salary;
}
let totalSalary = 0;
for(const p of people) {
averageAge += p.age;
}
averageAge = averageAge / people.length;
8.8 以管道取代循环(Replace Loop with Pipeline)[231]
const names = [];
for(const i of input) {
if (i.job === "Programmer") {
names.push(i.name);
}
}
👇
const names = input
.filter(i => i.job === "Programmer")
.map(i => i.name)
;
8.9 移出死代码(Remove Dead Code)[237]
if(false){
doSomethingThatUsedToMatter();
}
👇