Over the past few years, working remotely from home has given me many more opportunities to cook, and my skills have improved considerably. These days, for an ordinary home-style dish I’ve never tried before, I can roughly reproduce its flavor by following a video tutorial online. The reason, I think, is that I’ve applied the idea of modularity from coding to cooking.
Cooking can be roughly divided into three stages:
- Preparation: preprocessing such as cutting, marinating, and removing unwanted smells (e.g., the fishiness of fish);
- Cooking: the actual cooking with techniques we usually talk about — boiling, red-braising, pan-frying, stir-frying, steaming, and so on;
- Finishing: after cooking, some final touches are still needed, such as reducing the sauce over high heat, or pouring hot oil over a steamed fish.
With the modular mindset from programming, once these stages are divided into concrete modules, different dishes can be created by combining and recombining the modules. For example, red-braised fish and steamed fish are two very different ways of cooking fish, yet they share the same preparation stage:
- Preparation: remove the fishiness, and score the back of the fish so it absorbs flavor more easily;
- Cooking:
- Steamed fish: steam it;
- Red-braised fish: braise it in a soy-sauce-based sauce;
- Finishing:
- Steamed fish: discard the water in the steaming container (it’s too fishy), lay shredded scallions over the fish, and pour hot oil on top;
- Red-braised fish: reduce the sauce over high heat.
As you can see, no matter how the fish is cooked, the preparation stage is largely the same. In programming terms: this module is reusable. Once you’ve learned how to prep a fish for steaming, you can handle a fish destined for any other cooking method in much the same way.
Similarly, other stages have reusable modules too. For instance, the red-braising step in red-braised fish and red-braised pork belly is largely the same — you braise the ingredient in a sauce made with various seasonings, differing only in the choice of ingredients and the cooking time. So once you know how to red-braise a fish, with a little adaptation you can also learn how to red-braise pork.
So, by dividing the cooking process into stages, you end up with many reusable modules. Arranging and combining these modules differently yields different dishes.
This is why, when watching cooking tutorials now, I deliberately look at them this way:
- What are the three stages of this dish? Which ones haven’t I mastered yet, and which ones are similar to processes I already know and can reuse with small tweaks?
- What seasonings does the dish use, and in what proportions?
- How well done does it need to be — what does the “heat” (cooking intensity and timing) look like?
You can see that looking at dish preparation through the lens of stage division and module reuse makes everything much clearer.
Beyond that, when implementing a specific module, you can even borrow ideas from object-oriented programming. Take one step of red-braised pork: “coloring the food.” There are two common ways to do it:
- Fry sugar in oil or water until it caramelizes, and use the caramelized sugar for coloring;
- Simply use dark soy sauce for coloring.
In OOP terms, “coloring the food” is an interface, and the two methods above are two different implementations. As for me, I can never quite nail the heat when caramelizing sugar, so for the same interface I choose the dark-sauce implementation, which is easier for me. This doesn’t hurt the overall result, because there’s another saying in software design: done is better than perfect.
Similarly, once a dish is broken down into multiple steps, if some step isn’t your strong suit, you can hand it off to someone else, or use a semi-finished product that only needs simple processing. For example, if you don’t know how to slaughter a chicken or duck, you have a few options:
- Outsource that step to the market vendor and let them do it;
- Or buy a bagged frozen chicken — the flavor is slightly worse.
The following picture uses pizza as an example to explain the differences between various XaaS (X as a Service) offerings. Essentially, outsourcing different steps means consuming some kind of service:
A quick summary:
- Master the “modules” frequently used in cooking — red-braising, steaming, marinating — because these modules get reused across many dishes;
- Divide a dish into several distinct stages to make modules reusable, so you can combine modules you already know to complete dishes you don’t;
- Outsource the modules you’re not good at, and find suitable services as substitutes;
- Done is better than perfect — being able to complete a dish independently, with the help of different services, slowly builds your confidence in this domain.
My investment in cooking over these years has also led to another insight. The Chinese word 火候 (huǒhòu) is truly marvelous: 火 (fire) emphasizes doing work on the food, while 候 (waiting) reminds you to patiently let time do its part. There seems to be no faithful and elegant translation of 火候 in English — a literal translation would be “Fire Control,” but that drops the sense of time inherent in the Chinese word. The same is true for 功夫 (gōngfu): in English, “KungFu” only means martial arts, whereas in Chinese it doesn’t refer to martial arts alone — nowadays it more often means the time and effort invested in something.