APIs for the Mobile World

Post on 22-Jan-2018

127 views 0 download

Transcript of APIs for the Mobile World

APIs for the Mobile WorldMichele Titolo Lead Software Engineer @ Capital One

Why APIs for the

world?mobile

People 💖 Apps

Apps Have To Be Great 👍

Apps Are Complicated

📶🔗

🕐‼

👑

Can APIs make an app not great? Yes.

How?

Slow 💤

State 🙅

Crashes 💥

Oops something’s amiss

Slows Down Development

great📱5ways to make

experiences

Keep Things Consistent.1

Established Conventions

Don’t Return 200 With “Error”

Follow Your Own Conventions

Endpoint “id” field

/products id

/products/:id productID

/cart product_id

Document Everything.2

does notself documenting

code

exist

Ask So And So Is Not Documentation

Update Documentation

Communicate

Make Documentation Part Of The Process

Auto-Generate

Honor thy contracts.3

Documentation Is A Contract

Versioning

Unexpected Breaking Changes

http://

500s that return HTML

Insulate the client.4

SomethingWILL PROBABLY GOWRONG

Long Release Cycles

Releasing An App Doesn't Mean People Will Use It

Gateway Or Reverse Proxy

The Bigger Your Ecosystem, The More This Is Needed

Route To Different Servers

Mutate Requests And Responses

Zuul

Make an API just for mobile

.5

Backend For Frontend

Tailor APIs to Mobile Experiences

Not A New Concept

Why?

RestRepresentational State Transfer

= Data

Imagine…

The most amazing movie app in the world

Lets Add A New Feature

Show nearby movie times

# Obtain a list of moviesGET /movies

# Obtain a list of nearby theatresGET /theatres?lat=…&long=…

# Obtain the showing times for a theatreGET /theatres/1234/times

server.makeMoviesRequest { (movieList, error) in

if error {

// handle error case

} else {

// handle success case

}

}

server.makeMoviesRequest { (movieList, error) in

if error {

// handle error case

} else {

// handle success case

}

}

server.makeTheatresRequest(lat,long) { (theatreList, error) in

if error {

// handle error case

} else {

// handle success case

}

}

var moviesRequestComplete: Bool = false

var theatresRequestComplete: Bool = false

server.makeMoviesRequest { (movieList, error) in

if error {

// handle error case

} else {

moviesRequestComplete = true

// do something with the data

}

}

server.makeTheatresRequest(lat,long) { (theatreList, error) in

if error {

// handle error case

} else {

theatresRequestComplete = true

// do something with the data

}

}

func makeInitialServerCalls () {

var moviesRequestComplete: Bool = false

var theatresRequestComplete: Bool = false

server.makeMoviesRequest { (movieList, error) in

if error {

// handle error case

} else {

moviesRequestComplete = true

// do something with the data

}

}

server.makeTheatresRequest(lat,long) { (theatreList, error) in

if error {

// handle error case

} else {

theatresRequestComplete = true

// do something with the data

}

}

}

func makeTheatreTimesRequest(for: theatres) {

for theatre in theatres {

server.makeTheatreTimesRequest(theatre.id) {

if error {

// handle error case

} else {

// process movie times

}

}

}

}

func makeInitialServerCalls () {

var moviesRequestComplete: Bool = false

var theatresRequestComplete: Bool = false

server.makeMoviesRequest { (movieList, error) in

if error {

// handle error case

} else {

moviesRequestComplete = true

self.movies = movieList

}

}

server.makeTheatresRequest(lat,long) { (theatreList, error) in

if error {

// handle error case

} else {

theatresRequestComplete = true

makeTheatreTimesRequest(for: theatreList)

}

}

}

func makeTheatreTimesRequest(for: theatres) {

let closestTheatres = theatres..3 // get 3 closest theatres

for theatre in closestTheatres {

if !requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {

break

}

}

}

func requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {

server.makeTheatreTimesRequest(theatre.id) {

if error {

// handle error case

} else {

// process movie times

}

}

}

func makeInitialServerCalls () {

var moviesRequestCompletedSucessfully: Bool = false

var theatresRequestComplete: Bool = false

server.makeMoviesRequest { (movieList, error) in

if error {

// handle error case

} else {

moviesRequestCompletedSucessfully = true

self.movies = movieList

}

}

server.makeTheatresRequest(lat,long) { (theatreList, error) in

if error {

// handle error case

layoutMovies()

} else {

theatresRequestComplete = true

if moviesRequestCompletedSuccessfully {

makeTheatreTimesRequest(for: theatreList)

}

}

}

}

func makeTheatreTimesRequest(for: theatres) {

let closestTheatres = theatres..3 // get 3 closest theatres

var theatreTimesAPIsFinished: Bool = false

for theatre in closestTheatres {

if !requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {

theatreTimesAPIsFinished = true

break

}

}

layoutMovies()

}

func requestTimesForTheatreAndReturnIfAnotherRequestShouldBeMade(theatre) {

server.makeTheatreTimesRequest(theatre.id) {

if error {

// handle error case

} else {

// process movie times

}

}

}

🚫

🙀

💩

Multiple Client Implementations

More Bugs

Error Scenarios Times Many

Release Dependent Changes

Release Dependent Experiments

Resource Based Apis Make Creating Experiences Difficult

Solution: Apis For Mobile Experiences

Logic Has To Live Somewhere

Easier To Release And Iterate

Makes Mobile Development Easier

Great Experiences

1. Keep It Consistent 2. Document Everything 3. Honor Thy Contracts 4. Insulate The App 5. Make Something Special

In Summary

Thank You!@micheletitolo

• https://unsplash.com/search/phone?photo=0VGG7cqTwCo

• https://unsplash.com/search/phone?photo=UGX2qdjdKkw

Photo Credits