如何提高函数的可读性?


下面哪个版本的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)一书中进一步了解这一主题。