Building Beautiful APIs

& Microservices

Brendan McAdams

@rit

Beauty is in the Eye of

the Beholder

...But You Can't Always Put Lipstick On A Pig

and Expect Good Results

Beautiful APIs Should Speak For Themselves

  • Are your code & API are hard
    to understand internally?
    • It's likely the same
      externally
  • Is your API monolithic and slow
    moving, or small and
    nimble?
     
  • Is it well documented?
     
  • Do you return well
    articulated, meaningful
    errors?

Smaller Is (Often) Better

  • Build Lots of Small Services
     

  • Move Quickly. Move Independently.
     

  • APIs are powerful in this model

    • API can feed a UI (Angular, React/Flux)

    • API can feed Data Services

    • No Monolithic Dev Cycle Necessary
       

  • I'm really talking about "Microservices"

Some Lessons I Learned At Netflix

Lessons From Netflix

 

  • Build Lots of Small Services.

    • Make Them Easy To Work With.

  • Build fast, Build Often.
     

  • Documentation Is Non-Negotiable.
     
  • Tolerate Failure.
     
  • Errors Are Part Of Documentation.
     

Choose a Good Service Model

  • Choose a Service Model That's Easy To Interact With

    • This means develop new parts of as a producer

    • This also means use it as a consumer

  • The Two Crucial Parts

    • Data Layer (JSON? Thrift? Protobuf? Smoke Signals?)

    • Development Framework
       

  • REST + JSON Seem To Be Winners (On Popularity, At Least)

Build Fast. Build Often.

  • Continuous Integration Matters.

    • The caveat: You need lots of (good) tests.

    • Consider property based testing (e.g. ScalaCheck, QuickCheck)
       

  • Checkins Should Trigger CI Builds
     

  • Only CI Should Have Commit Permissions to "master"
     

  • These rules will help lead to Continuous Deployment

Continuous Deployment

  • I adore the Netflix deployment model

    • Successful CI Builds Trigger "Baking" Of a Cloud Image

    • New Image is Automatically Promoted to Staging
       

  • Deployed Servers are Tagged with CI Build #
     

  • One Click to Promote Staging to Prod
     

  • One Click to Roll Back to Prior Version

Documentation Is Non Negotiable

  • An API that isn't documented is no API at all
     

  • In an Ideal World?
    • Code is self documenting
       
  • At Netflix we used (and loved) Swagger
    • Describe API endpoints as part of code
    • Documentation generated
    • Easy to generate client libraries from Swagger endpoint

Swagger At A (Brief) Glance

Swagger At A (Brief) Glance

Tolerate Failure

  • Tolerating failure in a Microservice environment is crucial.
     
  • Small independent pieces should mean one thing failing doesn't take out the whole system.
     
  • Lots of small pieces, loosely coupled.
     
  • Key Term: Graceful Degradation

Failing Gracefully

  • Microservices let us choose what constitutes a true system outage
     
  • Search feature down? You can still serve the rest of your site
     
  • To Fail/Degrade Gracefully We Need To Use a Forbidden Word...
     
  • DESIGN PATTERN!

Circuit Breakers

  • In his book Release It, Michael Nygard introduced the Circuit Breaker pattern
     
  • Designed like an electrical circuit breaker
     
  • When things are working: Closed
     
  • When things aren't working: Open
     
  • When trying to reset: Half-Open

The Circuit Breaker Pattern

[ credit: akka.io ]

Netflix' Hysterix Framework Uses Circuit Breaker & Other Tools to Help Combine Microservices

Errors

  • Errors!
     

  • Errors!
     

  • Errors!

Errors

  • Meaningless Errors & Exceptions lead to long days (and nights!) slaving over error logs
     

  • Nothing sucks quite so much as spending long hours digging through error logs...
     

  • ... Only to find out it was something stupid that could have been provided in an error message

Good Practices with Errors

  • If you can validate an entire request object, do so.

    • Return every error you find immediately, and clearly.
       

  • If you can pass multiple errors up your stack and return them, do so...

    • JSON supports Arrays, after all

Good Practices with Errors

  • Provide useful data, not just a generic 500 Internal Server Error

    • If you have an exception, extract some useful message from it
       

    • REMINDER: Exceptions shouldn't be used for flow control

Provide Errors That Make Sense

  • PHP Provides a particularly useful error message...
     

  • Parse error: syntax
    error, unexpected
    T_PAAMAYIM_NEKUDOTAYIM
     

  • W. T. F. ?

Provide Errors That Make Sense

  • 'Paamayim
    Nekudotayim' ( פעמיים נקודתיים ) is apparently
    Hebrew for "Double Colon"
     

  • The main authors of PHP 3+
    are Israeli, and probably
    thought this was funny.
     

  • Imagine how many hapless
    devs have misplaced a '::'
    and spent hours scratching
    their heads...

Sensible Errors

  • Most API platforms have
    some sort of Status Code
    mechanism
     

  • For REST, Pick & Document
    HTTP Codes
     

  • BE CONSISTENT

Sensible Errors

  • Even if you make up your
    own silly HTTP codes, make
    sure you document them so
    people know what they mean.
     

  • There's a proposed HTTP
    Error Code "759 -
    Unexpected
    T_PAAMAYIM_NEKUDOTAYIM"
     

  • I also like "763 - Under-
    Caffeinated"

Testing Matters!

  • Your API Framework of
    choice should provide good
    tools for testing it

    • If it doesn't, consider finding something better
       

  • Good testing contributes greatly to feeling comfortable that
    what you've built works as
    documented

Write Lots of Tests

  • Positive Tests

  • Negative Tests

  • Service Level Tests (HTTP
    Calls)

  • Helper Level Tests (backend
    objects sans HTTP)

  • Parser Tests

  • Regression Tests

  • Voight-Kampff Tests

One Test
Two Test
Red Test
Blue Test

Never trust a test you haven't seen fail.

Questions?

Beautiful APIs & Microservices

By Brendan McAdams

Beautiful APIs & Microservices

  • 4,702