Skip to content

Latest commit

 

History

History
337 lines (265 loc) · 4.1 KB

presentation.md

File metadata and controls

337 lines (265 loc) · 4.1 KB

Designing mobile API

Wojtek Erbetowski

Toruń JUG, 29.04.2015

t: @erbetowski


About me


Why not simply 'design an API'?


Good mobile API

Good API


fit


REST & HATEOAS


GET /users/123

{
  "name": "John Doe",
  "age": 25,
  "links": [
    {
      "rel": "self",
      "href": "/users/123"
    },
    {
      "rel": "account",
      "href": "/accounts/987"
    },
    {
      "rel": "address",
      "href": "/addresses/555"
    }
  ]
}

GET /addresses/555

{
  "street": "Sesame",
  "no": 25,
  "zipCode": "12-321",
  "state": "NY",
  "country": "US"
}

HATEOAS is great!


there's a thing called latency


Latency

fit

inline


Latency

fit

inline


It can get crazy


Merging responses


GET /user/123

{
  "name": "John Doe",
  "age": 25,
  "country": "US"
}

And if it ain't yours?


Expansion FTW!


GET /users/123?fields=[name,age,address[country]]

{
  "name": "John Doe",
  "age": 25,
  "country": "US"
}

but most of all


CONNECTION: KEEP-ALIVE


HTTP/2


Docs


fit


THROUGHPUT


fit


Do you get only what you need?


{
  "person": {
    "id": 12345,
    "firstName": "John",
    "lastName": "Doe",
    "age": 25,
    "phones": {
      "home": "800-123-4567",
      "work": "888-555-0000",
      "cell": "877-123-1234"
    },
    "email": [
      "jd@example.com",
      "jd@example.org"
    ],
    "dateOfBirth": "1980-01-02T00:00:00.000Z",
    "registered": true,
    "emergencyContacts": [
      {
        "name": "",
        "phone": "",
        "email": "",
        "relationship": "spouse|parent|child|other"
      }
    ],
    "address": {
        "street": "Sesame",
        "no": 25,
        "zipCode": "12-321",
        "state": "NY",
        "country": "US"
    }
  }
}

{
    "firstName": "John",
    "lastName": "Doe",
    "age": 25,
    "country": "US"
}

And if it ain't yours?


Expansion FTW!


GET /users/123?fields=[name,age,address[country]]

{
  "name": "John Doe",
  "age": 25,
  "country": "US"
}

DATA COMPRESSION


{
"people": [
    {
        "firstName": "Jason",
        "lastName": "Page",
        "username": "jasonp",
        "isMale": true,
        "phone": "142-808-3743",
        "nid": "12252671714"
 ...

Full

222910 bytes

GZipped

32128 bytes (14%)


Domain complexity


Usually automated testing sucks

(on mobile)


So if UI differs from

##DATA MODEL


... let the backend guys worry


POST /relation

{
  "type": "follower",
  "from": 123,
  "to": 456
}

POST /users/456/follow


HTTP Cache


Expires: Sat, 21 Feb 2015 05:00 GMT

iOS (AFNetworking + NSURLCache)

Android (Retrofit + OkHttp + HttpResponseCache)


Paging


GET /users?page=1

[
  "Arthur",
  "Bob",
  "Celine",
  "Daniel",
  "Eve",
  "Fred",
  "George"
]

GET /users?since=185328145127


{
    "items": [
        ...
    ],
    "next": "/users?since=185328145127"
}

Case study


Endpoints overall

from 36 to 20


Endpoints usage

(full application flow)

from 86 to 20


96% data size reduction

(84% without GZIP)


In the end

it's all about usability


Starring


Akamai

State of the Internet


Swagger


Applause

(Former uTest)


Any thoughts?