Your SlideShare is downloading. ×
0
Poetic APIs     by Erik Rose “A poet is, before anything else, a person who is passionately in love with language.”       ...
Poetic APIs     by Erik Rose   programmer     ^ “A poet is, before anything else, a person who is passionately in love wit...
“Language is the best way of getting ideasfrom one head into another without surgery.”               —Mark Twain
“Oh! Everything has a name!”
“The window became a different thing by    having a symbol attached to it.”
Inventing   Language “Any fool can write code that a computer can understand.Good programmers write code that humans can u...
req = urllib2.Request(gh_url)password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()password_manager.add_password(   ...
req = urllib2.Request(gh_url)password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()password_manager.add_password(   ...
Don’t Be AnArchitecture Astronaut“It’s hard to make predictions, especially about the future.”                 —Robert Sto...
The best libraries are extracted, not invented.
def terminal_codes(self, stream):    capabilities = [bold, sc, rc, sgr0, el]    if hasattr(stream, fileno) and isatty(stre...
Tasks
TasksPrint some text with formatting.
Tasks      Print some text with formatting.Print some text at a location, then snap back.
Language Constructs
Language ConstructsFunctions, arguments, keyword arguments
Language ConstructsFunctions, arguments, keyword arguments              Decorators
Language ConstructsFunctions, arguments, keyword arguments              Decorators           Context managers
Language Constructs   Functions, arguments, keyword arguments                   Decorators               Context managersC...
Language Constructs         Functions, arguments, keyword arguments                         Decorators                    ...
Language Constructs         Functions, arguments, keyword arguments                         Decorators                    ...
Language Constructs         Functions, arguments, keyword arguments                         Decorators                    ...
Language Constructs         Functions, arguments, keyword arguments                         Decorators                    ...
Consistency  “Think like a wise man, but communicate       in the language of the people.”           —William Butler Yeats
get(key, default)    is better thanfetch(default, key)
TasksPrint some text at a location, then snap back.      Print some text with formatting.
Tasks        Print some text at a location, then snap back.              Print some text with formatting.print_at(Hello wo...
Tasks        Print some text at a location, then snap back.              Print some text with formatting.print_formatted(H...
Tasks        Print some text at a location, then snap back.              Print some text with formatting.print_formatted(H...
Tasks        Print some text at a location, then snap back.              Print some text with formatting.print_formatted(H...
Tasks        Print some text at a location, then snap back.              Print some text with formatting.print_formatted(H...
from blessings import Terminalt = Terminal()print t.red_bold + Hello world + t.normalprint t.red_on_white + Hello world + ...
from blessings import Terminalt = Terminal()print t.red_bold + Hello world + t.normalprint t.red_on_white + Hello world + ...
Consistency   warning signs
Consistency  warning signs  Frequent references to your docs or source
Consistency  warning signs  Frequent references to your docs or source         Feeling syntactically clever
Brevity“The finest language is mostly made up    of simple, unimposing words.”             —George Eliot
from blessings import Terminalterm = Terminal()print term.bold + I am bold! + term.normal
from blessings import Terminalterm = Terminal()print term.bold + I am bold! + term.normalprint term.bold(I am bold!)
from blessings import Terminalterm = Terminal()print term.bold + I am bold! + term.normalprint term.bold(I am bold!)print ...
Brevity warning signs
Brevity  warning signsCopying and pasting when writing against your API
Brevity  warning signsCopying and pasting when writing against your API  Typing something irrelevant while grumbling  “Why...
Composability “Perfection is achieved not when there is nothing left to add         but when there is nothing left to take...
print_formatted(Hello world, red, bold)
print_formatted(Hello world, red, bold)print_formatted(Hello world, red, bold, out=some_file)
print_formatted(Hello world, red, bold)print_formatted(Hello world, red, bold, out=some_file)print formatted(Hello world, ...
Composabilty    warning signs
Composabilty     warning signs   Classes with lots of state
Composabilty                                        warning signs                                     Classes with lots of...
Composabilty                                         warning signs                                     Classes with lots o...
Composabilty       warning signs    Classes with lots of state   Deep inheritance hierarchies
Composabilty         warning signs      Classes with lots of state     Deep inheritance hierarchies   Violations of the La...
Composabilty         warning signs      Classes with lots of state     Deep inheritance hierarchies   Violations of the La...
Composabilty                    warning signs                 Classes with lots of state                Deep inheritance h...
Composabilty                    warning signs                 Classes with lots of state                Deep inheritance h...
Composabilty         warning signs      Classes with lots of state     Deep inheritance hierarchies   Violations of the La...
Plain Data “All the great things are simple, and many   can be expressed in a single word…”          —Sir Winston Churchill
✚
✚
✚   ✚
✚         ✚RawConfigParser.parse(string)
✚         ✚RawConfigParser.parse(string)charming_parser.parse(file_contents(some_file.ini))
class Node(dict):    """A wrapper around a native Reflect.parse dict    providing some convenience methods and some cachin...
class Node(dict):    """A wrapper around a native Reflect.parse dict    providing some convenience methods and some cachin...
class Node(dict):    """A wrapper around a native Reflect.parse dict    providing some convenience methods and some cachin...
Plain Data   warning signs
Plain Data         warning signsUsers immediately transforming your output to another format
Plain Data         warning signsUsers immediately transforming your output to another format       Instantiating one objec...
Grooviness“The bad teacher’s words fall on his pupils like harsh rain;          the good teacher’s, as gently as dew.”    ...
Grooviness  Groove   Wall
Avoid nonsense representations.
Avoid nonsense representations.{    "bool" : {        "must" : {            "term" : { "user" : "fred" }        },        ...
Avoid nonsense representations.{    "bool" : {        "must" : {            "term" : { "user" : "fred" }        },        ...
Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None):    """Execute an elasticsearch query...
Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None):    """Execute an elasticsearch query...
Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None):    """Execute an elasticsearch query...
Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None):    """Execute an elasticsearch query...
Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None):    """Execute an elasticsearch query...
Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None):    """Execute an elasticsearch query...
Resource acquisition is initialization.
Resource acquisition is initialization.class PoppableBalloon(object):    """A balloon you can pop"""   def __init__(self):...
Resource acquisition is initialization.class PoppableBalloon(object):    """A balloon you can pop"""   def __init__(self):...
Compelling examples
Compelling examples
Grooviness   warning signs
Grooviness         warning signs  Nonsense states or representations
Grooviness         warning signs  Nonsense states or representations       Invariants that aren’t
Grooviness         warning signs  Nonsense states or representations       Invariants that aren’t  Users unclear where to ...
Grooviness         warning signs  Nonsense states or representations       Invariants that aren’t  Users unclear where to ...
Safety“I wish it was easier to hurt myself.”           —Nobody, ever
SafetyGroove   Wall
update things set frob=2 where frob=1;
update things set frob=2 where frob=1;update things set frob=2;
update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;
update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;rm *.pyc
update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;rm *.pycrm *
update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;rm *.pycrm *rm -f *
def delete(self, index, doc_type, id=None):    """Delete a typed JSON document from a specific    index based on its id."""
def delete(self, index, doc_type, id=None):    """Delete a typed JSON document from a specific    index based on its id."""
def delete(self, index, doc_type, id=None):    """Delete a typed JSON document from a specific    index based on its id.""...
Error reporting: exceptions are typically safer.
Safety warning signs
Safetywarning signsSurprisingly few—people will blame themselves.
non-astronautics                     consistency      brevity                   composability plain data                  ...
non-astronautics         consistencybrevity                composabilityplain data               grooviness              s...
non-astronautics                     consistencybrevity                            composability   Elegance?          “It ...
PreflightArchitecture Astronautics               ✖ Instantiating one object just to pass✖ Inventing rather than extracting...
Thank You    twitter: ErikRose  www.grinchcentral.com    erik@mozilla.com
Poetic APIs
Poetic APIs
Poetic APIs
Poetic APIs
Poetic APIs
Poetic APIs
Poetic APIs
Upcoming SlideShare
Loading in...5
×

Poetic APIs

1,264

Published on

API design is one of the most difficult areas of programming. Besides solving your immediate problem, you must also accomodate unknown future ones—and fit nicely into other people's brains. Let's explore how to do this without a time machine, considering compactness, orthogonality, consistency, safety, coupling, state handling, and the messy interface with human cognition, all illustrated with practical examples—and gruesome mistakes—from several popular Python libraries.

Published in: Sports, Technology
0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,264
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
15
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

Transcript of "Poetic APIs"

  1. 1. Poetic APIs by Erik Rose “A poet is, before anything else, a person who is passionately in love with language.” —W. H. Auden
  2. 2. Poetic APIs by Erik Rose programmer ^ “A poet is, before anything else, a person who is passionately in love with language.” —W. H. Auden
  3. 3. “Language is the best way of getting ideasfrom one head into another without surgery.” —Mark Twain
  4. 4. “Oh! Everything has a name!”
  5. 5. “The window became a different thing by having a symbol attached to it.”
  6. 6. Inventing Language “Any fool can write code that a computer can understand.Good programmers write code that humans can understand.” —Martin Fowler
  7. 7. req = urllib2.Request(gh_url)password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()password_manager.add_password( None, https://api.github.com, user, pass)auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)opener = urllib2.build_opener(auth_manager)urllib2.install_opener(opener)handler = urllib2.urlopen(req)print handler.getcode()
  8. 8. req = urllib2.Request(gh_url)password_manager = urllib2.HTTPPasswordMgrWithDefaultRealm()password_manager.add_password( None, https://api.github.com, user, pass)auth_manager = urllib2.HTTPBasicAuthHandler(password_manager)opener = urllib2.build_opener(auth_manager)urllib2.install_opener(opener)handler = urllib2.urlopen(req)print handler.getcode()r = requests.get(https://api.github.com, auth=(user, pass))print r.status_code
  9. 9. Don’t Be AnArchitecture Astronaut“It’s hard to make predictions, especially about the future.” —Robert Storm Petersen
  10. 10. The best libraries are extracted, not invented.
  11. 11. def terminal_codes(self, stream): capabilities = [bold, sc, rc, sgr0, el] if hasattr(stream, fileno) and isatty(stream.fileno()): # Explicit args make setupterm() work even when -s is passed: setupterm(None, stream.fileno()) # so things like tigetstr() work codes = dict((x, tigetstr(x)) for x in capabilities) cup = tigetstr(cup) codes[cup] = lambda line, column: tparm(cup, line, column) else: # If youre crazy enough to pipe this to a file or something, # dont output terminal codes: codes = defaultdict(lambda: , cup=lambda line, column: ) return codes...self._codes = terminal_codes(stdout)...class AtLine(object): def __enter__(self): """Save position and move to progress bar, col 1.""" self.stream.write(self._codes[sc]) # save position self.stream.write(self._codes[cup](self.line, 0)) def __exit__(self, type, value, tb): self.stream.write(self._codes[rc]) # restore position...print self._codes[bold] + results + self._codes[sgr0]
  12. 12. Tasks
  13. 13. TasksPrint some text with formatting.
  14. 14. Tasks Print some text with formatting.Print some text at a location, then snap back.
  15. 15. Language Constructs
  16. 16. Language ConstructsFunctions, arguments, keyword arguments
  17. 17. Language ConstructsFunctions, arguments, keyword arguments Decorators
  18. 18. Language ConstructsFunctions, arguments, keyword arguments Decorators Context managers
  19. 19. Language Constructs Functions, arguments, keyword arguments Decorators Context managersClasses (really more of an implementation detail)
  20. 20. Language Constructs Functions, arguments, keyword arguments Decorators Context managers Classes (really more of an implementation detail) åPatterns, Protocols, Interfaces, and Conventions
  21. 21. Language Constructs Functions, arguments, keyword arguments Decorators Context managers Classes (really more of an implementation detail) åPatterns, Protocols, Interfaces, and Conventions Sequences
  22. 22. Language Constructs Functions, arguments, keyword arguments Decorators Context managers Classes (really more of an implementation detail) åPatterns, Protocols, Interfaces, and Conventions Sequences Iterators
  23. 23. Language Constructs Functions, arguments, keyword arguments Decorators Context managers Classes (really more of an implementation detail) åPatterns, Protocols, Interfaces, and Conventions Sequences Iterators Mappings
  24. 24. Consistency “Think like a wise man, but communicate in the language of the people.” —William Butler Yeats
  25. 25. get(key, default) is better thanfetch(default, key)
  26. 26. TasksPrint some text at a location, then snap back. Print some text with formatting.
  27. 27. Tasks Print some text at a location, then snap back. Print some text with formatting.print_at(Hello world, 10, 2)with location(10, 2): print Hello world for thing in range(10): print thing
  28. 28. Tasks Print some text at a location, then snap back. Print some text with formatting.print_formatted(Hello world, red, bold)print color(Hello world, red, bold)print color(<red><bold>Hello world</bold></red>)print red(bold(Hello) + world)print codes[red] + codes[bold] + Hello world + codes[normal]print {t.red}Hi{t.bold}Mom{t.normal}.format(t=terminal)print terminal.red_bold + Hello world + terminal.normal
  29. 29. Tasks Print some text at a location, then snap back. Print some text with formatting.print_formatted(Hello world, red, bold)print color(Hello world, red, bold)print color(<red><bold>Hello world</bold></red>)print red(bold(Hello) + world)print codes[red] + codes[bold] + Hello world + codes[normal]print {t.red}Hi{t.bold}Mom{t.normal}.format(t=terminal)print terminal.red_bold + Hello world + terminal.normal
  30. 30. Tasks Print some text at a location, then snap back. Print some text with formatting.print_formatted(Hello world, red, bold)print color(Hello world, red, bold)print color(<red><bold>Hello world</bold></red>)print red(bold(Hello) + world)print codes[red] + codes[bold] + Hello world + codes[normal]print {t.red}Hi{t.bold}Mom{t.normal}.format(t=terminal)print terminal.red_bold + Hello world + terminal.normal
  31. 31. Tasks Print some text at a location, then snap back. Print some text with formatting.print_formatted(Hello world, red, bold)print color(Hello world, red, bold)print color(<red><bold>Hello world</bold></red>)print red(bold(Hello) + world)print codes[red] + codes[bold] + Hello world + codes[normal]print {t.red}Hi{t.bold}Mom{t.normal}.format(t=terminal)print terminal.red_bold + Hello world + terminal.normal
  32. 32. from blessings import Terminalt = Terminal()print t.red_bold + Hello world + t.normalprint t.red_on_white + Hello world + t.normalprint t.underline_red_on_green + Hello world + t.normal
  33. 33. from blessings import Terminalt = Terminal()print t.red_bold + Hello world + t.normalprint t.red_on_white + Hello world + t.normalprint t.underline_red_on_green + Hello world + t.normalArticle.objects.filter(tag__in=[color_red, color_blue])Article.objects.filter(tag__contains=color)
  34. 34. Consistency warning signs
  35. 35. Consistency warning signs Frequent references to your docs or source
  36. 36. Consistency warning signs Frequent references to your docs or source Feeling syntactically clever
  37. 37. Brevity“The finest language is mostly made up of simple, unimposing words.” —George Eliot
  38. 38. from blessings import Terminalterm = Terminal()print term.bold + I am bold! + term.normal
  39. 39. from blessings import Terminalterm = Terminal()print term.bold + I am bold! + term.normalprint term.bold(I am bold!)
  40. 40. from blessings import Terminalterm = Terminal()print term.bold + I am bold! + term.normalprint term.bold(I am bold!)print {t.bold}Very {t.red}emphasized{t.normal}.format(t=term)
  41. 41. Brevity warning signs
  42. 42. Brevity warning signsCopying and pasting when writing against your API
  43. 43. Brevity warning signsCopying and pasting when writing against your API Typing something irrelevant while grumbling “Why can’t it just assume the obvious thing?”
  44. 44. Composability “Perfection is achieved not when there is nothing left to add but when there is nothing left to take away.” —Antoine de Saint-Exupery
  45. 45. print_formatted(Hello world, red, bold)
  46. 46. print_formatted(Hello world, red, bold)print_formatted(Hello world, red, bold, out=some_file)
  47. 47. print_formatted(Hello world, red, bold)print_formatted(Hello world, red, bold, out=some_file)print formatted(Hello world, red, bold)
  48. 48. Composabilty warning signs
  49. 49. Composabilty warning signs Classes with lots of state
  50. 50. Composabilty warning signs Classes with lots of stateclass ElasticSearch(object): """ An object which manages connections to elasticsearch and acts as a go-between for API calls to it""" def index(self, index, doc_type, doc, id=None, force_insert=False, query_params=None): """Put a typed JSON document into a specific index to make it searchable.""" def search(self, query, **kwargs): """Execute a search query against one or more indices and get back search hits.""" def more_like_this(self, index, doc_type, id, mlt_fields, body=, query_params=None): """Execute a "more like this" search query against one or more fields and get back search hits.""" . . .
  51. 51. Composabilty warning signs Classes with lots of stateclass ElasticSearch(object): """ class PenaltyBox(object): An object which manages connections to elasticsearch and acts as a """A thread-safe bucket of servers (or other things) that may have go-between for API calls to it""" downtime.""" def index(self, index, doc_type, doc, id=None, force_insert=False, query_params=None): def get(self): """Put a typed JSON document into a specific index server and a bool indicating whether it was from the """Return a random to make it searchable.""" dead list.""" def search(self, query, **kwargs): mark_dead(self, server): def """Execute a search query against one or more indices and get wont search """Guarantee that this server back be returned again until a period of hits.""" time has passed, unless all servers are dead.""" def more_like_this(self, index, def mark_live(self, server): doc_type, id, mlt_fields, body=, query_params=None): """Execute a "more like this" search query against one or dead list to and live one.""" """Move a server from the more fields the get back search hits.""" . . .
  52. 52. Composabilty warning signs Classes with lots of state Deep inheritance hierarchies
  53. 53. Composabilty warning signs Classes with lots of state Deep inheritance hierarchies Violations of the Law of Demeter
  54. 54. Composabilty warning signs Classes with lots of state Deep inheritance hierarchies Violations of the Law of Demeter Mocking in tests
  55. 55. Composabilty warning signs Classes with lots of state Deep inheritance hierarchies Violations of the Law of Demeter Mocking in testsprint_formatted(Hello world, red, bold)
  56. 56. Composabilty warning signs Classes with lots of state Deep inheritance hierarchies Violations of the Law of Demeter Mocking in testsprint_formatted(Hello world, red, bold)print formatted(Hello world, red, bold)
  57. 57. Composabilty warning signs Classes with lots of state Deep inheritance hierarchies Violations of the Law of Demeter Mocking in tests Options
  58. 58. Plain Data “All the great things are simple, and many can be expressed in a single word…” —Sir Winston Churchill
  59. 59.
  60. 60.
  61. 61. ✚ ✚
  62. 62. ✚ ✚RawConfigParser.parse(string)
  63. 63. ✚ ✚RawConfigParser.parse(string)charming_parser.parse(file_contents(some_file.ini))
  64. 64. class Node(dict): """A wrapper around a native Reflect.parse dict providing some convenience methods and some caching of expensive computations"""
  65. 65. class Node(dict): """A wrapper around a native Reflect.parse dict providing some convenience methods and some caching of expensive computations""" def walk_up(self): """Yield each node from here to the root of the tree, starting with myself.""" node = self while node: yield node node = node.get(_parent)
  66. 66. class Node(dict): """A wrapper around a native Reflect.parse dict providing some convenience methods and some caching of expensive computations""" def walk_up(self): """Yield each node from here to the root of the tree, starting with myself.""" node = self while node: yield node node = node.get(_parent) def nearest_scope_holder(self): """Return the nearest node that can have its own scope, potentially including myself. This will be either a FunctionDeclaration or a Program (for now). """ return first(n for n in self.walk_up() if n[type] in [FunctionDeclaration, Program])
  67. 67. Plain Data warning signs
  68. 68. Plain Data warning signsUsers immediately transforming your output to another format
  69. 69. Plain Data warning signsUsers immediately transforming your output to another format Instantiating one object just to pass it to another
  70. 70. Grooviness“The bad teacher’s words fall on his pupils like harsh rain; the good teacher’s, as gently as dew.” —Talmud: Ta’anith 7b
  71. 71. Grooviness Groove Wall
  72. 72. Avoid nonsense representations.
  73. 73. Avoid nonsense representations.{ "bool" : { "must" : { "term" : { "user" : "fred" } }, "must_not" : { "range" : { "age" : { "from" : 12, "to" : 21 } } }, "minimum_number_should_match" : 1, "boost" : 1.0 }}
  74. 74. Avoid nonsense representations.{ "bool" : { "must" : { "term" : { "user" : "fred" } }, "must_not" : { "range" : { "age" : { "from" : 12, "to" : 21 } } }, "minimum_number_should_match" : 1, "boost" : 1.0 }} frob*ator AND snork
  75. 75. Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""
  76. 76. Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""search(q=frob*ator AND snork, body={some: query})
  77. 77. Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""search(q=frob*ator AND snork, body={some: query})search()
  78. 78. Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""search(q=frob*ator AND snork, body={some: query})search()✚
  79. 79. Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""search(q=frob*ator AND snork, body={some: query})search()✚ New pyelasticsearchdef search(self, query, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""
  80. 80. Old pyelasticsearchdef search(self, q=None, body=None, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results."""search(q=frob*ator AND snork, body={some: query})search()✚ New pyelasticsearchdef search(self, query, indexes=None, doc_types=None): """Execute an elasticsearch query, and return the results.""" Fail shallowly.
  81. 81. Resource acquisition is initialization.
  82. 82. Resource acquisition is initialization.class PoppableBalloon(object): """A balloon you can pop""" def __init__(self): self.air = 0 def fill(self, how_much): self.air = how_much
  83. 83. Resource acquisition is initialization.class PoppableBalloon(object): """A balloon you can pop""" def __init__(self): self.air = 0 def fill(self, how_much): self.air = how_muchclass PoppableBalloon(object): """A balloon you can pop""" def __init__(self, initial_fill): self.air = initial_fill def fill(self, how_much): self.air = how_much
  84. 84. Compelling examples
  85. 85. Compelling examples
  86. 86. Grooviness warning signs
  87. 87. Grooviness warning signs Nonsense states or representations
  88. 88. Grooviness warning signs Nonsense states or representations Invariants that aren’t
  89. 89. Grooviness warning signs Nonsense states or representations Invariants that aren’t Users unclear where to get started
  90. 90. Grooviness warning signs Nonsense states or representations Invariants that aren’t Users unclear where to get started Long, complicated documentation
  91. 91. Safety“I wish it was easier to hurt myself.” —Nobody, ever
  92. 92. SafetyGroove Wall
  93. 93. update things set frob=2 where frob=1;
  94. 94. update things set frob=2 where frob=1;update things set frob=2;
  95. 95. update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;
  96. 96. update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;rm *.pyc
  97. 97. update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;rm *.pycrm *
  98. 98. update things set frob=2 where frob=1;update things set frob=2;update things set frob=2 all;rm *.pycrm *rm -f *
  99. 99. def delete(self, index, doc_type, id=None): """Delete a typed JSON document from a specific index based on its id."""
  100. 100. def delete(self, index, doc_type, id=None): """Delete a typed JSON document from a specific index based on its id."""
  101. 101. def delete(self, index, doc_type, id=None): """Delete a typed JSON document from a specific index based on its id."""def delete(self, index, doc_type, id): """Delete a typed JSON document from a specific index based on its id."""def delete_all(self, index, doc_type): """Delete all documents of the given doctype from an index."""
  102. 102. Error reporting: exceptions are typically safer.
  103. 103. Safety warning signs
  104. 104. Safetywarning signsSurprisingly few—people will blame themselves.
  105. 105. non-astronautics consistency brevity composability plain data grooviness safety
  106. 106. non-astronautics consistencybrevity composabilityplain data grooviness safety
  107. 107. non-astronautics consistencybrevity composability Elegance? “It is the ineffable will of Bob.” —Old Thrashbargplain data grooviness safety
  108. 108. PreflightArchitecture Astronautics ✖ Instantiating one object just to pass✖ Inventing rather than extracting it to anotherConsistency Composability✖ Frequent references to your docs or ✖ Classes with lots of state source ✖ Deep inheritance hierarchies✖ Feeling syntactically clever ✖ Violations of the Law of Demeter ✖ Mocking in testsBrevity ✖ Bolted-on options✖ Copying and pasting when writing against your API Grooviness✖ Grumbling about having to hand- ✖ Nonsense states hold the API ✖ Invariants that aren’t ✖ No clear introductory pathPlain Data ✖ Long, tricky documentation✖ Users immediately transforming your output to another format Safety ✖ Ease of hurting self or others
  109. 109. Thank You twitter: ErikRose www.grinchcentral.com erik@mozilla.com
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×