DjangoCon Europe

The Ides of May

2013

1473–1543

Kraków

Bologna

Padua

Ferrara

*De Revolutionibus Orbium Coelestium*

Kopernik lifted the **Earth**

into the **heavens**

- Daily motion of the sky

- Planets moving more slowly

- Retrograde motion

100s BC

*Almagest*

*Pythagoras*

“First I found in **Cicero** that *Hicetas* had

realized that the Earth moved, and

later in **Plutarch** that others

had held the same view.”

Sun was **fixed** like the stars

and the center of planetary motions

Why was no one taking

these **ideas** seriously?

scholars were *too* empirical!

**Cannot**feel the Earth rotate**Cannot**feel the Earth revolve**No**stellar parallax

It was this **lack of physical**

“I say that if there were a *true*

the **center** of the universe…

we would, rather, have to say that

we **did not understand** those Scriptures,

than to say that something was false

which had been *demonstrated.”*

“But I do **not believe** that

there is *any* such demonstration;

Despite the *absence* of

physical **evidence**, the **ideas**

did keep getting better

1618

1638

1687

But **physical evidence**

did not appear until *180 years*

after Kopernik published

Bradley

Bessel

*Why did it take 113 years?*

Stellar aberration: **0° 0′ 40′′**

Stellar parallax: **0° 0′ 0.314′′**

It took *1,900* years after the Greeks

learned the distance to the **Moon**

for us to find the distance

to the nearest **stars**

Léon Foucault

*Evidence* took **200–300 years** to arrive

```
--1500s-- --1600s-- --1700s-- --1800s-- --1900s--
• • • • • • •
│ │ │ │ │ │ │
│ │ │ └ Newton │ │
│ │ └ Galileo│ │ └ Foucault
│ └ Kepler │ └ Bessel
└ Kopernik └ Bradley
Ideas Evidence
```

ignore **all** available

physical evidence?

Let's express Ptolemy's

system using Python code

```
# x-coordinates of the seven planets
# t = time, in Earth years
#
# deferent + epicycle
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = sin(t / 1.88) + 0.658 * sin(t)
ju = sin(t / 11.9) + 0.192 * sin(t)
sa = sin(t / 29.5) + 0.108 * sin(t)
```

```
# Step 1: make sin(t) coefficients = 1.0
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = sin(t / 1.88) + 0.658 * sin(t)
ju = sin(t / 11.9) + 0.192 * sin(t)
sa = sin(t / 29.5) + 0.108 * sin(t)
```

```
#
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = 1.52 * sin(t / 1.88) + sin(t)
ju = 5.21 * sin(t / 11.9) + sin(t)
sa = 9.26 * sin(t / 29.5) + sin(t)
```

```
# Step 2: move sin(t) to the front
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = 1.52 * sin(t / 1.88) + sin(t)
ju = 5.21 * sin(t / 11.9) + sin(t)
sa = 9.26 * sin(t / 29.5) + sin(t)
```

```
#
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = sin(t) + 1.52 * sin(t / 1.88)
ju = sin(t) + 5.21 * sin(t / 11.9)
sa = sin(t) + 9.26 * sin(t / 29.5)
```

```
# Step 3: “It's not you, it's me”
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = sin(t) + 1.52 * sin(t / 1.88)
ju = sin(t) + 5.21 * sin(t / 11.9)
sa = sin(t) + 9.26 * sin(t / 29.5)
```

```
# x-coordinates of the seven planets
# t = time, in Earth years
su = 0
me = 0.375 * sin(t / 0.24)
ve = 0.719 * sin(t / 0.62)
ea = 1.00 * -sin(t) # Earth moves
ma = 1.52 * sin(t / 1.88)
ju = 5.21 * sin(t / 11.9)
sa = 9.26 * sin(t / 29.5)
def planet_position(x):
return x - ea
```

So what did

Kopernik accomplish?

Not because of physical evidence!

Because it made

the code **so pretty**

“**ancient philosophers** were willing

to take the sequence of the planets as

being in accordance with the *size* of their

revolutions … Saturn the highest … Jupiter

under it, and after that Mars”

“But what reason can be produced

by those who put Venus below the Sun,

and Mercury after it? … Then it must be

“Consequently I think we should

certainly not despise the argument which

was *well known* to Martianus Capella

… that Venus and Mercury revolve

Ordering is not consistent

```
# deferent + epicycle
me = sin(t) + 0.375 * sin(t / 0.24)
ve = sin(t) + 0.719 * sin(t / 0.62)
su = sin(t)
ma = sin(t / 1.88) + 0.658 * sin(t)
ju = sin(t / 11.9) + 0.192 * sin(t)
sa = sin(t / 29.5) + 0.108 * sin(t)
```

```
su = 0
me = 0.375 * sin(t / 0.24)
ve = 0.719 * sin(t / 0.62)
ea = 1.00 * -sin(t) # Earth moves
ma = 1.52 * sin(t / 1.88)
ju = 5.21 * sin(t / 11.9)
sa = 9.26 * sin(t / 29.5)
```

“What is the **true lesson**

of the Copernican revolution? …

The *only* justification … lay in the

greater intellectual satisfaction he

derived from the celestial panorama as

seen from the **Sun** instead of the **Earth**.”

Kopernik “gave preference

to … delight in abstract *theory*,

at the **price** of rejecting the

*Or, in other words—*

It made the code so *pretty*

**Kopernik** — *The Great Refactorer*

Making a system *simpler*

by moving something

examples

and then I saw it

Mercedes 300D fan bolts

“it's **‘special tool time.’**

That's when you take a *bench grinder*

to the box wrench to reduce its height.

I have several box wrenches *ground*

at various points, *heated* and *bent,* etc.,

for dealing with nasty fastener locations.”

general principle

dependency injection

```
# Ugly: injecting I/O routines everywhere
import beautifulsoup, urllib2
def tw(handle, urlopen=urllib2.urlopen):
url = 'http://twitter.com/' + handle
u = urlopen(url)
return beautifulsoup.BeautifulSoup(u.read())
tw('brandon_rhodes')
#
# Tests use: tw('user', urlopen=fake_open)
#
```

wishbone splitting

```
"""Instead, I pull I/O up to a higher level."""
import beautifulsoup, urllib2
def make_url(handle):
return 'http://twitter.com/' + handle
def parse_page(u):
return beautifulsoup.BeautifulSoup(u.read())
url = make_url('brandon_rhodes')
u = urllib2.urlopen(url)
soup = parse_page(u)
```

Vladimir

Keleshev

The old

```
from argparse import argparse
def main():
parser = argparse.ArgumentParser(
description='Concatenate files.')
parser.add_argument(
'FILE', nargs='*',
help='Path(s) to files')
args = parser.parse_args()
```

```
usage: command [-h] [FILE [FILE ...]]
Concatenate files.
positional arguments:
FILE Path(s) to files
optional arguments:
-h, --help show this help message and exit
```

With docopt

```
"""Concatenate files.
Usage:
cat [-v] [FILE ...]
Options:
FILE Path(s) to files
-v, --version Display version
"""
from docopt import docopt
def main():
arguments = docopt(__doc__)
```

```
m = re.match('/user/([a-z_]+)$', path)
if m:
username = m.group(1)
return render('user.html', username)
m = re.match('/product/([-a-z_]+)$', path)
if m:
productname = m.group(1)
return render('user.html', productname)
m = re.match('/help/([-a-z_]+)$', path)
if m:
helppage = m.group(1)
return render('help.html', helppage)
return render('404.html', code=404)
```

```
def userview(request, username):
return render_to_response(
'user.html', username)
def productview(request, productname):
return render_to_response(
'product.html', productname)
def helpview(request, helppage):
return render_to_response(
'help.html', helppage)
```

**Copernican** refactorings

are my *favorite* refactorings!

The next time you

feel like your code is making

you work backwards—

**Stop,** and think of **Kopernik!**

**@brandon_rhodes**