# 17.7: Refactoring

- Page ID
- 16930

When I wrote `circle`

, I was able to re-use `polygon`

because a many-sided polygon is a good approximation of a circle. But `arc`

is not as cooperative; we can’t use `polygon`

or `circle`

to draw an arc.

One alternative is to start with a copy of `polygon`

and transform it into `arc`

. The result might look like this:

def arc(t, r, angle): arc_length = 2 * math.pi * r * angle / 360 n = int(arc_length / 3) + 1 step_length = arc_length / n step_angle = float(angle) / n for i in range(n): fd(t, step_length) lt(t, step_angle)

The second half of this function looks like `polygon`

, but we can’t re-use `polygon`

without changing the interface. We could generalize `polygon`

to take an angle as a third argument, but then `polygon`

would no longer be an appropriate name! Instead, let’s call the more general function `polyline`

:

def polyline(t, n, length, angle): for i in range(n): fd(t, length) lt(t, angle)

Now we can rewrite `polygon`

and `arc`

to use `polyline`

:

def polygon(t, n, length): angle = 360.0 / n polyline(t, n, length, angle) def arc(t, r, angle): arc_length = 2 * math.pi * r * angle / 360 n = int(arc_length / 3) + 1 step_length = arc_length / n step_angle = float(angle) / n polyline(t, n, step_length, step_angle)

Finally, we can rewrite `circle`

to use `arc`

:

def circle(t, r): arc(t, r, 360)

This process—rearranging a program to improve function interfaces and facilitate code re-use—is called **refactoring**. In this case, we noticed that there was similar code in `arc`

and `polygon`

, so we “factored it out” into `polyline`

.

If we had planned ahead, we might have written `polyline`

first and avoided refactoring, but often you don’t know enough at the beginning of a project to design all the interfaces. Once you start coding, you understand the problem better. Sometimes refactoring is a sign that you have learned something.