跳转到内容

移动语句

移动语句(Slide Statements)把相关的几行代码挪到一起,比如把变量的声明挪到第一次使用它的地方旁边。 它解决的痛是:读一段代码时,相关的东西散在各处,要上下来回翻才能拼出完整的意思。

一个下单函数在开头一口气声明了所有变量,中间夹着库存检查,最后才用到其中几个。

"""下单:移动前。"""
def place_order(stock: int, qty: int, unit_price: float) -> str:
discount = 0.1 if qty >= 10 else 0.0
shipping = 0.0 if qty >= 10 else 8.0
if qty > stock:
return "库存不足"
subtotal = qty * unit_price
return f"应付 {subtotal * (1 - discount) + shipping:.2f}"
if __name__ == "__main__":
print(place_order(5, 8, 10), place_order(20, 10, 10))
# 输出:
# 库存不足 应付 90.00
// 下单:移动前。
function placeOrder(stock: number, qty: number, unitPrice: number): string {
const discount = qty >= 10 ? 0.1 : 0;
const shipping = qty >= 10 ? 0 : 8;
if (qty > stock) return "库存不足";
const subtotal = qty * unitPrice;
return `应付 ${(subtotal * (1 - discount) + shipping).toFixed(2)}`;
}
console.log(placeOrder(5, 8, 10), placeOrder(20, 10, 10));
// 输出:
// 库存不足 应付 90.00
"""下单:移动后。"""
def place_order(stock: int, qty: int, unit_price: float) -> str:
if qty > stock:
return "库存不足"
subtotal = qty * unit_price
discount = 0.1 if qty >= 10 else 0.0
shipping = 0.0 if qty >= 10 else 8.0
return f"应付 {subtotal * (1 - discount) + shipping:.2f}"
if __name__ == "__main__":
print(place_order(5, 8, 10), place_order(20, 10, 10))
# 输出:
# 库存不足 应付 90.00
// 下单:移动后。
function placeOrder(stock: number, qty: number, unitPrice: number): string {
if (qty > stock) return "库存不足";
const subtotal = qty * unitPrice;
const discount = qty >= 10 ? 0.1 : 0;
const shipping = qty >= 10 ? 0 : 8;
return `应付 ${(subtotal * (1 - discount) + shipping).toFixed(2)}`;
}
console.log(placeOrder(5, 8, 10), placeOrder(20, 10, 10));
// 输出:
// 库存不足 应付 90.00

库存检查挪到了最前面,读者一眼看到“库存不够直接返回”;算钱的四行挨在一起,下一步把它们提炼成一个 amount_due 函数(第 4 章)就很自然。

移动语句:调整语句的顺序,把彼此相关的语句放在一起。它很少单独做,通常是提炼函数的准备步骤:要提炼的代码先得挨在一起。移动前要确认两条语句之间没有依赖:一条修改了另一条要读的变量、两条都有副作用(写文件、改全局状态)时,交换顺序会改变行为。只读、无副作用的语句可以放心移动。

两段代码之间有隐含的顺序依赖,比如先打开连接再查询、先加锁再修改,看不出依赖时别动。移动一次、跑一次测试,小步走。