Abstraction

Abstraction is another very general programming pattern that applies to more than just modular programming. Abstraction is essentially the process of hiding complexity: separating what you want to do from how to do it.

Abstraction is absolutely fundamental to all computer programming. Imagine, for example, that you had to write a program that calculates two averages and then figures out the difference between the two. A simplistic implementation of this program might look something like the following:

values_1 = [...]
values_2 = [...]

total_1 = 0
for value in values_1:
    total = total + value
average_1 = total / len(values_1)

total_2 = 0
for value in values_2:
    total = total + value
average_2 = total / len(values_2)

difference = abs(total_1 - total-2)
print(difference)

As you can see, the code that calculates the average of a list of numbers is repeated twice. This is inefficient, so you would normally write a function to avoid repeating yourself. This can be done in the following way:

values_1 = [...]
values_2 = [...]

def average(values):
    total = 0
    for value in values:
        total = total + value
    return = total / len(values)

average_1 = average(values_1)
average_2 = average(values_2)
difference = abs(total_1 - total-2)
print(difference)

Of course, you do this sort of thing every time you program, but it is actually quite an important process. When you create a function like this, the code inside the function deals with how to do something, while the code that calls that function simply knows what has to be done—and that the function will do it. In other words, the function hides the complexity of how the task is performed, allowing other parts of your program to simply call that function whenever they want that task to be performed.

This type of process is called abstraction. Using this pattern, you abstract away the details of how something is done so that the rest of your program doesn't need to worry about it.

Abstraction doesn't just apply to writing functions. The general principle of hiding complexity applies to groups of functions as well—and the module is a perfect way of grouping functions together. For example, your program might need to work with colors, and so you write a module named colors which contains various functions that allow you to create and work with color values. The various functions in the colors module know about color values and how to use them, so the rest of your program doesn't need to worry about it. Using this module, you could do all sorts of interesting things with colors. For example:

purple = colors.new_color(1.0, 0.0, 1.0)
yellow = colors.new_color(1.0, 1.0, 0.0)
dark_purple = colors.darken(purple, 0.3)
color_range = colors.blend(yellow, dark_purple, num_steps=20)
dimmed_yellow = colors.desaturate(yellow, 0.8)

Outside of this module, your code can simply concentrate on what it wants to do, without the slightest idea of how these various tasks are performed. By doing this, you are using the abstraction pattern to hide away the complexity of these color calculations from the rest of your program.

Abstraction is a fundamental technique for designing and writing modules and packages. For example, the Pillow library we used in the previous chapter provides a wide range of modules that allow you to load, manipulate, create, and save images. We can use this library without having any idea how these various operations are performed. For example, we could call drawer.line((x1, y1), (x2, y2), color, width) and not have to worry about the details of setting individual pixels within the image.

One of the great things about applying the abstraction pattern is that you often don't know just how complex something will be when you first start implementing your code. For example, imagine that you are writing a point-of-sale system for a hotel bar. Part of your system will need to calculate the price to charge a customer for the drinks they order. There are various formulae we can use to calculate this price, based on the quantity, the type of liquor used, and so on. But one of the challenging features is the need to support happy hour, that is, a period of time during which drinks will be offered at a discounted rate.

At first, you are told that happy hour is between five and six each evening. So, using good modular techniques, you add the following function to your code:

def is_happy_hour():
    if datetime.datetime.now().hour == 17: # 5pm.
        return True
    else:
        return False

You can then use this function to separate how happy hour is calculated from what happens during happy hour. For example:

if is_happy_hour():
    price = price * 0.5

So far this is pretty simple, and you might be tempted to bypass the creation of the is_happy_hour() function completely. However, this function soon becomes more complicated when you discover that happy hour doesn't apply on Sundays. So, you have to modify the is_happy_hour() function to support this:

def is_happy_hour():
    if datetime.date.today().weekday() == 6: # Sunday.
        return False
    elif datetime.datetime.now().hour == 17: # 5pm.
        return True
    else:
        return False

But you then discover that happy hour doesn't apply on Christmas day or on Good Friday. While Christmas day is easy enough to calculate, the logic used to calculate when Easter is on a given year is much more complicated. If you're interested, the example code for this chapter includes an implementation of the is_happy_hour() function which includes support for Christmas day and Good Friday. Needless to say, the implementation is rather complex.

Notice that our is_happy_hour() function becomes more and more complicated as we go along—we thought it would be quite simple at first but added requirements made it much more complicated. Fortunately, because we've abstracted away the details of how happy hour is calculated from the code that needs to know whether it is currently happy hour or not, only that one function needs to be updated to support this increased complexity.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.147.60.63