下面哪个版本的createPizza函数更容易理解?
func createPizza(order *Order) *Pizza {
pizza := &Pizza{Base: order.Size, Sauce: order.Sauce, Cheese: “Mozzarella”}
if order.kind == “Veg” { pizza.Toppings = vegToppings } else if order.kind == “Meat” { pizza.Toppings = meatToppings } oven := oven.New() if oven.Temp != cookingTemp { for (oven.Temp < cookingTemp) { time.Sleep(checkOvenInterval) oven.Temp = getOvenTemp(oven) } }
if !pizza.Baked { oven.Insert(pizza) time.Sleep(cookTime) oven.Remove(pizza) pizza.Baked = true }
box := box.New() pizza.Boxed = box.PutIn(pizza) pizza.Sliced = box.SlicePizza(order.Size) pizza.Ready = box.Close() return pizza
}
第二个: func createPizza(order *Order) *Pizza { pizza := prepare(order) bake(pizza) box(pizza) return pizza }
func prepare(order *Order) *Pizza { pizza := &Pizza{Base: order.Size, Sauce: order.Sauce, Cheese: “Mozzarella”} addToppings(pizza, order.kind) return pizza
}
func addToppings(pizza *Pizza, kind string) { if kind == “Veg” { pizza.Toppings = vegToppings } else if kind == “Meat” { pizza.Toppings = meatToppings }
}
func bake(pizza *Pizza) { oven := oven.New() heatOven(oven) bakePizza(pizza, oven) }
func heatOven(oven *Oven) { … } func bakePizza(pizza *Pizza, oven *Oven) { … } func box(pizza *Pizza) { … }
|
你可能说第二个更容易,但为什么呢?
第一个混合了几个层次的抽象:低级实现细节(如如何加热烤箱)、中级功能(如如何烤披萨)和高级抽象(如准备、烤制和装箱)。
createPizza 是一个高级函数,它将准备、烘烤和装盒步骤委托给了具有直观名称的低级专门函数。这些函数反过来又委托给各自的低级专门函数(如 heatOven),直到它们到达一个无需调用其他函数就能处理执行细节的函数为止。
避免将不同的抽象层混合到一个函数中。在相同的抽象层中嵌套函数,以提供一种叙述方式。这种自文档风格更易于跟踪、调试和重用。
您可以在罗伯特-C-马丁(Robert C. Martin)所著的《清洁代码》(Clean Code)一书中进一步了解这一主题。