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

Simplicity is a Feature

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.

Cory Benfield

September 20, 2015
Tweet

More Decks by Cory Benfield

Other Decks in Programming

Transcript

  1. Hi!

  2. 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)
  3. 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())
  4. 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)
  5. import requests r = requests.post( 'https://http2bin.org/post', files={ 'key': 'value', 'filekey':

    ( 'test.py', open('test.py'), 'application/octet-stream' ) } ) print(r.text)
  6. 80%