Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Simplicity is a Feature

214c694acb154321379cbc58dc91528c?s=47 Cory Benfield
September 20, 2015

Simplicity is a Feature

When you talk to software professionals, you come away with the idea that we have a case of feature-itis. An enormous number of people evaluate software in terms of the length of feature lists and functionality. People dismiss software with fewer features as “underpowered”. And how many times have you heard software devalued because “I could build that”?

And yet, intuitively we know that’s not always true. urllib3 has more features than requests, but people overwhelmingly prefer to use requests. Android has more features than iOS, but Android hasn’t demolished iOS.

The reason for this is that simplicity is a powerful advantage. This talk will explain what is meant by simplicity, how to judge software simplicity, and how to approach building simple tools. It’ll also talk about how to structure your code to give the optimum balance of simplicity and flexibility, to keep yourself and your users happy down the line.

214c694acb154321379cbc58dc91528c?s=128

Cory Benfield

September 20, 2015
Tweet

Transcript

  1. Simplicity Is A Feature

  2. Hi!

  3. Me @lukasaoz @lukasa

  4. None
  5. Warning Opinions!

  6. What Is Simplicity?

  7. None
  8. None
  9. None
  10. None
  11. import requests r = requests.get( ‘https://api.github.com', auth=('user', ‘pass') )

  12. import urllib2 gh_url = 'https://api.github.com' req = urllib2.Request(gh_url) password_manager =

    urllib2.HTTPPasswordMgrWithDefaultRealm() password_manager.add_password(None, gh_url, 'user', 'pass') auth_manager = urllib2.HTTPBasicAuthHandler(password_manager) opener = urllib2.build_opener(auth_manager) urllib2.install_opener(opener) handler = urllib2.urlopen(req)
  13. – Justice Potter Stewart “I know it when I see

    it.”
  14. Simplicity ⫫ Features

  15. Simplicity is about defaults

  16. Why Be Simple?

  17. – Edsger Dijkstra “Simplicity is a prerequisite for reliability.”

  18. – Robert Browning “Less is more.”

  19. – Henry David Thoreau “Our life is frittered away by

    detail. Simplify.”
  20. How To Be Simple

  21. None
  22. How To Onion

  23. Build In Layers

  24. Layer 1: Low-level

  25. import email.generator import http.client import io import os import shutil

    def _encode_multipart_formdata(fields, files): boundary = email.generator._make_boundary() buf = io.BytesIO() textwriter = io.TextIOWrapper( buf, 'utf8', newline='', write_through=True) for (key, value) in fields.items(): textwriter.write( '--{boundary}\r\n' 'Content-Disposition: form-data; name="{key}"\r\n\r\n' '{value}\r\n'.format( boundary=boundary, key=key, value=value)) for (key, filepath, filename) in files: if os.path.isfile(filepath): textwriter.write( '--{boundary}\r\n' 'Content-Disposition: form-data; name="{key}"; ' 'filename="{filename}"\r\n' 'Content-Type: {content_type}\r\n\r\n'.format( boundary=boundary, key=key, filename=filename, content_type='application/octet-stream')) with open(filepath, "rb") as f: shutil.copyfileobj(f, buf) textwriter.write('\r\n') textwriter.write('--{}--\r\n\r\n'.format(boundary)) content_type = 'multipart/form-data; boundary={}'.format(boundary) return content_type, buf.getvalue() content_type, data = _encode_multipart_formdata( fields={'key': 'value'}, files=[('filekey', 'test.py', 'test.py')] ) headers = { 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'Connection': 'keep-alive', 'User-Agent': 'python-requests/2.7.0 CPython/2.7.10 Darwin 14.5.0', 'Content-Type': content_type, 'Content-Length': '{}'.format(len(data)), } c = http.client.HTTPSConnection('http2bin.org', 443) c.request('POST', '/post', body=data, headers=headers) resp = c.getresponse() print(resp.read())
  26. Layer 1: Low-level Layer 2: Features

  27. import urllib3 from urllib3.filepost import RequestField fields = [ RequestField(

    'key', 'value', ), RequestField( 'filekey', open('test.py').read(), filename='test.py', ), ] fields[0].make_multipart() fields[1].make_multipart(content_type='application/octet-stream') headers = {'User-Agent': 'python-requests/2.7.0 CPython 2.7.10 Darwin/14.5.0'} http = urllib3.PoolManager() r = http.request('POST', 'http://http2bin.org/post', fields=fields) print(r.data)
  28. Layer 1: Low-level Layer 2: Features Layer 3: Simplicity

  29. import requests r = requests.post( 'https://http2bin.org/post', files={ 'key': 'value', 'filekey':

    ( 'test.py', open('test.py'), 'application/octet-stream' ) } ) print(r.text)
  30. While We’re Here…

  31. 80%

  32. None
  33. Thanks! ✨✨