Horizontal task integration via Python decorator

Rain Wu
Random Life Journal
4 min readMay 18, 2020

Decorator is an extremely powerful weapon for Pythoners to increase the readability and scalability of our code, through very effective reduction of duplicated code and lower cost of refactoring. Because of this, decorator is often used as a key indicator to identify the level of a Python software engineer.

In this note, I will try to explain how the decorator improves the structure of the program with the example of making coffee in daily life :)

How to Make Coffee

Suppose we already have some coffee beans, and we are going to make different kinds of coffee…, or store the coffee beans for next week.

  • make cold drip coffee
  • make cold brew coffee
  • store coffee beans for next week

If we think more carefully, we can arrange the steps like below :

  • make cold drip coffee
    - roast coffee beans
    - grind coffee beans
    - make cold drip coffee
  • make cold brew coffee
    - roast coffee beans
    - grind coffee beans
    - make cold brew coffee
  • store coffee beans for next week
    - roast coffee beans
    - store coffee beans

Now you can find that the first step in everything is roasting coffee beans, this is a very suitable occasion for using decorators.

Scrape some parts horizontally.

Roast Coffee Beans

Let’s implement our first decorator for roasting coffee beans, remember to import wraps and partial from module functools.

The first parameter in decorator functions must be the target function that we are going to wrap, and follows by some extra parameters for advanced configurations. The slash sign ‘/’ in parameter list is a new syntax in python 3.8, which means parameter on the left hand side is positional-only, you can refer to the documents for advanced information.

I usually check the parameter requirements just inside the decorator first, instead of packaging it into the callable return object. Because this is the content of the decorator, this ensures that the wrapped function works as expected. We want to detect errors during the wrapping time, rather than rasiing an error when it is executed.

The return object is a wrapped function, the parameters used to call the function could be passed via (*args, **kwargs), then the returned value can be passed back in reverse, just like the function call stack. The only thing that decorator does is adding the code to print out roasting message.

Now we can attach it on the store coffee beans step :

Finish roasting coffee beans with level 6
Seperated: True
Vacuum: False
Coffee already stored for next week.

Grind Coffee Beans

For the process of making two different kinds of coffee, the matter of ground coffee beans can be further separated. Then we construct another decorator :

The structure is similar to the previous decorator, but with one more parameter. We also detect unreasonable parameters in the decorator, which will facilitate our debugging.

Make Coffee

With the help of the above two decorators, we can finish all steps of making any kind of coffee easily. The only thing we need to pay attention is the order of decorators, coffee beans needs to be roasted before grinding, right?

Finish roasting coffee beans with level 5
Finish grinding coffee beans with burr grinder, dialing in level 2
Sugar free: True
Ice free: True
Here’s your cold drip coffee.
Finish roasting coffee beans with level 6
Finish grinding coffee beans with burr grinder, dialing in level 2
Sugar free: True
Ice free: True
Here’s your cold brew coffee.

For convenience of explanation, the two functions are very similar, but in actual development, this is almost never the case, and the decorator may be carried by various functions. We do not need to target sub-tasks that are difficult to separate to avoid getting over-designed.

That’s the way how Python decorator help us improve our workflow when we make coffee in our daily life, hope this note improves your usage of decorators, too :).

--

--

Rain Wu
Random Life Journal

A software engineer specializing in distributed systems and cloud services, desire to realize various imaginations of future life through technology.