1def calc(l, t):2 x=0 # set x to 03 for i in range(len(l)):4 x=x+l[i][0]*l[i][1]5 if t==True :6 x=x*1.27 if x>100: x=x-x*0.18 else:9 if x>100: x=x-x*0.110 return x123✓108.0✓60✓112.5✓error1234567108.060112.5ValueError1.21000.1
Cards: the code, the constants and the helper function, each line a slot that can changeTest bench: one lamp per test, ✓ while the function gives the expected answerTokens: numbers and code hopping to their new home, answers hopping to the testsOne function, refactored one change at a time. Each step highlights the lines it changes and crossfades them into the new version. Magic numbers hop out to a constants card and the adding loop hops out into its own helper function. The test lamps prove the point: the same three carts give 108.0, 60 and 112.5 before and after. Only the last step, a fix, changes behaviour: a negative quantity now raises ValueError. The refactor keeps the behaviour for the inputs the function is meant for: add_tax is True or False, and every item is a (price, qty) pair. For other values the two forms can differ (with add_tax = "yes", t == True is False but if add_tax: is true).

Why clean code

  1. Code is read far more often than it is written, so write it for the next reader. This 10-line function works, but can you tell what calc(l, t) does? We will tidy it without changing what it does.

Refactor, line by line

Check and fix

What changes

;; step 1/10 · read-more
the function, 10 lines, as found:
def calc(l, t):
    x=0  # set x to 0
    for i in range(len(l)):
        x=x+l[i][0]*l[i][1]
    if t==True :
        x=x*1.2
        if x>100: x=x-x*0.1
    else:
        if x>100: x=x-x*0.1
    return x

it works; it is just hard to read

The refactor keeps the behaviour for the inputs the function is meant for: add_tax is True or False, and every item is a (price, qty) pair. For other values the two forms can differ (with add_tax = "yes", t == True is False but if add_tax: is true). x *= 1.2 gives the same result as x = x * 1.2, and 1 + 0.20 is exactly the same float as 1.2, so every answer matches to the last digit. Each version on the card is checked with python3.