The code in the red is imperative, with implicit state all over the place. I would argue that it's not linear, you have to keep all those mutable values and state transitions in your head as you read what's happening from top to bottom.<p>It's not extensible, It's not composable, It's hard to test, and frankly, it's complicated and complex for no other reason than a particular type of engineer thinks its easier to read, because they feel all programming should be imperative.<p>Don't get me wrong, there's a time and a place for this style of programming. (Manual memory management, algorithmic design that maximizes speed or memory usage, or even taking a bunch of services and dictating the order in which they are supposed to be executed.)<p>For business logic, especially the type thats supposed to model "the world," this is terrible code.<p>How is the bottom, not better code?<p><pre><code> type Oven struct {
Temp int
}
type Box struct {
// Box properties
}
type Pizza struct {
Base string
Sauce string
Cheese string
Toppings []string
Baked bool
Boxed bool
Sliced bool
Ready bool
}
type Order struct {
Size string
Sauce string
Kind string
}
func preparePizza(order *Order) *Pizza {
toppings := map[string][]string{
"Veg": []string{"Tomato", "Bell Pepper"},
"Meat": []string{"Pepperoni", "Sausage"},
}
return &Pizza{
Base: order.Size,
Sauce: order.Sauce,
Cheese: "Mozzarella",
Toppings: toppings[order.Kind],
}
}
func bakePizza(oven *Oven, pizza *Pizza, cookingTemp int, checkOvenInterval int) *Pizza {
// Simulate oven heating
for oven.Temp < cookingTemp {
time.Sleep(time.Duration(checkOvenInterval) * time.Millisecond)
oven.Temp += 10 // Simulate oven heating
}
pizza.Baked = true
return pizza
}
func boxPizza(pizza *Pizza, order *Order) *Pizza {
box := &Box{}
pizza.Boxed = true // Simulate putting pizza in box
pizza.Sliced = true // Simulate slicing pizza
pizza.Ready = true // Simulate closing box
return pizza
}
// I just need to really understand this imperative part
// this is the meat and potatoes
func createPizza(order *Order, oven *Oven, cookingTemp int, checkOvenInterval int) *Pizza {
pizza := preparePizza(order)
pizza = bakePizza(oven, pizza, cookingTemp, checkOvenInterval)
pizza = boxPizza(pizza, order)
return pizza
}</code></pre>