Slide 1

Slide 1 text

A Python Æsthetic

Slide 2

Slide 2 text

Video: http://pyvideo.org/video/1599/ Slides: http://rhodesmill.org/brandon/slides/2012-11-pyconca/

Slide 3

Slide 3 text

Video: http://pyvideo.org/video/1676/ Slides: http://rhodesmill.org/brandon/slides/2013-03-pycon/

Slide 4

Slide 4 text

Name the Ducks • Well-factored Nouns • Relentless Verbs • Sin of Synecdoche • Problem of Pluralization

Slide 5

Slide 5 text

Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)

Slide 6

Slide 6 text

Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(page)! ... = client.get(page)

Slide 7

Slide 7 text

Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url)! page = client.get(url)

Slide 8

Slide 8 text

Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url):! page = client.get(url)! process_page(page)! ! def process_page(page):! ... = page.content

Slide 9

Slide 9 text

Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url):! page = client.get(url)! process_page(page)! ! def process_page(response):! page = response.content

Slide 10

Slide 10 text

Well-Factored Nouns def main():! page = 'http://twitter.com/uranusjr/'! download_page(page)! ! def download_page(url):! page = requests.get(url)! process_page(page)! ! def process_page(response):! page = response.content

Slide 11

Slide 11 text

Well-Factored Nouns def main():! url = 'http://twitter.com/uranusjr/'! download_page(url)! ! def download_page(url):! response = requests.get(url)! process_page(response)! ! def process_page(response):! page = response.content

Slide 12

Slide 12 text

Well-Factored Nouns • Plan ahead (when you can) • Refactor often • Challenge yourself

Slide 13

Slide 13 text

Relentless Verbs def database():! # What does this even do?! ! def get_database():! # Gets an instance for me!! ! def create_database():! # Creates a database and returns! # it for me!

Slide 14

Slide 14 text

Relentless Verbs def database():! # What does this even do?! ! def get_database():! # Gets an instance for me!! ! def create_database():! # Creates a database and returns! # it for me!

Slide 15

Slide 15 text

Relentless Verbs document.md5()! ! ! # Probably okay! ! document.get_md5()! ! document.calculate_md5()

Slide 16

Slide 16 text

[P]racticality beats purity.

Slide 17

Slide 17 text

[P]racticality beats purity. reversed(iterable)! ! 'a'.upper()! ! len(iterable)! ! min(iterable)!

Slide 18

Slide 18 text

Relentless Verbs • Functions act • Verbose verbs can be dropped • Practicality beats purity

Slide 19

Slide 19 text

Sin of Synecdoche # In medialib.py:! def fetch_songs(urls):! ...! ! # In songlib.py:! def fetch(urls):! ...

Slide 20

Slide 20 text

Sin of Synecdoche # The caller has their choice:! ! from songlib import fetch! fetch(...)! ! # or:! ! import songlib! songlib.fetch(...)

Slide 21

Slide 21 text

Sin of Synecdoche • Be obvious • Don’t repeat yourself • Let users choose

Slide 22

Slide 22 text

Problem of Pluralization >>> connections! [,! ,! ]! ! >>> connections! {'master': ,! 'backup': }

Slide 23

Slide 23 text

datum data datum datum datum dataset data datum datum datum data datum datum datum data datum datasets data datu datu datu data datu datu datu data data datu datu datu data datu datu datu data dataset data datu datu datu data datu datu datu data

Slide 24

Slide 24 text

Anti-Plural connection_set! connection_list! connection_dict! ! def close_all(connection_seq):! ...! ! def reset_all(connection_map):! ...

Slide 25

Slide 25 text

I still favor plurals And documentation is always necessary.

Slide 26

Slide 26 text

Problem of Pluralization • Plurals can be ambiguous • There are only so many expressions • Total anti-plural may be too much

Slide 27

Slide 27 text

My Problem

Slide 28

Slide 28 text

My Problem def user_profile(request, username):! user = request.user! if user.is_authenticated:! if user.username == username:! # Show personal page! else:! # Show public page! else:! # Show page for anonymous user

Slide 29

Slide 29 text

My Problem def user_profile(request, username):! user = request.user! if user.is_authenticated:! if user.username == username:! # Show personal page! else:! # Show public page! else:! # Show page for anonymous user

Slide 30

Slide 30 text

My Problem >>> user.is_authenticated! >

Slide 31

Slide 31 text

My Problem def user_profile(request, username):! user = request.user! if user.is_authenticated():! if user.username == username:! # Show personal page! else:! # Show public page! else:! # Show page for anonymous user

Slide 32

Slide 32 text

No content

Slide 33

Slide 33 text

Descriptive Boolean # is + adjective = method! user.is_authenticated()! ! ! # No!! user.is_active! ! # Clearly a noun.! user.activeness

Slide 34

Slide 34 text

Watch Out # is + noun = variable?! >>> user.is_staff! True! ! # But...! >>> '1'.isdigit!

Slide 35

Slide 35 text

No content

Slide 36

Slide 36 text

My Current Solution # is + anything = method! user.is_authenticated()! ! ! # WRONG! method.is_action = True! ! # Considered correct (but ugly)! method.action_flag = True! ! # Maybe use something else?! method.action_info = None

Slide 37

Slide 37 text

Python lacked booleans until 2.2.1 Maybe we can get away with it.

Slide 38

Slide 38 text

Similarly Problematic # Makes more sense being a variable! request.url! ! # Obviously needs processing. Okay.! document.md5()! ! # ???! rectangle.left! rectangle.center

Slide 39

Slide 39 text

No Perfect Solution # Parentheses do not matter in Ruby! user.authenticated?! ! # But things can get funky quickly! proc_obj = proc { user.authenticated? }! proc_obj.call! ! # Python can be inconvenient! user.is_authenticated()! ! # But obvious things stay obvious! func = user.is_authenticated! func()

Slide 40

Slide 40 text

FIRE QUESTIONS