Upload
michele-titolo
View
126
Download
0
Embed Size (px)
Citation preview
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